在不安全的上下文中编辑位图 - 如何避免不稳定?

时间:2009-04-03 18:50:25

标签: c# interop bitmap rendering unsafe

我正在尝试在不安全的上下文中使用位图,并且看到不稳定,例如,程序第一次运行但第二次失败。这是代码:

private static void RenderBitmap(Graphics g)
{
  const int width = 150, height = 150;
  using (Bitmap bmp = new Bitmap(width, height, 
    System.Drawing.Imaging.PixelFormat.Format24bppRgb))
  {
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    System.Drawing.Imaging.BitmapData bmpData =
      bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, 
        bmp.PixelFormat);
    NativeMethods.RenderText(Graphics.FromImage(bmp).GetHdc(), bmpData.Scan0,
      "This works only first time round", "Segoe", 10, 
      new RGBA(255, 0, 0, 255), width, height);
    bmp.UnlockBits(bmpData);
    g.DrawImage(bmp, new Rectangle(width, height, width, -height));
  }
}

看到这不起作用,我有几个问题。如果本地RenderText方法直接操作位图内存,那么我的安全和正确吗?我从位图中获取HDC的方法是正确的,还是应该使用从绘图方法传递的参数g

我得到的错误是:

  

System.AccessViolationException是   未处理的消息=“尝试阅读   或写保护的内存。这是   经常表明其他记忆   是腐败的。“

3 个答案:

答案 0 :(得分:3)

NativeMethods.RenderRext方法不能安全地处理位图数据,因为它不知道位图的扫描线有多宽,以及它是否颠倒存储在内存中。症状表明该方法是在位图外部写入内存,覆盖应用程序中需要的其他内容。

BitmapData.Stride属性具有该方法处理数据所需的信息。它包含以字节为单位的扫描线宽度,如果为负,则表示位图在内存中上下颠倒存储。 Simply Scan0是第一条扫描线的地址,Scan0 + Stride是第二条扫描线的地址。

答案 1 :(得分:1)

也许这是一个愚蠢的问题,但为什么不使用.NET附带的TextRenderer类而不是使用p / invoke?

TextRenderer::DrawText Method (IDeviceContext, String, Font, Point, Color)

http://msdn.microsoft.com/en-us/library/4ftkekek.aspx

-Oisin

答案 2 :(得分:1)

好吧,经过多次痛苦和痛苦之后,我找到了一个解决方案:我没有传入要填充的内存缓冲区,而是传递了一个设备上下文(HDC)来渲染。到目前为止似乎工作!

感谢所有回答的人。