我正在做一些图像处理在.NET(VB 2010)。我使用下面的代码(不执行任何操作):(例如图像亮度的)损坏的内存与LockBits(DirectShow摄像头)
Sub Manipulate(IMG As Bitmap)
' Dim foo(100000) As Integer - will need it later...
Dim bd = IMG.LockBits(New Rectangle(0, 0, IMG.Width, IMG.Height),
Imaging.ImageLockMode.ReadWrite,
Imaging.PixelFormat.Format24bppRgb)
Dim absstride = Math.Abs(bd.Stride)
Dim numbytes = absstride * IMG.Height
Dim bytes(numbytes - 1) As Byte
Dim flipped = bd.Stride < 0
Dim ptr = If(flipped, bd.Scan0 - numbytes + absstride, bd.Scan0)
System.Runtime.InteropServices.Marshal.Copy(ptr, bytes, 0, numbytes)
' I'm going to put sg here
System.Runtime.InteropServices.Marshal.Copy(bytes, 0, ptr, numbytes)
IMG.UnlockBits(bd)
End Sub
这完全适用于简单的目的,但我的算法需要一些大的变量(见“富”以上)。在声明它(取消注释行),我突然得到例外:
取决于“富”的大小...
...无论是第一Marshal.Copy()抛出
AccessViolationException:尝试读取或写保护的内存。这通常表明其他内存已损坏。
...或“字节”的声明抛出
FatalExecutionEngineError:运行时遇到致命错误。错误的地址是0x6819d142,线程0x3690。错误代码是0xc0000005。此错误可能是CLR中的错误,也可能是用户代码中不安全或不可验证的部分。此错误的常见来源包括COM-interop或PInvoke的用户编组错误,这可能会破坏堆栈。
...或根本没有例外,一切正常。
这是怎么回事?
附加信息:我使用DirectShow从网络摄像头获取图像对象。
摆脱翻转,位图永远不会在Scan0之前开始。并且不要在从不再执行的回调中获得的位图上运行此代码。除非使用Bitmap(Image)构造函数对位图进行深层复制。 – 2012-08-06 16:31:11
@HansPassant我在理论上知道我应该总是从Scan0复制,但当翻转为真时,这种方法不起作用。这样我从正确的内存位置复制,我用Bitmap.GetPixel()检查它。 – Dave 2012-08-07 02:21:01
@HansPassant制作深层副本确实可以解决问题,谢谢:) – Dave 2012-08-07 02:35:46