2010-03-26 6 views
0

지금 당분간이 문제를 해결하고 있습니다.
libjpeg가있는 프로그램에 JPEG 지원을 추가하려고합니다.
대부분의 경우 상당히 잘 작동하지만 일부 JPEG의 경우 왼쪽 그림처럼 표시됩니다. C : WinAPI CreateDIBitmap() from byte [] 문제

Original Image http://www.recipehawk.com/media/failsample.png

그것은 분명하지 않을 수도 있지만, 배경은 적색, 녹색, 청색의 행을 번갈아 나타난다. 누군가가 이전에 이러한 행동을 보았고 가능한 원인을 알고 있다면, 나는 모든 의견을 고맙게 생각합니다.

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에게 감사드립니다.

+0

어쩌면 우리가 문제를 진단하는 데 유용한 코드를 게시. –

+0

origianl 문제 jpeg에 대한 링크를 게시하는 것도 유용 할 수 있습니다. – SteelBytes

답변

1

왼쪽 이미지의 가장 일반적인 원인 중 하나는 올바르게 정렬되지 않은 버퍼입니다.

Windows에서 DWORD로 정렬 된 버퍼가 필요하다고 생각합니다.

위의 코드에서 볼 수있는 한 가지 문제점은 winRowSize를 사용하여 실제 픽셀을 복사하지 않으려는 경우, 변수를 픽셀 당 이미지 너비 * 바이트로 사용하고 싶다는 것입니다. winRowSize 사본 아마 너무 큰 인 DWORD 정렬 크기는 루프

변경 (그들은 기본적으로 DWORD 정렬에 가을 일부 이미지가 작동 할 수 있지만합니다.) :

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

은 (또한 조정해야 할 수도 rgb에서 bgr 코드까지)

+0

1 분이 지났지 만 버퍼 시작 부분뿐만 아니라 각 행에 DWORD 정렬이 필요하다는 것을 잊었습니다. –

+0

그 고마워,하지만 내 문제를 해결하지 못했습니다. – zmbush

+0

감사합니다. RGB/BGR 변환기를 수정했습니다. – zmbush

0

RGB로 입력하고 RGBA (24 비트 대신 32 비트 비트 맵)로 취급하는 것처럼 보입니다.

0

정수 값의 DWORD를 차지하도록 각 행 픽셀을 채우는 것을 잊어 버린 것일 수 있습니다.

+0

나는 그것을했다. 각 줄이 이동했지만 컬러 문제는 해결되지 않았습니다. – zmbush

-1

아마 jpeg가 rgb가 아니지만 대신 cmyk (또는 그레이 스케일) 일 수 있습니다. 모든 jpeg가 rgb가 아닙니다.

PS는 (그래, 난 사진과 실제로 RGB하지 알고있다 - 대신 YUV입니다, 그냥이 대답을 간단하게 유지하려고)