簡體   English   中英

C:WinAPI CreateDIBitmap()來自byte []問題

[英]C: WinAPI CreateDIBitmap() from byte[] problem

我已經在這個問題上工作了一段時間了。
我正在嘗試使用libjpeg向程序添加JPEG支持。
在大多數情況下,它工作得很好,但是對於某些JPEG,它們的顯示方式類似於左側的圖片。

(與原始圖像比較。)

可能並不明顯,但是背景顯示為紅色,綠色和藍色交替的行。 如果有人以前見過這種行為並知道可能的原因,我將不勝感激。

我將行填充為四個字節的倍數,這對問題沒有多大幫助。

碼:

  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

左圖像的最常見原因之一是緩沖區未正確對齊。

我相信Windows期望使用DWORD對齊的緩沖區。

我在上面的代碼中看到的一個問題是,您不想使用winRowSize復制實際像素,而是想使用一個變量,其變量為(圖像寬度*每個像素的字節數)。 winRowSize復制DWORD對齊的大小,該大小可能太大(盡管默認情況下某些圖像可能因為DWORD對齊而可以工作)。

更改for循環:

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

(您可能還需要將rgb調整為bgr代碼。)

看起來您正在接收本應為RGB的輸入,並將其視為RGBA(32位位圖,而不是24位)。

也許您忘了填充每行像素以占據整數倍的DWORD。

也許問題jpeg不是rgb,而是cmyk(甚至是灰度)。 並非所有的jpeg都是rgb。

PS,(是的,我知道jpeg實際上不是rgb-而是yuv,只是試圖使這個答案簡單)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM