2009-03-02 98 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的?