gpt4 book ai didi

c# - 使用 LockBit 时出现 AccessViolation

转载 作者:行者123 更新时间:2023-11-30 14:02:58 25 4
gpt4 key购买 nike

我想使用 LockBits 方法更快地比较相似图像,如下所示

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

public class CompareImages {

public static void Main ( String[] args ) {

Bitmap bm1 = new Bitmap ( "PB270029.JPG" );
Console.WriteLine ( bm1.PixelFormat.ToString() );

int width = bm1.Width;
int height = bm1.Height;
Console.WriteLine ( "width = " + width + " height = " + height );

Rectangle rect1 = new Rectangle ( 0, 0, width, height );
BitmapData bm1Data = bm1.LockBits ( rect1, ImageLockMode.ReadOnly, bm1.PixelFormat );

Console.WriteLine ( "stride = " + bm1Data.Stride );

IntPtr bm1Ptr = bm1Data.Scan0;

int bytes = Math.Abs(bm1Data.Stride) * height;
Console.WriteLine ( "bytes = " + bytes );

byte[] rgbValues1 = new byte [ bytes ];
Marshal.Copy ( bm1Ptr, rgbValues1, 0, bytes );

Console.WriteLine ( "After 1st Marshal.Copy ..." );

Bitmap bm2 = new Bitmap ( "PA050164.JPG" );
Rectangle rect2 = new Rectangle ( 0, 0, bm2.Width, bm2.Height );
BitmapData bm2Data = bm2.LockBits ( rect2, ImageLockMode.ReadOnly, bm2.PixelFormat );

IntPtr bm2Ptr = bm2Data.Scan0;
byte[] rgbValues2 = new byte [ Math.Abs(bm2Data.Stride) * bm2.Height ];
Marshal.Copy ( bm2Ptr, rgbValues2, 0, rgbValues2.Length );

}

}

但是在第二次 Marshal.Copy 期间发生了 AccessViolationException:

C:\CompareImages>csc CompareImages.cs
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1
Copyright (C) Microsoft Corporation. All rights reserved.


C:\CompareImages>CompareImages.exe
Format24bppRgb
width = 3648 height = 2736
stride = 10944
bytes = 29942784
After 1st Marshal.Copy ...

Unhandled Exception: System.AccessViolationException: Attempted to read or write
protected memory. This is often an indication that other memory is corrupt.
at System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object
destination, Int32 startIndex, Int32 length)
at CompareImages.Main(String[] args)

我的程序有什么问题?

谢谢。

最佳答案

几个小时以来,我一直在研究类似的问题,我想我已经找到了您可能遇到的问题。我猜您的位图可能以略有不同的格式存储。位图可以向前或向后存储。向后存储时步幅将为负。但是,Scan0 将始终指向扫描的第一行,即第一个像素不是数组中的第一个字节。

因此,在反向扫描位图中,Scan0 + Abs(Stride) - 1 是数组中的最后一个字节。 Scan0 + Stride 将始终是第二行的开始,因此如果 stride 为负数,它将向后工作,而正数将向前工作。

如果您以负步幅执行 Marshal.Copy(bm2Ptr, rgbValues2, 0, rgbValues2.Length),这将在进入访问违规区域之前复制最后一条扫描线。以下代码会将任何位图转换为向后扫描 byte[](只是因为这就是我正在使用的)。我猜你现在已经解决/解决了你的问题,但希望这对其他人有帮助。

    private byte[] BitmapToByteArray2(Bitmap bmp)
{
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, ImageLockMode.ReadOnly,
bmp.PixelFormat);

int absStride = Math.Abs(bmpData.Stride);
int bytes = absStride * bmp.Height;

// Declare an array to hold the bytes of the bitmap.
byte[] rgbValues = new byte[bytes];

for (int i = 0; i < bmp.Height; i++)
{
IntPtr pointer = new IntPtr(bmpData.Scan0.ToInt32() + (bmpData.Stride * i));
System.Runtime.InteropServices.Marshal.Copy(pointer, rgbValues, absStride * (bmp.Height - i - 1), absStride);
}

// Unlock the bits.
bmp.UnlockBits(bmpData);

return rgbValues;
}

关于c# - 使用 LockBit 时出现 AccessViolation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4816956/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com