我不知道一个更好的标题,但我会描述这个问题。
我们使用的硬件能够显示图像。 它可以显示分辨率为64 x 256的黑白图像。
问题是我们必须发送到设备的图像格式。 它不是标准的位图格式,而是简单的数组 表示图像的每个像素的字节。
0 =黑色,1 =白色。
因此,如果我们有一个大小为4 x 4的图像,则字节数组可能类似于:
1000 0100 0010 0001
图像看起来像:
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);
}
这里有两个问题:
所以我需要一种方法:
我发现你可以将像素深度设置为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;
}
答案 0 :(得分:6)
我计算每个像素a的亮度,然后将其与某个阈值进行比较。
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 :(得分:1)
我不知道C#。可能有很多方法可以做到这一点。这是一个简单的方法。
创建一个大小等于设备要求的空白黑色位图图像。无论你想绘制什么,如文字,数字等,都要画上它。
现在对图像进行阈值处理,即将图像像素设置为强度值低于零,否则将其设置为。例如设定所有强度值&gt; 0到1.
现在转换为您的设备所需的格式。创建一个大小为(64 * 256)/ 8的字节数组。将相应的位设置为1,其中先前位图中的相应像素值为1,否则将它们重置为0.
编辑:步骤3.使用按位运算符设置位。
答案 2 :(得分:1)
您不应该使用位图的GetPixel方法将整个位图从一种格式转换为另一种格式!这将是无效的。相反,您应该使用LockBits方法来访问图像缓冲区的副本并将其转换为所需的格式。我不完全确定将其转换为单色,但PixelFormat枚举中的Format1bppIndexed值可能对您有帮助。
答案 3 :(得分:1)
您可以尝试在构造函数中提供pixelformat:
var bitmap = new Bitmap(256, 64, PixelFormat.Format1bppIndexed);
当我在其他平台上绘制单色位图时,我有时会这样做 禁用抗锯齿或渲染文本不会显示:
graphics.SmoothingMode=SmoothingMode.None;
因人而异。
答案 4 :(得分:1)
Bitmap has a GetPixel method。这将让您在Bitmap上绘制,然后将其转换为您需要的格式。
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);
}
此过程称为简单阈值。它是脑死亡,但它将作为第一次切割。
答案 5 :(得分:1)
感谢上面的代码 - 我正在尝试将单色图像转换为2d数组,其中1-black 0-white然而我遇到了一些麻烦 - 我用你的代码加载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?
答案 6 :(得分:0)
This chap有一些代码可以创建单声道位图。 SaveImage样本是您感兴趣的样本。