我正在尝试制作一个程序,该程序使用指针检测图像中的线条并删除这些线条。目前,检测线部分工作得非常好,大部分情况下,删除线部分也工作得很好。但是,在大约 150-200 张图像之后,程序将在与代码的不安全位无关的地方抛出随机 AccessViolationExceptions。
这是删除行的位:
static unsafe Bitmap RemoveLines(Bitmap input, int[] horizontalLines, int[] verticalLines)
{
Bitmap output;
if (input.PixelFormat == PixelFormat.Format24bppRgb)
{
output = (Bitmap) input.Clone();
}
else
{
output = ConvertTo24bpp((Bitmap)input.Clone());
}
BitmapData bitmapData = output.LockBits(new Rectangle(0, 0, output.Width, output.Height), ImageLockMode.ReadWrite, output.PixelFormat);
int w = output.Width;
int h = output.Height;
int bpp = 3;
int s = bitmapData.Stride;
byte* p = (byte*) bitmapData.Scan0;
for (int r = 0; r < h; r++)
{
for (int c = 0; c < h; c++)
{
if (horizontalLines.Contains(r) || verticalLines.Contains(c))
{
int i = (r * s) + c * bpp;
p[i + 0] = 255;
p[i + 1] = 255;
p[i + 2] = 255;
}
}
}
output.UnlockBits(bitmapData);
return output;
}
在此代码之后,我保存生成的位图并将其嵌入到另一个位图中以进行比较:
// ... Detect lines and such
Bitmap export = new Bitmap(bitmap.Width * 3, bitmap.Height, PixelFormat.Format24bppRgb);
Graphics fg = Graphics.FromImage(export);
fg.DrawImage(bitmap, 0, 0); // Draw the original input bitmap
fg.DrawImage(edited, bitmap.Width, 0); // Draw the input after processing (Line Detection)
try
{
Bitmap lineRemoved = RemoveLines(bitmap, horizontalLines.ToArray(), verticalLines.ToArray()); // Remove lines based on earlier detection
lineRemoved.Save(cellDirectory + "\\Lines\\cell_lr_" + i.ToString("D2") + j.ToString("D2") + ".gif", ImageFormat.Gif); // Save image after removal
fg.DrawImage(lineRemoved, bitmap.Width * 2, 0); // Add image to composite for comparison; This line is what throws the error most of the time
lineRemoved.Dispose();
export.Save(cellDirectory + "\\Lines\\cell" + i.ToString("D2") + j.ToString("D2") + ".gif", ImageFormat.Gif);
}
catch (Exception ex)
{ }
DrawImage 调用是引发错误的原因,它始终是 AccessViolationException 后跟 InvalidOperationException。查看错误期间的 lineRemoved 表明它的大多数成员都有“抛出类型为'InvalidOperationException'的异常”而不是实际值,即使在同一个位图之前的一行保存得很好。输入位图在整个代码中保持不变,并且当我需要以任何方式更改它时,它总是被克隆或绘制到不同的位图。
我尝试在保存 lineRemoved 后注释掉这些行,但是稍后在代码中会弹出相同的错误。更重要的是,try/catch 实际上并没有捕捉到异常——它总是说未处理。它必须与指针有关,但否则我完全不知道是什么原因造成的。