I'm using the FreeImage 3.15.4 library to analyze PNG images. I'm basically trying to build a simple data structure of consisting of a palette of all colors as well as an array version of the image per-pixel data consisting of indexes into the palette.
The thing is that FreeImage_GetBits seems to be returning a pointer to invalid data and I'm not sure why. I am able to read the width and height of the PNG file correctly, but the data pointed to by FreeImage_GetBits is just garbage data, and appears to be of an odd size. No matter how many times I run the program, it consistently dies in the same place, when iPix in the code below is equal to 131740. I get a C0000005 error accessing bits[131740] in the std::find call. The actual and reported PNG image size is 524288.
Furthermore, I've tried this code with smaller images that I myself have built and they work fine. The PNG I'm using is provided my a third party, and does not appear to be corrupt in anyway (Photoshop opens it, and DirectX can process and use it normally)
Any ideas?
Here's the data declarations:
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
And here's the code that does the color indexing:
// 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;
}
}
bits[524288]and the number of entries inbitsis 524288, then you are accessing out of bounds as the top index should be 524287. - Some programmer dudebits[131740], actually. I'll have to investigate the data again, since 131740 is suspiciously close to 524288 / 4 (8bpp instead of 32bpp perhaps?). I checked the data format returned by my smaller test image and worked out the code to process that format; it hadn't occurred to me that the format would differ between file types. How does FreeImage decide what format to store the internal data in? - 8bitcartridge