0

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;

}

なにが問題ですか ??

ここにYUV画像があります

4

2 に答える 2

1

提供される画像ファイル (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);
}

jpeg_start_compress() と jpeg_finish_compress() の間に配置すると、色空間変換なしで JPEG ファイルが正しく作成されます (ただし、アップサンプリングあり)。

jason_s のコードも正しいように見えます

于 2014-01-21T16:36:18.960 に答える
0

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;
于 2013-06-11T00:37:11.430 に答える