ポインタを使って画像内の線を検出し、それらの線を削除するプログラムを作成しようとしています。現在、線の検出部分は非常にうまく機能しており、ほとんどの場合、線の削除部分も機能しています。ただし、約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を見ると、同じビットマップの前の1行がそれ自体で問題なく保存されていても、ほとんどのメンバーが実際の値ではなく「タイプ'InvalidOperationException'の例外をスローした」ことがわかります。入力ビットマップはコード全体で変更されないままであり、何らかの方法で変更する必要がある場合は、常に別のビットマップに複製または描画されます。
lineRemovedを保存した後、行をコメントアウトしようとしましたが、同じエラーがコードの後半に表示されます。さらに、そのtry /catchは実際には例外をキャッチしません-それは常に未処理と言います。それはポインタと関係があるはずですが、そうでなければ私はこれを引き起こしているものについて完全に迷っています。