2013-07-26 3 views
1

J'utilise le FreeImage 3.15.4 library pour analyser les images PNG. Essentiellement, je tente de construire une structure de données simple composée d'une palette de toutes les couleurs ainsi que d'une version de tableau de l'image par pixel composée d'index dans la palette. Le FreeImage_GetBits semble renvoyer un pointeur vers des données non valides et je ne sais pas pourquoi. Je suis capable de lire la largeur et la hauteur du fichier PNG correctement, mais les données pointées par FreeImage_GetBits sont juste des données de vidage, et semblent être d'une taille impaire. Peu importe combien de fois je lance le programme, il meurt constamment au même endroit, quand iPix dans le code ci-dessous est égal à 131740. J'obtiens une erreur C0000005 accédant aux bits [131740] dans l'appel std :: find. La taille d'image PNG réelle et rapportée est 524288.FreeImage: Les données de pixels accédées par FreeImage_GetBits ne sont pas correctes (données + taille)

En outre, j'ai essayé ce code avec des images plus petites que j'ai moi-même construites et elles fonctionnent bien. Le PNG que j'utilise est fourni à un tiers, et ne semble pas corrompu de toute façon (Photoshop l'ouvre, et DirectX peut le traiter et l'utiliser normalement)

Des idées?

est ici les déclarations de données:

struct Color 
{ 
    char b; // Blue 
    char g; // Green 
    char r; // Red 
    char a; // Alpha value 

    bool operator==(const Color& comp) 
    { 
     if (a == comp.a && 
      r == comp.r && 
      g == comp.g && 
      b == comp.b) 
      return TRUE; 
     else 
      return FALSE; 
    } 
}; 

typedef std::vector<Color> ColorPalette; // Array of colors forming a palette 

Et voici le code qui fait l'indexation des couleurs:

// Read image data with FreeImage 
unsigned int imageSize = FreeImage_GetWidth(hImage) * FreeImage_GetHeight(hImage); 

unsigned char* pData = new unsigned char[imageSize]; 

// Access bits via FreeImage 
FREE_IMAGE_FORMAT fif; 
FIBITMAP* hImage; 
fif = FreeImage_GetFIFFromFilename(fileEntry.name.c_str()); 
if(fif == FIF_UNKNOWN) 
{ 
    return false; 
} 
hImage = FreeImage_Load(fif, filename); 
BYTE* pPixelData = NULL; 
pPixelData = FreeImage_GetBits(hImage); 
if (pPixelData == NULL) 
{ 
    return false; 
} 

Color* bits = (Color*)pPixelData; 
ColorPalette palette; 

for (unsigned int iPix = 0; iPix < imageSize; ++iPix) 
{ 
    ColorPalette::iterator it; 

    if((it = std::find(palette.begin(), palette.end(), bits[iPix])) == palette.end()) 
    { 
     pData[iPix] = palette.size(); 
     palette.push_back(bits[iPix]); 
    } 
    else 
    { 
     unsigned int index = it - palette.begin(); 
     pData[iPix] = index; 
    } 
} 
+0

Etes-vous sûr que le format des données de pixel brut correspond à la structure? Que faire si l'ordre des octets est différent? Que faire si le compilateur décide d'ajouter un remplissage à votre structure? –

+0

En outre, si vous essayez d'accéder à 'bits [524288]' et le nombre d'entrées dans 'bits' est 524288, alors vous accédez hors limites que l'index supérieur devrait être 524287. –

+1

Désolé, ce fut une faute de frappe. Il échoue à 'bits [131740]', en fait. Je vais devoir réexaminer les données, puisque 131740 est étrangement proche de 524288/4 (8bpp au lieu de 32bpp peut-être?). J'ai vérifié le format de données retourné par ma plus petite image de test et j'ai élaboré le code pour traiter ce format; il ne m'est pas venu à l'esprit que le format différerait entre les types de fichiers. Comment FreeImage décide-t-il du format dans lequel stocker les données internes? – 8bitcartridge

Répondre

1

Les images PNG qui étaient problématiques ont été en utilisant des modes de couleurs indexées et les données de pixel brut a été en effet étant retourné comme 8bpp. Le traitement correct consistait à traiter ces données sur 8 bits par pixel et à traiter chaque valeur de 8 bits comme un index dans une palette de couleurs pouvant être récupérée à l'aide de FreeImage_GetPalette. L'alternative, qui est le choix que j'ai finalement fait, était d'appeler FreeImage_ConvertTo32Bits sur ces images PNG en mode couleur indexées, et de passer ensuite tout par le même chemin de code que le même format d'image 32 bits.

conversion assez simple, mais la voici:

// Convert non-32 bit images 
if (FreeImage_GetBPP(hImage) != 32) 
{ 
    FIBITMAP* hOldImage = hImage; 
    hImage = FreeImage_ConvertTo32Bits(hOldImage); 
    FreeImage_Unload(hOldImage); 
} 
Questions connexes