2017-02-27 31 views
1

我正在試驗一些使用unsafe代碼的基本圖像處理。然後我訪問一個像素爲bmp.GetPixel,這導致程序「停止工作」。我不知道如何調試。不安全的圖像處理導致程序退出

我是不是在Treshold方法中做了一些我應該做的事情?

var imageFilename = @"foo.jpg"; 
var im = (Bitmap)Bitmap.FromFile(imageFilename); 

Threshold(im, 2); 

// this line causes it to stop working without an exception 
im.GetPixel(0,0); 



static void Threshold(Bitmap bmp, int thresh) 
{ 
    BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat); 

    unsafe 
    { 
    byte* p = (byte*)(void*)bmData.Scan0.ToPointer(); 
    int h = bmp.Height; 
    int w = bmp.Width; 
    int ws = bmData.Stride; 

    for (int i = 0; i < h; i++) 
    { 
     byte* row = &p[i * ws]; 
     for (int j = 0; j < w * 3; j += 3) 
     { 
     row[j] = (byte)((row[j] > (byte)thresh) ? 255 : 0); 
     row[j + 1] = (byte)((row[j + 1] > (byte)thresh) ? 255 : 0); 
     row[j + 2] = (byte)((row[j + 2] > (byte)thresh) ? 255 : 0); 
     } 
    } 
    } 

    bmp.UnlockBits(bmData); 
} 

更新:出於某種原因,我發現,使用不同的像素格式PixelFormat.Format24bppRgb解決了這個問題。爲什麼?輸入圖像是灰度。

+0

更多信息「你試過將其關閉並重新開啓?」 ...我無法複製您的問題 - 代碼可以按原樣運行,並且可以在調用GetPixel後保存生成的圖像...我嘗試了幾張圖像,可能是圖像相關的,可能是某種東西特定於您的設置。我正在使用VS2015社區版。無論哪種方式,這不是你的代碼。 – CoolBots

+0

奇怪的是,在lockbits中使用'bmp.PixelFormat'嗎?我有一種偷偷摸摸的感覺,這可能與VS 2017 RC有關。 – user3791372

+0

是的,你的代碼是這樣的。這個問題是灰度 - 它是一個16位每像素的圖像,而不是24位 - 您正在通過不安全的代碼讀取圖像。 – CoolBots

回答

0

問題是具體的圖像格式。灰度圖像是每像素8或16位(取決於圖像),而不是每像素24位;你正在讀取(並且更加不利地寫入)圖像之後的內存位置 - 不安全的代碼不檢查數組邊界,因此不會引發異常。

例如,16位灰階,重新寫內部循環:

for (int j = 0; j < w * 2; j += 2) 
    { 
     row[j] = (byte)((row[j] > (byte)thresh) ? 255 : 0); 
     row[j + 1] = (byte)((row[j + 1] > (byte)thresh) ? 255 : 0); 
    } 

程序「停止工作」,你試圖與圖像上班不安全的代碼運行後,由於腐敗記憶 - 你寫給內存不屬於圖像的東西。

您還可以根據bmp.PixelFormat調整您的循環,並操縱適當的位數;這樣你的代碼將適用於多種圖像格式。在bits per pixel

+0

如果您使用'bmp.PixelFormat',如何調整每像素格式的不同位數? – user3791372

+0

@ user3791372它是一個'enum';你可以建立一個'Dictionary '併爲每個條目存儲相應的位數。然後,在運行時查看該字典,並在循環中使用if語句來訪問相應的位數。 – CoolBots

+0

或我可以使用'Image.GetPixelFormat(bmp.PixelFormat)';) – user3791372