Printing bitmaps using CPCL
I've had no end of grief trying to print a PCX to a Zebra Printer using the CPCL printer language. Silly me, didn't notice the EG command (expanded graphics) so there was no need to convert my BMP to a PCX and then struggle with binary data.
I still had a bit of grief working out how to print using the EG command because the documentation is quite frankly crap. The expected command format is
The printer expects a 1 bit pixel matrix. So if pixel(0, 0) is set you will set "80" in the data. If pixel(0, 0) is set and pixel (7, 0) is also set you would sent "81". Basically what you need to do is to read each set of 8 horizontal pixels and then use bit operations to create a byte value 0..255, and then output this as hex 00..FF.
Here's the routine :-)
I still had a bit of grief working out how to print using the EG command because the documentation is quite frankly crap. The expected command format is
EG {WidthInBytes} {HeightInPixels} {XPos} {YPos} {Data}\r\n
The printer expects a 1 bit pixel matrix. So if pixel(0, 0) is set you will set "80" in the data. If pixel(0, 0) is set and pixel (7, 0) is also set you would sent "81". Basically what you need to do is to read each set of 8 horizontal pixels and then use bit operations to create a byte value 0..255, and then output this as hex 00..FF.
Here's the routine :-)
public void DrawBitmap(Bitmap bmp, int xPosition, int yPosition)
{
if (bmp == null)
throw new ArgumentNullException("bmp");
//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} ", loopWidth / 8, bmp.Height, 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");
}
Comments
As I'm a VB.net CF2 developer, I am attempting to migrate your code to VB.
I pretty much have all but the 'for..next' loop and wondered could you help please.
// VB.Net Snippet //
Private Function GetImagePixelsAsHex(ByVal mybmp As Bitmap, ByVal xPosition As Integer, ByVal yPosition As Integer) As String
Dim result As StringBuilder = New StringBuilder()
' Make sure the width is divisible by 8
Dim loopWidth As Integer
loopWidth = (8 - (mybmp.Width Mod 8))
If loopWidth = 8 Then
loopWidth = mybmp.Width
Else
loopWidth += mybmp.Width
End If
result.Append(String.Format("EG {0} {1} {2} {3} ", loopWidth / 8, mybmp.Height, xPosition, yPosition))
' For...Next Loop goes here
result.Append("\r\n")
Return result.ToString()
End Function
Have you seen the following:
http://www.codeplex.com/sharpzebra
This could become very interesting for mobile printer developers.
Great code, exactly what I need!! The only problem is I can't make out the c# code at the start of the for loop, it seems to be formatted wrong? Could you repost this if you have a chance?
Many thanks,
Ciaran
thank you...
I owe you a beer.
On another note to anybody who stumbles upon this, there is also the compressed-graphics command which is twice as efficient as it requires the exact bytes to be sent to the printer rather than having to encode them as a hex encoded string.
MemoryStream s = new MemoryStream();
// Replace
DataString.Append(currentValue.ToString("X2"));
// With
s.WriteByte((byte)currentValue);
Then write the buffer directly to the port after you've written the CG graphics command.
Its working fine.
But i want to print Text along with my image, i tried using Text Command but it is not working.
Hope u will suggest some method to print Text and image together?
Thanks in Advance.
http://khanowais.blogspot.com/2012/04/printing-bitmaps-using-cpcl-in-android.html
It is a good solution.
But it has a performance penalty on Windows Mobile Device. For a bitmap with size 560x200, it takes almost 10 seconds to complete DrawBitmap routine.
Can any improvement be done in your code?