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包含图像的高度和宽度,pngispng_structReadFullImageis wrapper around 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 字节可用,不久之后就会在分配的内存之外进行写入尝试。

问题是,为什么行的大小只有 1512=503*3+3,尽管格式是每像素 24 位,以及如何分配足够的内存并将其馈送到位图中?

或者,可以以兼容的方式使用 libpng 读取 png 吗?

更新: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;
}

并且通过 png_get_rowbytes 检索行字节。

4

1 回答 1

2

首先,据我所知,24/8 = 3,所以503*(24/8)=1509,那么Stride值是正确的。

另一件事是png_read_image使用指针数组,而Scan0不是指针数组。这意味着png_read_image正在从Scan0读取数据(但它是只写的)并将此数据解释为指针。

您可以尝试以下(未测试)。您需要修改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 回答