【问题标题】:weird image while trying to compress YUV image to jpeg using libjpeg尝试使用 libjpeg 将 YUV 图像压缩为 jpeg 时出现奇怪的图像
【发布时间】:2013-06-06 10:03:21
【问题描述】:

我正在使用 Qt、OpenCV 和 libJpeg 压缩 YUV422 图像,但输出不正确。

如果我将 yuv 转换为 rgb 然后压缩,我会得到正确的输出,但我知道 Jpeg 在内部使用 YUV,这就是我想要删除冗余的原因。

这是我的代码:

bool ipl2jpeg(IplImage *frame, unsigned char **outbuffer, long unsigned int *outlen) {
    unsigned char *outdata = (uchar *) frame->imageData;
    struct jpeg_compress_struct cinfo ;
    struct jpeg_error_mgr jerr;
    JSAMPROW row_ptr[1];
    int row_stride;

    *outbuffer = NULL;
    *outlen = 0;

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_mem_dest(&cinfo, outbuffer, outlen);

    cinfo.image_width = frame->width;
    cinfo.image_height = frame->height;
    cinfo.input_components = frame->nChannels;
    cinfo.in_color_space = JCS_YCbCr;

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality (&cinfo,100 , true);
    jpeg_start_compress(&cinfo, TRUE);
    row_stride = frame->width *2;// frame->nChannels;

    while (cinfo.next_scanline < cinfo.image_height) {
        /* jpeg_write_scanlines expects an array of pointers to scanlines.
         * Here the array is only one element long, but you could pass
         * more than one scanline at a time if that's more convenient.
         */
        row_ptr[0] = &outdata[cinfo.next_scanline * row_stride];
        (void) jpeg_write_scanlines(&cinfo, row_ptr, 1);
      }

    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);

    return true;

}

怎么了??

Here is the YUV image

【问题讨论】:

    标签: c++ c qt opencv jpeg


    【解决方案1】:

    我认为 libjpeg 不会接受二次采样的图像数据作为输入。因此,您必须先对其进行去子采样。

    您可以分配一个临时行缓冲区,并转换每一行,如下所示:

    for (i=0; i<frame->width; i++) {
        tmpbuf[i*3+0] = outdata[cinfo.next_scanline * row_stride + i*2];
        tmpbuf[i*3+1] = outdata[cinfo.next_scanline * row_stride + (i-i%2)*2+1];
        tmpbuf[i*3+2] = outdata[cinfo.next_scanline * row_stride + (i-i%2)*2+3];
    }
    row_ptr[0] = tmpbuf;
    

    【讨论】:

      【解决方案2】:

      提供的图片文件 (frame-3.raw) 是 640x480 的 YUYV 格式

      以下代码

      JSAMPROW row_pointer[1];
      row_pointer[0] = row_buf;
      while (cinfo.next_scanline < cinfo.image_height) {
          unsigned i, j;
          unsigned offset = cinfo.next_scanline * cinfo.image_width * 2;
          for (i = 0, j = 0; i < cinfo.image_width*2; i += 4, j += 6) {
              row_buf[j + 0] = buf[offset + i + 0]; // Y
              row_buf[j + 1] = buf[offset + i + 1]; // U
              row_buf[j + 2] = buf[offset + i + 3]; // V
              row_buf[j + 3] = buf[offset + i + 2]; // Y
              row_buf[j + 4] = buf[offset + i + 1]; // U
              row_buf[j + 5] = buf[offset + i + 3]; // V
          }        
          jpeg_write_scanlines(&cinfo, row_pointer, 1);
      }
      

      在 jpeg_start_compress() 和 jpeg_finish_compress() 之间可以正确创建 JPEG 文件,无需颜色空间转换(但有上采样)

      jason_s 的代码看起来也正确

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-22
        • 2013-06-04
        • 2012-03-29
        • 1970-01-01
        • 2010-09-22
        • 1970-01-01
        相关资源
        最近更新 更多