FreeImage:FreeImage_GetBits访问的像素数据不正确(数据+大小)

时间:2013-07-26 09:06:52

标签: c++ image-processing png freeimage

我正在使用FreeImage 3.15.4 library来分析PNG图像。我基本上试图构建一个简单的数据结构,包括所有颜色的调色板以及由像素组成的每像素数据的数组版本。

问题是FreeImage_GetBits似乎正在返回指向无效数据的指针,我不知道为什么。我能够正确读取PNG文件的宽度和高度,但FreeImage_GetBits指向的数据只是垃圾数据,看起来有些奇怪。无论我运行多少次程序,它都会在同一个地方死掉,当下面代码中的iPix等于131740时。我在std :: find调用中访问位[131740]时出现C0000005错误。实际和报告的PNG图像大小为524288。

此外,我已经尝试使用我自己构建的较小图像的代码,并且它们工作正常。我正在使用的PNG是我的第三方,并且似乎没有任何损坏(Photoshop打开它,DirectX可以正常处理和使用它)

有什么想法吗?

这是数据声明:

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

这是执行颜色索引的代码:

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

1 个答案:

答案 0 :(得分:1)

有问题的PNG图像使用索引颜色模式,原始像素数据确实返回为8bpp。正确的做法是将此数据视为每像素8位,并将每个8位值视为可以使用FreeImage_GetPalette检索的颜色调色板的索引。替代方案是我最终做出的选择,就是在这些索引颜色模式PNG图像上调用FreeImage_ConvertTo32Bits,然后通过与相同32位图像格式相同的代码路径传递所有内容。

非常简单的转换,但现在是:

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