jpeg6b直接解码yuv

来源:互联网 发布:火车采集软件 编辑:程序博客网 时间:2024/06/05 18:25
我看到网络上有些人用jpeg6b解码输出yuv,用这样的方法:先解码成rgb,然后再转换成yuv,觉得很奇怪,一是这样增加了开销,色彩空间转化rgb->yuv一般比较耗费时间,尤其在嵌入式平台上都用查表法或者对应平台的汇编去优化;二是数据损失。其实jpeg本身的编码就是yuv输入,输出当然也可以是yuv,没必要转化,设置下参数即可,注意一般默认的是yuv411,不是我们常用的yuv420,不过这个只是排列组合下,不会消耗多少资源。

#include <stdlib.h>
#include <string.h>
#include <jpeglib.h>
#include <setjmp.h>

struct my_error_mgr {
    struct jpeg_error_mgr pub;  /* "public" fields */

    jmp_buf setjmp_buffer;  /* for return to caller */
};

typedef struct my_error_mgr * my_error_ptr;

void my_error_exit (j_common_ptr cinfo)
{
    /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
    my_error_ptr myerr = (my_error_ptr) cinfo->err;

    /* Always display the message. */
    /* We could postpone this until after returning, if we chose. */
    (*cinfo->err->output_message) (cinfo);

    /* Return control to the setjmp point */
    longjmp(myerr->setjmp_buffer, 1);
}
int decode_jpeg_file (const char *srcfile, const char *optfile)
{
    struct jpeg_decompress_struct cinfo;
    struct my_error_mgr jerr;
    FILE *infile, *outfile;
    JSAMPARRAY buffer;      /* Output row buffer */
    int row_stride;     /* physical row width in output buffer */

    int finished = 1;
    int chromaWidth, chromaHeight;
    int yMask,xMask;

    int x,y;
    int width,height;

    unsigned char *pixels,*rgbPixels, *src;
                                                                                                           1,11         顶章   unsigned char *yPixels, *uPixels, *vPixels;
    unsigned char *yPtr, *uPtr, *vPtr;

    if ((infile = fopen(srcfile, "rb")) == NULL) {
    fprintf(stderr, "Can't open %s\n", srcfile);
    return -1;
    }
    if ((outfile = fopen(optfile, "wb")) == NULL) {
    fprintf(stderr, "Can't open %s\n", optfile);
    return -1;
    }

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    if (setjmp(jerr.setjmp_buffer)) {
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    return -1;
    }
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, infile);
    (void) jpeg_read_header(&cinfo, TRUE);

    /*set parameters for decompression */
    cinfo.out_color_space = JCS_YCbCr;

    (void) jpeg_start_decompress(&cinfo);

    width  = cinfo.output_width;
    height = cinfo.output_height;

    pixels = (unsigned char *)malloc(width*height*3);
    memset(pixels, 0, width * height * 3);

    src = rgbPixels = pixels;

    /* JSAMPLEs per row in output buffer */
    row_stride = cinfo.output_width * cinfo.output_components;
    /* Make a one-row-high sample array that will go away when done with image */
    buffer = (*cinfo.mem->alloc_sarray)
    ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
    while (cinfo.output_scanline < cinfo.output_height) {
    int num_rows = jpeg_read_scanlines(&cinfo, buffer, 1);
    if (num_rows == 0) {
        finished = 0;
        break;
    }
    if (cinfo.output_components == 1) {        // greyscale
        unsigned int i;
        unsigned char *in = (unsigned char *)(*buffer);
        for (i = 0; i < width * num_rows; ++i) {
        *pixels++ = *in; // red
        *pixels++ = *in; // green
        *pixels++ = *in; // blue
        ++in;
        }
    } else if (cinfo.output_components == 3) { // RGB
        memcpy(pixels, (*buffer), num_rows * width * 3);
        pixels += num_rows * width * 3;
    }
    }

    chromaWidth = width / 2;
    chromaHeight = height / 2;
    yMask = xMask = 1;

    yPixels = (unsigned char*)malloc(height * width);
    uPixels = (unsigned char*)malloc(chromaWidth * chromaHeight);
    vPixels = (unsigned char*)malloc(chromaWidth * chromaHeight);

    yPtr = yPixels;
    uPtr = uPixels;
    vPtr = vPixels;

    for(y = 0; y < height; y++)
    {
    for(x = 0; x < width; x++)
    {
        *yPtr++ = *rgbPixels++;
        if((y & yMask) == 0 && (x & xMask) == 0){
        *uPtr++ = *rgbPixels++;
        *vPtr++ = *rgbPixels++;
        }
        else
        rgbPixels += 2;
    }
    }
    if(finished){
    (void) jpeg_finish_decompress(&cinfo);
    }
    jpeg_destroy_decompress(&cinfo);
    fwrite(yPixels, 1, width * height, outfile);
    fwrite(uPixels, 1, chromaWidth * chromaHeight, outfile);
    fwrite(vPixels, 1, chromaWidth * chromaHeight, outfile);

    fclose(infile);
    fclose(outfile);

    free(yPixels);
    free(uPixels);
    free(vPixels);
    free(src);

    return 0;
}

int main(int argc, char **argv)
{
    if(argc != 3){
    printf("Usage:%s inputfile.jpg outputfile\n",argv[0]);
    return -1;
    }
    decode_jpeg_file(argv[1],argv[2]);

    return 0;
}
原创粉丝点击