Platform: Windows Mobile 6.5 Handheld
Language: C#
My problem: I'm being asked to capture a signature from the user and then send that signature to a printer to print on a receipt. I've successfully captured the image of the signature and have the byte array of the signature in memory but cannot seem to print it properly.
To get me started, I followed the blog here to get the Hex representation of the bitmap. However, this just printed out a very long receipt with the hex
representation of the signature. Code here instead of following the link:
private static string DrawBitmap(Bitmap bmp, int xPosition, int yPosition)
{
if (bmp == null)
throw new ArgumentNullException("bmp");
StringBuilder DataString = new StringBuilder();
//Make sure the width is divisible by 8
int loopWidth = 8 - (bmp.Width % 8);
if (loopWidth == 8)
loopWidth = bmp.Width;
else
loopWidth += bmp.Width;
//DataString.Append(string.Format("EG {0} {1} {2} {3} ", xPosition, yPosition));
DataString.Append(string.Format("EG 64 128 {0} {1} ", xPosition, yPosition));
for (int y = 0; y < bmp.Height; y++)
{
int bit = 128;
int currentValue = 0;
for (int x = 0; x < loopWidth; x++)
{
int intensity;
if (x < bmp.Width)
{
Color color = bmp.GetPixel(x, y);
intensity = 255 - ((color.R + color.G + color.B) / 3);
}
else
intensity = 0;
if (intensity >= 128)
currentValue |= bit;
bit = bit >> 1;
if (bit == 0)
{
DataString.Append(currentValue.ToString("X2"));
bit = 128;
currentValue = 0;
}
}//x
}//y
DataString.Append("\r\n");
return DataString.ToString();
}
After that failed, I found the CPCL programming guide for Zebra printers and followed the example on page 95 to print the little tile image. However, this did the same thing as the signature. Once that failed, I found that I needed to run the command: ! U1 setvar "device.languages" "zpl" before doing any EG commands; so I went ahead and did this but things took a bad turn here which end up forcing me to fully reset the printer and/or cleanboot the handheld because it causes a COM exception that crashes COM6 and the printer.
I have exhausted most if not all of the resources that I can think of and none of them have worked.
Does anyone have any other ideas or examples that could help me get this working?
Thanks
I found another CPCL programmers guide and it has this simple (test) example:
! 0 200 200 210 1
EG 2 16 90 45 F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F
F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F
FORM
PRINT
This should print a small checker board pattern.
The next example prints a PCX graphic:
PCX Commands
The PCX command gives a user the ability to send “.PCX” graphics formatted images to the printer. The
.PCX image MUST be encoded as a black and white image.
Format:
{command} {x} {y}
{data}
where:
{command}: PCX
{x}: X-coordinate of the top-left corner.
{y}: Y-coordinate of the top-left corner.
{data}: PCX image data.
Example:
! 0 200 200 500 1
PCX 0 30
<binary black and white pcx data stream>
FORM
PRINT
Example using a file (loaded previously the printers file system)
! 0 200 200 500 1
PCX 0 30 !<IMAGE.PCX
FORM
PRINT
If the printer has been switched to line printer mode, the command
! U1 PCX {x coordinate} {y coordinate} !< {filename.pcx}
for example
! U1 PCX 0 30 !< IMAGE.PCX
can be used to print monochrome PCX from file system.
Remeber that .NET is UTF-8 and so all commands and data has to be converted to ASCII before sending over a COM port. So do something like this:
Encoding ansi = Encoding.GetEncoding(1252);
byte[] buf = ansi.GetBytes(DataString);
System.IO.Ports.SerialPort sp = new System.IO.Ports.SerialPort("COM1:");
sp.Write(buf, 0, buf.Length);
for the PCX data just use the byte stream for the byte[] buffer.
Related
I need to check if the PNG image that has constant size (512x512 pixels) has only white pixels and nothing else or not.
Is there an easy way to do this, preferably without checking every pixel manually? Maybe using ImageMagick?
I don't think there is a magic way of determining whether an image is white.
You'll probably just have to check all pixels, but you can have fast access to your image if you convert it to bitmap and, instead of using GetPixel(), you lock the bitmap in memory using the LockBits() method. Then you can work with the BitmapData type and write your own, fast, GetPixel(), as explained here: Working with BitmapData.
Edit:
Actually, I though of another way: you can create a plain white image of the same size, and then compare your image to that one by computing and comparing their hashes. Take a look at this: Comparing two images.
You can avoid parsing and loops and two-step tests by asking Imagemagick to tell you the answer.
If the mean of the pixels is 1.0 (which it has to be if all pixels are white) and also the width is 512 and the height is 512, the test below will output 1, else 0.
# Test a white 512x512 image => Result: 1
identify -format "%[fx:(mean==1)&&(w==512)&&(h==512)?1:0]" white.png
1
# Test a white 600x512 image => Result: 0
identify -format "%[fx:(mean==1)&&(w==512)&&(h==512)?1:0]" white600x512.png
0
# Test a gray image => Result: 0
identify -format "%[fx:(mean==1)&&(w==512)&&(h==512)?1:0]" gray90.png
0
Another simple solution in ImageMagick command line is to just average the image down to 1 pixel or compute the mean of the image and test if the value is 1 (in the range 0 to 1), where 1 is white and 0 is black.
Create a test image
convert -size 512x512 xc:white white.png
convert -size 512x512 xc:black black.png
convert -size 512x512 xc:gray gray.png
Method 1 -- scale to 1 pixel:
convert white.png -scale 1x1! -format "%t = %[fx:u]\n" info:
white = 1
convert black.png -scale 1x1! -format "%t = %[fx:u]\n" info:
black = 0
convert gray.png -scale 1x1! -format "%t = %[fx:u]\n" info:
gray = 0.494118
Method 2:
convert white.png -format "%t = %[fx:mean]\n" info:
white = 1
convert black.png -format "%t = %[fx:mean]\n" info:
black = 0
convert gray.png -format "%t = %[fx:mean]\n" info:
gray = 0.494118
You can also do (a ternary) test in the command line. 1 will be true and 0 will be false.
test=$(convert white.png -format "%[fx:mean==1?1:0]\n" info:)
echo $test
1
Testing using Unix conditional:
if [ $test -eq 1 ]; then
echo "full white"
else
echo "not white"
fi
full white
Note that fx: is general purpose calculator and u is just the pixel value. t gives the name of the images without suffix.
ImageMagick supports C# in the Magick.Net module. See https://github.com/dlemstra/Magick.NET
From the commandline, you can run
identify -verbose image
And look for
Channel statistics:
Pixels: 10
Gray:
min: 65535 (1)
max: 65535 (1)
mean: 65535 (1)
If the image has a "min" that is not 65535, then it's not an entirely white image.
Use this code:
private bool IsBlankImage(string path)
{
bool isBlank = true;
Image img = Image.FromFile(path);
Bitmap bmp = new Bitmap(img);
for (int x = 0; x < bmp.Width && isBlank; x++)
for (int y = 0; y < bmp.Height && isBlank; y++)
if (bmp.GetPixel(x, y).Name != "ffffffff") isBlank = false;
bmp.Dispose();
img.Dispose();
return isBlank;
}
Then Call the Function:
bool isBlank = isBlankImage("D:\\myImage.jpg");
if (isBlank) MessageBox.Show("The Image is Blank");
else MessageBox.Show("The Image is Not Blank");
You could use the method as described in the answer from Eutherpy. If you want to do more image operation and you need an advanced image library you might want to use the ImageMagick C# wrapper that I created called Magick.NET.
Below is a small sample of how you could check it in that library:
private static bool IsWhite(MagickImage image)
{
var white = MagickColors.White;
using (var pixels = image.GetPixels())
{
foreach (var pixel in pixels)
{
var color = pixel.ToColor();
if (color != white)
return false;
}
}
return true;
}
static void Main(string[] args)
{
using (var image = new MagickImage(#"c:\folder\yourimage.png"))
{
if (IsWhite(image))
Console.WriteLine("The image is all white");
}
}
I am printing the mono chorme bit map image on thermal printer where i am able to print the image but at rightmost, one vertical line is getting printed. (The line is from Top right to bottom right with nearly 2mm thick)
Bitmap image = new Bitmap(imagePath, false);
int imageDepth = System.Drawing.Bitmap.GetPixelFormatSize(image.PixelFormat);
Rectangle monoChromeBitmapRectangle = new Rectangle(0, 0, image.Width, image.Height);
BitmapData monoChromebmpData = null;
int stride = 0;
monoChromebmpData = image.LockBits(monoChromeBitmapRectangle, ImageLockMode.ReadOnly, resizedImage.PixelFormat);
IntPtr ptr = monoChromebmpData.Scan0;
stride = monoChromebmpData.Stride;
int numbytes = stride * image.Height;
byte[] bitmapFileData = new byte[numbytes];
Marshal.Copy(ptr, bitmapFileData, 0, numbytes);
image.UnlockBits(monoChromebmpData);
//Invert bitmap colors
for (int i = 0; i < bitmapFileData.Length; i++)
{
bitmapFileData[i] ^= 0xFF;
}
StringBuilder hexaDecimalImageDataString = new StringBuilder(bitmapFileData.Length * 2);
foreach (byte b in bitmapFileData)
hexaDecimalImageDataString.AppendFormat("{0:X2}", b);
return hexaDecimalImageDataString;
Here i am converting the mono chrome bitmap image to byte array and from byte array to hexadecimal string.
i googled in forums but this kind of error is not discussed. (May be i am doing silly mistake)
Can any one suggest where exactly i am making the mistake.
Thanks in advance.
Cheers,
Siva.
Your are returning monoChromebmpData.Stride * image.Height bytes, i.e. each line in the image will be exactly monoChromebmpData.Stride * 8 pixels wide - but probably the original image has a pixel width that is less than that, hence the extra vertical line on the right.
Try something like this:
byte[] masks = new byte[]{0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
int byteWidth = (image.Width+7)/8;
int nBits = imageWidth % 8;
byte[] actualBitmapFileData = new byte[byteWidth*image.Height];
int yFrom = 0;
for (int y=0; y<image.Height; y++) {
for (int x=0; x<byteWidth-1; x++) {
actualBitmapFileData[y*byteWidth + x] = (bitmapFileData[yFrom + x] ^ 0xFF);
}
int lastX = byteWidth - 1;
actualBitmapFileData[y*byteWidth + lastX] = (bitmapFileData[yFrom + lastX] ^ 0xFF) & masks[nBits];
yFrom += stride;
}
it creates an actualBitmapFileData array for bitmapFileData with of the correct size.
Note that the last byte of every line would contain only nBits pixels - and so needs to be 'masked' to clear out the extra bit not corresponding with any pixel. This is done by & masks[nBits], where masks is an array of 8 bytes with the 8 masks to use. The actual values of the mask depend on how the printer works: you might need to set the extra bits to 0 or to 1, and the extra bits can be the most-significant or the least-significant ones. The mask values used above assume that the most significant bits are rendered to the right, and that the masked bits should be set to 0. Depending on how the printer works it might be necessary to swap the bits and/or set the masked bits to 1 instead than zero (complementing the mask and using | instead than &)
For performance reasons each horizontal row in a Bitmap is buffered to a DWORD boundary (see this answer for more details). So if your Bitmap's width multiplied by it's bits-per-pixel(bpp) is not divisible by 32 (DWORD = 32bits) then it's padded with extra bits. So a 238x40 1bpp Bitmap has a memory foot print of 8 DWORDs per row or 256 bits.
The BitmapData object's Stride property is the number of bytes that each row of your bitmap consumes in memory. When you capture the Byte Array, you're capturing that padding as well.
Before you convert the byte array to hex you need to trim the buffer off the end. The following function should do that nicely.
public static byte[] TruncatePadding(byte[] PaddedImage, int Width, int Stride, int BitsPerPixel)
{
//Stride values can be negative
Stride = Math.Abs(Stride);
//Get the actual number of bytes each row contains.
int shortStride = (int)Math.Ceiling((double)(Width*BitsPerPixel/8));
//Figure out the height of the image from the array data
int height = PaddedImage.Length / Stride;
if (height < 1)
return null;
//Allocate the new array based on the image width
byte[] truncatedImage = new byte[shortStride * height];
//Copy the data minus the padding to a new array
for(int i = 0; i < height; i++)
Buffer.BlockCopy(PaddedImage,i*Stride,truncatedImage,i*shortStride,shortStride);
return truncatedImage;
}
The comments from MiMo and MyItchyChin helped me alot on resolving the issue.
The problem is getting the extra line at the end. So technically, on printing the each row of image, last few byte information is incorrect.
The reason for getting this problem is, the image size could be anything, but whne it sends to printer, the byte width should be divisible by eight. In my case my printer expects the bytewidth as input so i must be careful on passing the image.
Assume i have image 168x168 size.
byteWidth = Math.Ceiling(bitmapDataWidth / 8.0);
so the byteWidth is 21 here, As per printer expectation i did Left shift operation to 24 which is diviseble by 8, so virtually i increased the size of image by 3bytes and then started reading the byte information. The line i am talking about is that extra 3 bytes. Since no data is there, the black line is getting printed.
I wrote the logic in such a way, where byte array doesnot effect with shift operations hence it worked for me.
Early days for me in image processing, So please ignore, if i made a silly mistake and explaining the solution here.
I'm working with Scintilla (not ScintillaNET), and I'm trying to set the images used in the auto complete list. Scintilla requires a string of bytes/pixels in the RGBA format.
Scintilla's description of this RGBA format: (Quote from documentation)
The RGBA format allows translucency with an alpha value for each
pixel. It is simpler than XPM and more capable.
The data is a sequence of 4 byte pixel values starting with the pixels
for the top line, with the leftmost pixel first, then continuing with
the pixels for subsequent lines. There is no gap between lines for
alignment reasons.
Each pixel consists of, in order, a red byte, a green byte, a blue
byte and an alpha byte. The colour bytes are not premultiplied by the
alpha value. That is, a fully red pixel that is 25% opaque will be
[FF, 00, 00, 3F]
I expect that I'm misunderstanding the format explained above, the documentation is not very clear.
My Conversion Method:
I wrote this function to convert a PNG into this string of bytes:
public static string ConvertFromPNG(Bitmap PNG)
{
string rgba = "";
int pixWidth = PNG.Width;
int pixHeight = PNG.Height;
for (var y = 0; y < pixHeight; y++)
{
for (var x = 0; x < pixWidth; x++)
{
Color pix = PNG.GetPixel(x, y);
rgba += pix.R.ToString("X2") + pix.G.ToString("X2") + pix.B.ToString("X2") + pix.A.ToString("X2");
}
}
return rgba;
}
The Resulting Image:
But Scintilla is just showing the image as a grey box:
.
The image in question is a copy of one of Microsoft's Babel images: .
I know that the set of bytes is correct because interestingly, if I format them in lines and zoom out on them I can see the outline of the image:
Bytes Generated:
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009F000000EC0000001B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815B0000DF9B0000F8000000B40000002F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B0000007F4E0000FDC80000FFFF0000FF720000FF1D0000B50000003E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001613000085350000FFDE0000FFFF0000FFFF0000FFFF0000FF750000FF230000C4000000240000000000000000000000000000000000000000000000000000000000000000000000000000000000000085400000EADB0000FFF90000FFFF0000FFFF0000FFFF0000FFF60000FFA70000F5000000DA00000000000000000000000000000000000000000000000000000000000000000000000000000091810000EACA0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFBB0000FF460000FF000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000FF7E0000FFE80000FFFF0000FFFF0000FFFF0000FFFB0000FFB30000FF460000FF0C0000FF000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000FF000000FF660000FFFF0000FFFF0000FFFF0000FFC70000FF0D0000FF590000FF7A0000FF000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000FF8C0000FF7D0000FF2E0000FFFF0000FFBB0000FF1C0000FF510000FFB40000FF7B0000FF000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000FFE20000FFE40000FF410000FF8B0000FF510000FF350000FFB60000FF8F0000FF3A0000EA00000091000000000000000000000000000000000000000000000000000000000000000000000000000000DA910000F5F30000FFFF0000FF0C0000FF270000FFC10000FF930000FF220000EA0000008500000000000000000000000000000000000000000000000000000000000000000000000000000000000000241D0000C4870000FFFF0000FF270000FF420000FF9E0000FF230000FF090000860000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E2D0000B5610000FF120000FF1C0000FF370000FD0000007F0000001B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E000000B4000000F8000000DF00000081000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B000000EC0000009F0000000000000000000000000000000000000000
You are formatting the bytes as hex values and placing them in a string. Scintilla just wants the bytes themselves.
I suspect you want to create a byte array rather than a string, and store into it the values of pix.R, pix.G, pix.B, and pix.A directly, rather than formatting them as strings.
After accepting JasonD's answer I've updated my code and it's working. In case it helps anyone else, here is the working code:
public static byte[] ConvertFromPNG(Bitmap PNG)
{
byte[] rgbaB = new byte[4 * (PNG.Width * PNG.Height)];
int i = 0;
for (var y = 0; y < PNG.Height; y++)
{
for (var x = 0; x < PNG.Width; x++)
{
Color pix = PNG.GetPixel(x, y);
rgbaB[i++] = pix.R;
rgbaB[i++] = pix.G;
rgbaB[i++] = pix.B;
rgbaB[i++] = pix.A;
}
}
return rgbaB;
}
I am learning C# and I am trying this making my homeworks on image processing examples. I am trying to read the pixel values along an horizontal line in a gray levels jpeg image. Some prints I made inform me that I am reading a Format8bppIndexed image (this was a kind of surprise to me, because my belief was that jpeg images do not use a palette at all). The code to load the image in the proper control in the windows form is something like this:
try
{
myImage = ( Bitmap ) Image.FromFile(imageName);
}
catch
{
MessageBox .Show("Unable to load the image" , Text, MessageBoxButtons .OK, MessageBoxIcon .Hand);
}
pictureBox1.Image = myImage ;
Then I try to read the pixel along an arbitrary straight path in the image listing them in a csv file when pressing a button. I assume that, being the image a gray level one, reading the red color is enough (is it? other color components are equal; using the getBrightness seems to me an overkill):
cursorStartx = 0;
cursorStarty = 256;
cursorEndx = myImage.Width;
cursorEndy = 256;
Color pixel;
StreamWriter fs = new StreamWriter( "pixels.csv" , true );
for (var i = 0; i < cursorEndx; i++)
{
pixel = myImage.GetPixel(i, cursorStarty);
fs.WriteLine( String .Format("{0}; {1}; {2}" , i, cursorStarty, pixel.R));
}
fs.Close();
When reading the cross section in the file I see values that make no sense at all: they are all multiple of 17 (???):
0; 256; 17
1; 256; 0
2; 256; 17
3; 256; 0
4; 256; 17
5; 256; 0
6; 256; 17
7; 256; 0
8; 256; 17
9; 256; 0
10; 256; 17
............
66; 256; 17
67; 256; 34
68; 256; 51
69; 256; 68
70; 256; 85
71; 256; 85
72; 256; 102
73; 256; 85
An histogram made in the same program shows clearly distinct count peaks at multiple of 17 (????)
Just to perform a reality check, I made something similar in Perl (I have a lot more experience in perl, I am just learning C#) using the module GD and, reading the pixel on the very same path in the same image, I get very different values.
First rows of the histogram drwan by imageJ are the following:
0 0
1 0
2 1
3 1
4 15
5 81
6 304
7 984
8 2362
9 206144
10 2582
11 1408
12 653
13 451
14 345
15 321
16 277
17 288
a quite different story.
Someone could possibly explain to me what horribly stupid kind of error I am doing?
Thanks a lot
----------------------------------- EDITED LATER --------------------------------------
Things are becoming intriguing. Reading the same image using Aforge image lab, written in C#, I got the same kind of error: the histogram shows discrete count at pixel values that are multiple of 17. Reading the image with ImageJ, written in Java, I get a correct histogram. Now I am trying to figure out if there is a way, using C#, to manage the image reading somehow, in order to be able to get the correct values, or this is a major issue and the alternatives are: to give up or to perform some sort of low level image reading (hard stuff for jpeg format...)
Multiples of 17 are actually quite common when converting 4bpp channels into 8bpp channels. 0x00, 0x11, 0x22 ... 0xFF are all multiples of 17.
Looks to me you have a quantized 16 colors grayscale image with dithering.
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:
The generated bitmap isn't monochrome
The generated bitmap has a different binary format
So I need a way to:
Generate a monochrome bitmap in .NET
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;
}
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;
}
}
I don't know C#. There are possibly many ways to do it. Here is a simple way.
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.
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.
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.