2009-03-02 99 views
3

我不知道更好的標題,但我會描述問題。閱讀單色位圖像素顏色

我們使用的一塊硬件能夠顯示圖像。 它可以顯示分辨率爲64 x 256的黑白圖像。

問題是我們必須發送到設備的圖像格式。 這不是一個標準的位圖格式,而是一個簡單的代表圖像每個像素的 字節的數組。

0 =黑色,1 =白色。

因此,如果我們曾與大小的圖片:4×4的字節數組可能看起來像:

和圖像看起來像:

Bitmap http://www.mediafire.com/imgbnc.php/6ee6a28148d0170708cb10ec7ce6512e4g.jpg

問題是,我們需要通過在C#中創建一個單色位圖 來創建該圖像,然後將其轉換爲設備可理解的文件格式。

例如,可能會在設備上顯示文本。爲了做到這一點,他將 必須創建一個位圖和文本寫入它:

var bitmap = new Bitmap(256, 64); 

using (var graphics = Graphics.FromImage(bitmap)) 
{ 
    graphics.DrawString("Hello World", new Font("Courier", 10, FontStyle.Regular), new SolidBrush(Color.White), 1, 1); 
} 

有2個問題在這裏:

  1. 生成位圖是不是單色
  2. 生成位圖有不同的二進制格式

所以我需要一種方法來:

  1. 生成.NET
  2. 單色位圖閱讀每個像素的單個像素的顏色位圖

我發現,您可以將像素深度設置爲16,24或32位,但還沒有找到單色,我不知道如何讀取像素數據。

建議歡迎。

更新:我不能使用Win32 PInvokes ...必須是平臺中立!

後續:下面的代碼現在適用於我。 (萬一有人需要它)

private static byte[] GetLedBytes(Bitmap bitmap) 
{ 
    int threshold = 127; 
    int index = 0; 
    int dimensions = bitmap.Height * bitmap.Width; 

    BitArray bits = new BitArray(dimensions); 

    //Vertically 
    for (int y = 0; y < bitmap.Height; y++) 
    { 
     //Horizontally 
     for (int x = 0; x < bitmap.Width; x++) 
     { 
      Color c = bitmap.GetPixel(x, y); 
      int luminance = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11); 
      bits[index] = (luminance > threshold); 
      index++; 
     } 
    } 

    byte[] data = new byte[dimensions/8]; 
    bits.CopyTo(data, 0); 
    return data; 
} 

回答

6

我計算每個像素的亮度一然後比較它的一些閾值。

y=0.3*R+0.59G*G+0.11*B 

說閾值是127:

const int threshold = 127; 
Bitmap bm = { some source bitmap }; 

byte[,] buffer = new byte[64,256]; 

for(int y=0;y<bm.Height;y++) 
{ 
    for(int x=0;x<bm.Width;x++) 
    { 
    Color c=source.GetPixel(x,y); 
    int luminance = (int)(c.R*0.3 + c.G*0.59+ c.B*0.11); 
    buffer[x,y] = (luminance > 127) ? 1 : 0; 
    } 
} 
+1

點!但是,如果使用Bitmap.LockBits而不是Bitmap.GetPixel,則可以獲得卓越的性能! – 2009-03-02 11:41:00

+0

Thnx! 經過一些小的調整,這段代碼就像一個魅力:-) – TimothyP 2009-03-02 11:45:31

0

This chap具有創建一個單一的位圖一些代碼。 SaveImage樣本是感興趣的。

+0

鏈接已死 – danmiser 2016-06-01 00:25:30

1

我不知道C#。有可能有很多方法來做到這一點。這是一個簡單的方法。

  1. 創建一個空白的黑色位圖圖像的大小等於您的設備要求。借鑑它不管你想畫一樣的文字,數字等

  2. 現在門檻的圖像,即設定圖像的像素以下的強度值爲零否則將其設置爲。例如將所有強度值> 0到1

  3. 現在轉換爲設備所要求的格式。創建一個大小爲(64 * 256)/ 8的字節數組。將相應的位設置爲1,其中較早的位圖中的相應像素值爲1,否則將它們重置爲0.

編輯:步驟3.使用按位運算符設置位。

+0

問題是我不知道如何讀取位圖的像素值 – TimothyP 2009-03-02 11:24:54

+0

那麼你需要檢查API。必須有一些像getPixel(),getIntensity()這樣的方法,或者甚至可以使用簡單的數組引用。 – Xolve 2009-03-02 11:33:13

1

你不應該用你的位圖的GetPixel方法,整個位圖從一種格式轉換爲另一種!這將是無效的。相反,您應該使用LockBits方法來訪問圖像緩衝區的副本並將其轉換爲所需的格式。我不完全確定將它轉換爲單色,但在PixelFormat枚舉中有Format1bppIndexed值,可以幫助您。

1

您可以嘗試在構造函數中提供一個像素格式:

var bitmap = new Bitmap(256, 64, PixelFormat.Format1bppIndexed); 

當我做畫在其他平臺上我有時不得不 禁用反鋸齒或呈現的文本將不會顯示單色位圖:

graphics.SmoothingMode=SmoothingMode.None; 

情況因人而異。

1

Bitmap has a GetPixel method,您可以使用。這會讓你在位圖上繪圖,然後將其轉換爲你需要的格式。

位圖在Windows的形式(即通過Graphics.FromImage訪問)是24 BPP(也許32?還爲時過早,我真的忘記了)。儘管如此,GetPixel會返回一個Color對象,因此位圖的位深度並不重要。我建議你寫這樣的代碼:

MyBitmapFormat ToMyBitmap(Bitmap b) 
{ 
    MyBitmapFormat mine = new MyBitmapFormat(b.Width, b.Height); 

    for (int y=0; y < b.Height; y++) { 
     for (int x=0; x < b.Width; x++) { 
      mine.SetPixel(x, y, ColorIsBlackish(b.GetPixel(x, y))); 
     } 
    } 
} 

bool ColorIsBlackish(Color c) 
{ 
    return Luminance(c) < 128; // 128 is midline 
} 

int Luminance(c) 
{ 
    return (int)(0.299 * Color.Red + 0.587 * Color.Green + 0.114 * Color.Blue); 
} 

這個過程被稱爲簡單閾值。這是braindead,但它將作爲第一次切割。

1

感謝上面的代碼 - 我試圖將單色圖像轉換成2維數組,其中1-黑色0-白色但是我有一些麻煩 - 我用你的代碼加載8x8 bmp圖像,並且我用

myGrid =GetLedBytes(myBmp); 
    for (int x = 1; x < 8; x++) 
    { 
     textBox1.Text = textBox1.Text + Convert.ToString(myGrid[x])+ " "; 
    } 

輸出其內容的文本框,但是我得到這個結果在文本框中:

225 231 231 231 231 129 255 

我如何得到它,所以它是0和1的?