1

FreeImage 3.15.4 ライブラリを使用して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;
    }
}
4

1 に答える 1

1

問題のある 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 );
}
于 2013-07-29T02:14:58.007 に答える