0

私はしばらくの間、この問題に取り組んできました。
libjpeg を使用してプログラムに JPEG サポートを追加しようとしています。
ほとんどの場合、かなりうまく機能していますが、一部の JPEG では、左の写真のように表示されます。

(元の画像と比較してください。)

明らかではないかもしれませんが、背景は赤、緑、青の行が交互に表示されます。誰かが以前にこの動作を見たことがあり、考えられる原因を知っている場合は、情報をいただければ幸いです。

行を 4 バイトの倍数になるようにパディングしましたが、問題はわずかに改善されました。

コード:

  rowSize = cinfo.output_width * cinfo.num_components;
  /* Windows needs bitmaps to be defined on Four Byte Boundaries */
  winRowSize = (rowSize + 3) & -4;
  imgSize = (cinfo.output_height * winRowSize + 3) & -4;
  while(cinfo.output_scanline < cinfo.output_height){
        jpeg_read_scanlines(&cinfo, &row_pointer, 1);

        /* stagger read to get lines Bottom->Top (As BMP Requires) */
        location = (imgSize) - (cinfo.output_scanline * winRowSize);
        rowsRead++;

        for(i = 0; i < winRowSize; i++){
           rawImage[location++] = row_pointer[i];
        }
     }

     /* Convert BGR to RGB */
     if(cinfo.num_components == 3){
        for(i = 0; i < imgSize; i += 3){
           tmp = rawImage[i+2];
           rawImage[i+2] = rawImage[i];
           rawImage[i] = tmp;
        }
     }

     biSize = sizeof(BITMAPINFOHEADER);
     if(cinfo.num_components == 1){ /* Greyscale */
        biPallete = 32 * 256;
        biSize += biPallete;
     }

     bitInf = (BITMAPINFO *)malloc(biSize);

     bitInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     bitInf->bmiHeader.biWidth = cinfo.output_width;
     bitInf->bmiHeader.biHeight = cinfo.output_height;
     bitInf->bmiHeader.biPlanes = 1;
     bitInf->bmiHeader.biBitCount = 8*cinfo.num_components;
     bitInf->bmiHeader.biCompression = BI_RGB;
     bitInf->bmiHeader.biSizeImage = 0;
     bitInf->bmiHeader.biXPelsPerMeter = 0;
     bitInf->bmiHeader.biYPelsPerMeter = 0;
     bitInf->bmiHeader.biClrUsed       = 0;
     bitInf->bmiHeader.biClrImportant  = 0;

     if(cinfo.num_components == 1){
        for(i = 0; i < 256; i++){
           bitInf->bmiColors[i].rgbBlue = i;
           bitInf->bmiColors[i].rgbGreen = i;
           bitInf->bmiColors[i].rgbRed = i;
           bitInf->bmiColors[i].rgbReserved = 0;
        }
     }

     /* Loads rawImage into an HBITMAP */
     /* retval = CreateDIBitmap(inDC, &bitInf->bmiHeader, CBM_INIT, rawImage, bitInf, DIB_RGB_COLORS); */
     retval = CreateCompatibleBitmap(inDC, cinfo.output_width, cinfo.output_height);
     errorCode = SetDIBits(inDC, retval, 0, cinfo.output_height, rawImage, bitInf, DIB_RGB_COLORS);

解決策: RGB/BGR コンバーターを次のように変更しました。

if(cinfo.num_components == 3){
   for(i = 0; i < cinfo.output_height; i++){
      location = (i * winRowSize);
      for(j = 0; j < rowSize; j += 3){
         tmp = rawImage[location+2];
         rawImage[location+2] = rawImage[location];
         rawImage[location] = tmp;
         location += 3;
      }
   }
}

そして、それは魅力のように機能しました。roygbivに感謝します。

4

4 に答える 4

1

左の画像の最も一般的な原因の 1 つは、適切に配置されていないバッファーです。

Windows は DWORD で整列されたバッファを期待していると思います。

上記のコードで見られる問題の 1 つは、実際のピクセルをコピーするために winRowSize を使用したくない、(画像の幅 * ピクセルあたりのバイト数) の変数を使用したいということです。winRowSize は、おそらく大きすぎる DWORD 整列サイズをコピーします (ただし、一部の画像はデフォルトで DWORD 整列に該当するため、機能する場合があります)。

for ループを変更します。

        for(i = 0; i < (width of the image * bytes per pixel); i++){ 
           rawImage[location++] = row_pointer[i]; 
        }

(rgb を bgr コードに調整する必要がある場合もあります。)

于 2010-03-26T01:55:44.720 に答える
0

RGB を意図した入力を受け取り、RGBA (24 ビットではなく 32 ビット ビットマップ) として扱っているようです。

于 2010-03-26T01:55:25.203 に答える
0

整数の DWORD を占めるようにピクセルの各行をパディングするのを忘れたのかもしれません。

于 2010-03-26T01:57:40.613 に答える
-1

おそらく、jpegの問題はrgbではなく、代わりにcmyk(またはグレースケール)です。すべての jpeg が RGB であるとは限りません。

PS、(はい、jpegは実際にはrgbではないことを知っています-代わりにyuvです。この答えをシンプルにしようとしています)

于 2010-03-26T02:11:16.530 に答える