Question

I don't know a better title, but I'll describe the problem.

A piece of hardware we use has the ability to display images. It can display a black and white image with a resolution of 64 x 256.

The problem is the format of the image we have to send to the device. It is not a standard bitmap format, but instead it is simply an array of bytes representing each pixel of the image.

0 = black, 1 = white.

So if we had an image with the size: 4 x 4 the byte array might look something like:

1000 0100 0010 0001

And the image would look like:

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

The problem is that we need to create this image by creating a monochrome bitmap in C# and then convert it to the file format understood by the device.

For example, one might to display text on the device. In order to do so he would have to create a bitmap and write text to it:

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);
}

There are 2 problems here:

  1. The generated bitmap isn't monochrome
  2. The generated bitmap has a different binary format

So I need a way to:

  1. Generate a monochrome bitmap in .NET
  2. Read the individual pixel colors for each pixel in the bitmap

I have found that you can set the pixel depth to 16, 24, or 32 bits, but haven't found monochrome and I have no idea how to read the pixel data.

Suggestions are welcome.

UPDATE: I cannot use Win32 PInvokes... has to be platform neutral!

FOLLOW UP: The following code works for me now. (Just in case anybody needs it)

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;
}
Was it helpful?

Solution

I'd compute the luminance of each pixel a then compare it to some threshold value.

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

Say the threshold value is 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;
  }
}

OTHER TIPS

I don't know C#. There are possibly many ways to do it. Here is a simple way.

  1. Create a blank black bitmap image of size equal to your device requirement. Draw on it whatever you wish to draw like text, figures etc.

  2. Now threshold the image i.e. set the pixel of image below an intensity value to zero else set it to. e.g. set all intensity values > 0 to 1.

  3. Now convert to the format required by your device. Create a byte array of the size (64 * 256)/8. Set the corresponding bits to 1 where the corresponding pixel values in earlier bitmap are 1, else reset them to 0.

Edit: Step 3. Use bitwise operators to set the bits.

You shouldn't use GetPixel method of your bitmap to convert entire bitmap from one format to another! This will be ineffective. Instead you should use LockBits method to get access to a copy of image buffer and convert it into desired format. I'm not completely sure about converting it to monochrome but there is Format1bppIndexed value in PixelFormat enumeration which may help you.

You may try to supply a pixelformat in the constructor:

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

When I did draw monochrome bitmaps on other platforms I sometimes had to disable antialiasing or the rendered text would not show up:

graphics.SmoothingMode=SmoothingMode.None;

YMMV.

Bitmap has a GetPixel method that you can use. This will let you draw on the Bitmap and later convert it to the format that you need.

Bitmaps in Windows forms (ie, accessed through Graphics.FromImage) are 24 bpp (maybe 32? It's too early and I honestly forget). Nonetheless, GetPixel returns a Color object, so the bit depth of the bitmap is immaterial. I suggest you write your code like this:

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);
}

This process is called simple thresholding. It's braindead, but it will work as a first cut.

thanks for the above code - I'm trying to convert a monochrome image into a 2d array where 1-black 0-white however I'm having some trouble - I used your code to load an 8x8 bmp image, and am outputting its contents to a textbox by using

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

however I get this as a result in the textbox:

225  231  231  231  231  129  255  

how do I get it so it's 0's and 1's?

This chap has some code that creates a mono bitmap. The SaveImage sample is the one of interest.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top