Chinaunix首页 | 论坛 | 博客
  • 博客访问: 530587
  • 博文数量: 70
  • 博客积分: 3162
  • 博客等级: 中校
  • 技术积分: 850
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-23 13:30
文章分类
文章存档

2013年(1)

2012年(4)

2011年(1)

2010年(7)

2009年(9)

2008年(20)

2007年(3)

2006年(25)

分类: LINUX

2008-12-04 10:42:05

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

#include
#include
#include
#include

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;
}

阅读(4370) | 评论(5) | 转发(0) |
给主人留下些什么吧!~~

linux_fan20132013-08-02 13:59:22

输出当然也可以是yuv,没必要转化,设置下参数即可,注意一般默认的是yuv411,不是我们常用的yuv420,

===============》 你写的程序真的很不错。但至于上面的这句话,我还真是看的不太明白。 
1. libjpeg解码后输出的默认是YUV411 (out_color_space设置为YCbCr ) ,你确定吗?  

2. 你的程序是在输出YUV411 吧?

linux_fan20132013-07-31 19:33:44

你好,LZ。 请问您的程序经过测试,确认正确了吗?

我也是用的libjpeg,并且套用您的方式去生成YUV420SP的数据,
可是发现数据不对啊。。

能否指点一二?

多谢多谢 

zdj14142013-06-13 00:04:07

楼主,再请教一下,
chromaWidth = width / 2;
 chromaHeight = height / 2;
这个表示420还是411?420和411这个地方分别怎么写?

qwdu2013-05-27 15:25:05

fallseven:lz。我是新手。。。有个问题想请教一下。。。我看维基百科里面说jpeg一般是4:4:4、4:2:2和4:2:0。没有提到411格式的。。。还有就是。程序我还没太看明白。。。代码里面那一部分是体现到底是420还是411格式的呢?。。。好多年前的帖了希望lz如果看到的话能帮忙回答一下。。。跪谢~

chromaWidth = width / 2;
    chromaHeight = height / 2;
这里体现的

回复 | 举报

fallseven2013-05-02 12:03:13

lz。我是新手。。。有个问题想请教一下。。。我看维基百科里面说jpeg一般是4:4:4、4:2:2和4:2:0。没有提到411格式的。。。还有就是。程序我还没太看明白。。。代码里面那一部分是体现到底是420还是411格式的呢?。。。好多年前的帖了希望lz如果看到的话能帮忙回答一下。。。跪谢~