我正在尝试在不安全的上下文中使用位图,并且看到不稳定,例如,程序第一次运行但第二次失败。这是代码:
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是 未处理的消息=“尝试阅读 或写保护的内存。这是 经常表明其他记忆 是腐败的。“
答案 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)来渲染。到目前为止似乎工作!
感谢所有回答的人。