WinForms 位图区域已被锁定
WinForms Bitmap region is already locked
我想滑过几张图片,基本上你有 2 个向前和向后的按钮。它们的功能是滚动列表图像。一旦其中一个到达末尾,它必须返回列表的另一侧。这是我的
private List<Bitmap> RotatePacks = new List<Bitmap> { new Bitmap(@"Assets\All_Cards\All_Royal\All_Royal.png"),
new Bitmap(@"Assets\All_Cards\All_Classic\All_Classic.jpg")};
private void bNext_Click(object sender, EventArgs e)
{
Bitmap currentImage = (Bitmap)pickCards.Image;
for (int i = 0; i < RotatePacks.Count; i++)
{
if (AreEqual(currentImage, RotatePacks[i]))
{
try
{
pickCards.Image = RotatePacks[i + 1];
}
catch (Exception)
{
bPrevious_Click(sender, e);
pickCards.Image = RotatePacks[i - 1];
}
}
}
}
private void bPrevious_Click(object sender, EventArgs e)
{
Bitmap currentImage = (Bitmap)pickCards.Image;
for (int i = 0; i < RotatePacks.Count; i++)
{
if (AreEqual(currentImage, RotatePacks[i]))
{
try
{
pickCards.Image = RotatePacks[i - 1];
}
catch (Exception)
{
bNext_Click(sender, e);
}
}
}
}
这是 2 个按钮。在这里,我试图将保存图像的 pictureBox 的图像与列表 RotatePacks
进行比较。就像这样,我正在获取正在显示的当前图像。这是 AreEqual 方法:
public unsafe static bool AreEqual(Bitmap b1, Bitmap b2) // copy pasted
{
if (b1.Size != b2.Size)
{
return false;
}
if (b1.PixelFormat != b2.PixelFormat)
{
return false;
}
/*if (b1.PixelFormat != PixelFormat.Format32bppArgb)
{
return false;
}*/
Rectangle rect = new Rectangle(0, 0, b1.Width, b1.Height);
BitmapData data1
= b1.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
BitmapData data2
= b2.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
int* p1 = (int*)data1.Scan0;
int* p2 = (int*)data2.Scan0;
int byteCount = b1.Height * data1.Stride / 4; //only Format32bppArgb
bool result = true;
for (int i = 0; i < byteCount; ++i)
{
if (*p1++ != *p2++)
{
result = false;
break;
}
}
b1.UnlockBits(data1);
b2.UnlockBits(data2);
return result;
}
所以现在回到我的问题,按钮按照我想要的方式工作,但它们只工作一次。如果我按下一个按钮而不是上一个按钮,或者我按两次下一个按钮,程序将崩溃。它在这里给了我例外
BitmapData data2
= b2.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
下面是实际异常的一些屏幕截图:
- P.S 我正在使用这种比较方法,但我还没有编程。我从另一个 Whosebug 问题中复制了代码
这里似乎有几个问题:
值得早点检查
if (b1 == b2) //put this
return true;
//do something else
Rectangle rect = new Rectangle(0, 0, b1.Width, b1.Height);
//and so on
可能 b1 == b2
会导致该问题
您的 LockBits
似乎指的是完全相同的项目(相同 rect
、相同大小、某些模式、相同像素格式):
Rectangle rect = new Rectangle(0, 0, b1.Width, b1.Height);
BitmapData data1
= b1.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
BitmapData data2
= b2.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
这可能是问题的另一个原因...
就像 Ian 指出的那样,您必须检查您在 AreEqual()
方法中尝试比较的图像(current image
和 Rotatepacks[i]
中的图像是否相同并且属于是否相同的实例?如果它们属于同一个实例,它显然会生成该异常。使用 .Equals()
方法检查图像是否属于同一实例。
考虑一个图像实例
Bitmap img;
img
中的图像与 RotatePacks
中的一样被加载到图片框中。在您的代码中,您试图两次锁定同一个实例,因此它会生成异常
Ian 指出的位图线没问题,但 2 个不同的图像可以具有相同的大小和像素格式。
此外,如果确实如此,我认为您不需要逐个像素地进行比较。我想您在 Rotatepacks
中有 Bitmap
个实例。只需使用 .Equals()
将图片框中的图片实例与 Rotatepacks
中的图片实例进行比较
我想滑过几张图片,基本上你有 2 个向前和向后的按钮。它们的功能是滚动列表图像。一旦其中一个到达末尾,它必须返回列表的另一侧。这是我的
private List<Bitmap> RotatePacks = new List<Bitmap> { new Bitmap(@"Assets\All_Cards\All_Royal\All_Royal.png"),
new Bitmap(@"Assets\All_Cards\All_Classic\All_Classic.jpg")};
private void bNext_Click(object sender, EventArgs e)
{
Bitmap currentImage = (Bitmap)pickCards.Image;
for (int i = 0; i < RotatePacks.Count; i++)
{
if (AreEqual(currentImage, RotatePacks[i]))
{
try
{
pickCards.Image = RotatePacks[i + 1];
}
catch (Exception)
{
bPrevious_Click(sender, e);
pickCards.Image = RotatePacks[i - 1];
}
}
}
}
private void bPrevious_Click(object sender, EventArgs e)
{
Bitmap currentImage = (Bitmap)pickCards.Image;
for (int i = 0; i < RotatePacks.Count; i++)
{
if (AreEqual(currentImage, RotatePacks[i]))
{
try
{
pickCards.Image = RotatePacks[i - 1];
}
catch (Exception)
{
bNext_Click(sender, e);
}
}
}
}
这是 2 个按钮。在这里,我试图将保存图像的 pictureBox 的图像与列表 RotatePacks
进行比较。就像这样,我正在获取正在显示的当前图像。这是 AreEqual 方法:
public unsafe static bool AreEqual(Bitmap b1, Bitmap b2) // copy pasted
{
if (b1.Size != b2.Size)
{
return false;
}
if (b1.PixelFormat != b2.PixelFormat)
{
return false;
}
/*if (b1.PixelFormat != PixelFormat.Format32bppArgb)
{
return false;
}*/
Rectangle rect = new Rectangle(0, 0, b1.Width, b1.Height);
BitmapData data1
= b1.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
BitmapData data2
= b2.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
int* p1 = (int*)data1.Scan0;
int* p2 = (int*)data2.Scan0;
int byteCount = b1.Height * data1.Stride / 4; //only Format32bppArgb
bool result = true;
for (int i = 0; i < byteCount; ++i)
{
if (*p1++ != *p2++)
{
result = false;
break;
}
}
b1.UnlockBits(data1);
b2.UnlockBits(data2);
return result;
}
所以现在回到我的问题,按钮按照我想要的方式工作,但它们只工作一次。如果我按下一个按钮而不是上一个按钮,或者我按两次下一个按钮,程序将崩溃。它在这里给了我例外
BitmapData data2
= b2.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
下面是实际异常的一些屏幕截图:
- P.S 我正在使用这种比较方法,但我还没有编程。我从另一个 Whosebug 问题中复制了代码
这里似乎有几个问题:
值得早点检查
if (b1 == b2) //put this return true; //do something else Rectangle rect = new Rectangle(0, 0, b1.Width, b1.Height); //and so on
可能
b1 == b2
会导致该问题您的
LockBits
似乎指的是完全相同的项目(相同rect
、相同大小、某些模式、相同像素格式):Rectangle rect = new Rectangle(0, 0, b1.Width, b1.Height); BitmapData data1 = b1.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat); BitmapData data2 = b2.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
这可能是问题的另一个原因...
就像 Ian 指出的那样,您必须检查您在 AreEqual()
方法中尝试比较的图像(current image
和 Rotatepacks[i]
中的图像是否相同并且属于是否相同的实例?如果它们属于同一个实例,它显然会生成该异常。使用 .Equals()
方法检查图像是否属于同一实例。
考虑一个图像实例
Bitmap img;
img
中的图像与 RotatePacks
中的一样被加载到图片框中。在您的代码中,您试图两次锁定同一个实例,因此它会生成异常
Ian 指出的位图线没问题,但 2 个不同的图像可以具有相同的大小和像素格式。
此外,如果确实如此,我认为您不需要逐个像素地进行比较。我想您在 Rotatepacks
中有 Bitmap
个实例。只需使用 .Equals()
Rotatepacks
中的图片实例进行比较