【问题标题】:BitmapData size in windows mobileWindows Mobile 中的 BitmapData 大小
【发布时间】:2012-10-19 12:24:15
【问题描述】:

我正在尝试使用本机函数读取图像。为此,我尝试使用此代码:

        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 包含图像的高度和宽度,pngpng_structReadFullImagepng_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 检索行字节。

【问题讨论】:

    标签: c# bitmap windows-mobile bitmapdata libpng


    【解决方案1】:

    据我所知,第一件事,24/8 = 3,所以 503*(24/8)=1509,然后是 步幅 值正确。

    另一件事是 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 位 应用程序。

    【讨论】:

    • 我知道 png_read_image 接受一个指针数组(请参阅使用包装器代码更新),但正如您所指出的,24/8 确实是 3(其他 3 个字节应该是填充,看到行必须能被 4)) 整除,而且很可能,我在基本的 aryphmethics 和在 .NET 代码和 libpng 中类似地设置像素格式都失败了。
    • 如果 libpng 需要 2012 字节来读取 503 像素行,我认为您应该使用 PixelFormat.Format32bppRgb 或逐行解码(使用 png_read_row ) 但它可能很棘手......
    • 好吧,我使用 libpng 的全部目的是使用 png_read_row 并逐行读取它;将格式更改为每像素 32 位就像一个魅力。
    猜你喜欢
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 2013-07-15
    • 1970-01-01
    相关资源
    最近更新 更多