Я использую Библиотека FreeImage 3.15.4 анализировать изображения PNG. Я в основном пытаюсь построить простую структуру данных, состоящую из палитры всех цветов, а также версию массива данных изображения на пиксель, состоящую из индексов в палитре.
Дело в том, что FreeImage_GetBits
кажется, возвращает указатель на недопустимые данные, и я не уверен, почему. Я могу правильно прочитать ширину и высоту файла PNG, но данные, на которые указывает FreeImage_GetBits
это просто данные мусора, и, кажется, имеет нечетный размер. Независимо от того, сколько раз я запускаю программу, она постоянно умирает в одном и том же месте, когда iPix
в приведенном ниже коде равно 131740. Я получаю ошибку C0000005 при доступе к битам [131740] в вызове std :: find. Фактический и заявленный размер изображения 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;
}
}
В проблемных PNG-изображениях использовались индексированные цветовые режимы, а необработанные пиксельные данные действительно возвращались как 8bpp. Правильный порядок действий заключался в том, чтобы обрабатывать эти данные как 8 бит на пиксель, и каждое 8-битное значение обрабатывать как индекс в палитре цветов, которые можно получить с помощью FreeImage_GetPalette
, Альтернативой, которую я в конечном итоге сделал, было призвать FreeImage_ConvertTo32Bits
на этих изображениях PNG с индексированным цветным режимом, а затем пропускают все по тому же пути кода, что и тот же 32-битный формат изображения.
Довольно простое преобразование, но вот оно:
// Convert non-32 bit images
if ( FreeImage_GetBPP( hImage ) != 32 )
{
FIBITMAP* hOldImage = hImage;
hImage = FreeImage_ConvertTo32Bits( hOldImage );
FreeImage_Unload( hOldImage );
}
Других решений пока нет …