2012-03-24 115 views
0

我在我的C#WinForms程序中檢查圖像的X列是否具有黑色像素。奇怪的「嘗試讀取或寫入受保護的內存」錯誤行爲

static Boolean GetColumnState(Bitmap bmp, int x, int col) 
    { 
     BitmapData pixelData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb); 
     Boolean state = false; 
     unsafe 
     { 
      int* pData = (int*)pixelData.Scan0.ToPointer(); 
      pData += x; 
      for (int i = 0; i < bmp.Height; ++i) 
      { 
       pData += bmp.Width; 
       if (Color.FromArgb(*pData) == Color.FromArgb(255, col, col, col)) // error here 
       { state = true; break; } 
      } 
     } 
     bmp.UnlockBits(pixelData); 
     return state; 
    } 

可惜的是我得到

「試圖讀取或寫入保護內存」 在錯誤

「(Color.FromArgb(* pData所)== Color.FromArgb(255山口,山口,列))「

下面是如何定義 」欄「,從不同的方法:

  if (GetColumnState(b1, 0, 255) == false) 
      { col = 255; } 
      else {col = 0;} 
      // more code + loops 
      GetColumnState(b1, i, col) 

奇怪的是:我只有在像素顏色被定義爲255時纔會出錯。黑色)..

你如何解釋這一點?請注意,我正在編寫一個OCR程序,因此我使用不同的鍵值加載多個字典。我在OCR期間裁剪了很多圖片。 我的幸運猜測是線程互相混淆。

現在,我找到了解決這個問題的方法,但價格是+〜150-200ms到總腳本執行時間(這是不必要的價格,我認爲)。

通常我加載字典是這樣的:

 Dictionary<string, Bitmap> lookup = new Dictionary<string, Bitmap>(); 
     Bitmap l0 = new Bitmap(@"C:\xxx\0.bmp", true); 
      //+15 more 
     lookup.Add("0", l0); 
      //+15 more 

     Dictionary<string, Bitmap> lookup2 = new Dictionary<string, Bitmap>(); 
     Bitmap nAa = new Bitmap(@"C:\yyy\Aa.bmp", true); 
      //+15 more 
     lookup2.Add("A", nAa); 
      //+15 more 

要解決這個問題,我要創建「空洞」爲每個字典並加載它們在不同的線程,就像這樣:

void loadNumbers1() 
{ 
     lookup4 = new Dictionary<string, Bitmap>(); 
     Bitmap sd = new Bitmap(@"C:\xxxxx\a.bmp", true); 
      //+15 more 
     lookup4.Add("0", s0); 
      //+15 more 
} 

void loadNumbers2()// 4, 5, 6, 
{ 
     //repeat 
} 

現在我們推出線程:

 Thread tNum2= new Thread(new ThreadStart(loadNumbers2)); 
     tNum2.Start(); 

     Thread tNum3= new Thread(new ThreadStart(loadNumbers3)); 
     tNum3.Start(); 

最後一步(沒有t他一步程序運行速度更快,但是會出現誤差往往):

tNum3.Join(); 

就是這樣,現在我沒有任何問題,但執行時間較長..如何在一個解決這個問題的任何想法更簡單的方法,而不使用多個線程?在我的情況下,沒有連接()我得到5-100ms字典加載時間,加入() - 高達300毫秒。沒有線程 - 最多180(如果錯誤沒有發生)。

對不起長期後

編輯:(永久性的修復)

static unsafe Boolean GetColumnState(Bitmap bmp, int x, int col) 
     { 
      BitmapData pixelData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb); 
      Boolean state = false; 

      unsafe 
      { 
       byte[] buffer = new byte[pixelData.Height * pixelData.Stride]; 
       Marshal.Copy(pixelData.Scan0, buffer, 0, buffer.Length); 

       for (int i = 0; i < pixelData.Height - 1; ++i) 
       { 
        byte red = buffer[i * pixelData.Stride + 4 * x + 2]; 
        if (red == col) 
        { state = true; break; } 
       } 
      } 
      bmp.UnlockBits(pixelData); 
      return state; 
     } 

我不明白什麼是錯關於指針,而是一個字節工作的偉大。 @tia感謝您指出我的問題。

有誰知道爲什麼多線程減慢字典加載時間而不是加速它?

回答

1

如果我理解正確的代碼,循環

for (int i = 0; i < bmp.Height; ++i) 
{ 
    pData += bmp.Width; 
    if (Color.FromArgb(*pData) == Color.FromArgb(255, col, col, col)) // error here 
    { state = true; break; } 
} 

是不正確的。指針應在迭代結束時遞增,否則將跳過第一條掃描線並溢出讀取位圖緩衝區。

+0

好的,我不得不徹底刪除指針,因爲我根本不理解它們,而是使用Byte []代替。請參閱編輯。無論如何,線程爲什麼會減慢執行時間這麼多? – Alex 2012-03-24 16:30:31

相關問題