C++ 尝试使用libjpeg将YUV图像压缩为jpeg时出现奇怪的图像
我使用Qt、OpenCV和libJpeg压缩YUV422图像,但输出不正确 如果我将yuv转换为rgb,然后进行压缩,我会得到正确的输出,但据我所知,Jpeg在内部使用yuv,这就是为什么我想消除冗余 这是我的密码:C++ 尝试使用libjpeg将YUV图像压缩为jpeg时出现奇怪的图像,c++,c,qt,opencv,jpeg,C++,C,Qt,Opencv,Jpeg,我使用Qt、OpenCV和libJpeg压缩YUV422图像,但输出不正确 如果我将yuv转换为rgb,然后进行压缩,我会得到正确的输出,但据我所知,Jpeg在内部使用yuv,这就是为什么我想消除冗余 这是我的密码: bool ipl2jpeg(IplImage *frame, unsigned char **outbuffer, long unsigned int *outlen) { unsigned char *outdata = (uchar *) frame->imag
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;
}
bool ipl2jpeg(IplImage*帧,无符号字符**exputffer,长无符号int*outlen){
无符号字符*outdata=(uchar*)帧->图像数据;
结构jpeg\u压缩\u结构cinfo;
结构jpeg\u错误\u管理器jerr;
JSAMPROW row_ptr[1];
int row_跨步;
*exputffer=NULL;
*outlen=0;
cinfo.err=jpeg\u std\u error(&jerr);
jpeg\u创建\u压缩(&cinfo);
jpeg文件目的地(&cinfo、Exputfer、outlen);
cinfo.image_width=帧->宽度;
cinfo.image_height=帧->高度;
cinfo.input\u components=框架->通道;
cinfo.in_color_space=JCS_YCbCr;
jpeg\u set\u默认值(&cinfo);
jpeg设置质量(&cinfo,100,真);
jpeg\u start\u compress(&cinfo,TRUE);
行步长=帧->宽度*2;//帧->通道;
while(cinfo.next\u扫描线
怎么了
我认为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;
(i=0;iwidth;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];
}
行_ptr[0]=tmpbuf;
提供的图像文件(frame-3.raw)是YUYV格式的640x480
下面的代码
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);
}
JSAMPROW行_指针[1];
行指针[0]=行指针;
while(cinfo.next\u扫描线
介于jpeg_start_compress()和jpeg_finish_compress()之间可以正确创建jpeg文件,而无需进行颜色空间转换(但需要进行上采样)
jason_的代码看起来也正确