2010-03-26 16 views
0

Je travaille sur ce problème depuis un moment maintenant.
J'essaye d'ajouter le support de JPEG à un programme avec libjpeg.
Pour la plupart, il fonctionne assez bien, mais pour certains fichiers JPEG, ils apparaissent comme l'image sur la gauche.C: WinAPI CreateDIBitmap() de byte [] problème

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

Il ne peut pas être évident, mais l'arrière-plan apparaît avec une alternance de lignes vertes et bleues rouges. Si quelqu'un a déjà vu ce comportement et connaît une cause probable, j'apprécierais toute contribution. J'ai rembourré les lignes pour être des multiples de quatre octets, et cela n'a aidé que légèrement le problème.

code:

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); 

Solution: J'ai changé le convertisseur RGB/BGR à ceci:

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; 
     } 
    } 
} 

Et cela a fonctionné comme un charme. Merci à roygbiv.

+0

affichage Peut-être un extrait de code pourrait nous aider à diagnostiquer votre problème. –

+0

poster un lien vers le problème origianl jpeg pourrait aussi être utile – SteelBytes

Répondre

1

L'une des causes les plus courantes de l'image de gauche est un tampon qui n'est pas correctement aligné. Je crois que Windows attend un tampon aligné DWORD.

Un problème que je vois avec le code ci-dessus est que vous ne voulez pas utiliser winRowSize pour copier les pixels réels, vous voulez utiliser une variable avec la (largeur de l'image * octets par pixel). copies winRowSize la taille aligné DWORD qui est probablement trop grand

de changement de la boucle (bien que certaines images peuvent travailler comme ils tombent sur l'alignement DWORD par défaut.):

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

(Vous pouvez également avoir à régler le code rgb to bgr.)

+0

Vous m'avez battu de 1 minute mais vous avez oublié de mentionner que l'alignement DWORD est nécessaire pour chaque ligne non seulement pour le début du tampon. –

+0

Merci pour cette prise, Mais cela n'a pas résolu mon problème. – zmbush

+0

Merci. J'ai corrigé le convertisseur RGB/BGR. – zmbush

0

Il semble que vous preniez une entrée destinée à être RVB et la traitant comme RGBA (bitmap 32 bits au lieu de 24 bits).

0

Peut-être avez-vous oublié de remplir chaque rangée de pixels pour occuper un nombre entier de DWORD.

+0

Je l'ai fait. Cela m'a aidé à déplacer chaque ligne, mais pas le problème de couleur. – zmbush

-1

peut-être que le problème jpeg n'est pas rgb, mais c'est plutôt cmyk (ou même en niveaux de gris). pas tous les jpeg sont RVB.

PS, (oui je sais jpegs ne sont pas réellement rgb - sont yuv à la place, juste essayer de garder cette simple réponse)