0

ネイティブ関数を使用して画像を読み取ろうとしています。そのために、私はこのコードを使用してみました:

        var result = new Bitmap((int)info.width,(int)info.height,PixelFormat.Format24bppRgb);
        var data = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
        bool success = ReadFullImage(data.Scan0, ref info, ref png);
        result.UnlockBits(data);
        if (!success)
            return null;
        else
        {
            return result;
        }

ここでinfo、は画像の高さと幅を含み、はラッパーでpngありpng_structReadFullImageはラッパーpng_read_imageです。ただし、アクセス違反が発生していました(例外コード0xc0000005)。

その後、私は値dataが保持されていることを調べました、私はこれを発見しました:

        data    {System.Drawing.Imaging.BitmapData} System.Drawing.Imaging.BitmapData
    Height  1557    int
        m_bmpdata   {Microsoft.AGL.Drawing.AGL_BITMAPDATA} Microsoft.AGL.Drawing.AGL_BITMAPDATA
    PixelFormat Format24bppRgb  System.Drawing.Imaging.PixelFormat
        Scan0   1638432 System.IntPtr
    Stride  1512    int
    Width   503 int

ここに一見問題があります。書き込まれている行のサイズは2012バイトですが、使用可能なのは1512のみであり、やがて割り当てられたメモリの外部で書き込みが試行されます。

問題は、フォーマットがピクセルあたり24ビットであるにもかかわらず、行のサイズが1512 = 503 * 3 + 3しかないのはなぜですか。また、十分なメモリを割り当ててビットマップにフィードするにはどうすればよいでしょうか。

あるいは、互換性のある方法でpngをlibpngで読み取ることはできますか?

更新:ReadFullImageはのDllImportです

extern "C" void read_image_full( unsigned char * buffer,pngImageInfo* info,pngDataStructures* png)
{
    png_bytepp  row_pointers = new png_bytep[info->height];
    for (unsigned int i = 0;  i < info->height;  ++i)
        row_pointers[i] = buffer + i*info->rowbytes;
    png_read_image(png->png_struct_field, row_pointers);
    return true;
}

そして、rowbytesはpng_get_rowbytesを介して取得されます。

4

1 に答える 1

2

まず、私の知る限り、24/8 = 3、つまり503*(24/8)=1509であり、ストライド値は正しいです。

もう 1 つのことは、png_read_imageがポインターの配列を使用し、Scan0がポインターの配列ではないことです。これは、png_read_imageScan0からデータを読み取り(ただし書き込み専用)、このデータをポインターとして解釈することを意味します。

以下を試すことができます(テストされていません)。ReadFullImageの最初のパラメーターを変更する必要があります(現在はint[]になります)。

var result = new Bitmap((int)info.width,(int)info.height,PixelFormat.Format24bppRgb);
var data = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
int y, ptr = data.Scan0.ToInt32();
int[] lines = new int[result.Height];
for (y = 0; y < lines.Length; y++)
{
    lines[y] = ptr;
    ptr += data.Stride;
}
bool success = ReadFullImage(lines, ref info, ref png);
result.UnlockBits(data);
if (!success)
    return null;
else
{
    return result;
}

これは32 ビットアプリケーションであると想定しています。

于 2012-10-30T08:51:30.180 に答える