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

EG {WidthInBytes} {HeightInPixels} {XPos} {YPos} {Data}rn

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("rn");
}

9 thoughts on “Printing bitmaps using CPCL

  1. Thanks Peter
    It is a good solution.

    But it has a performance penalty on Windows Mobile Device. For a bitmap with size 560×200, it takes almost 10 seconds to complete DrawBitmap routine.

    Can any improvement be done in your code?

  2. Thanks Peter,
    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.

  3. Good stuff Peter, I just checked this out because I was pulling my hair out with, like you say, the crap documentation from zebra.

    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.

  4. Hi Peter,

    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

  5. Hi Peter, i was delighted to find you snippet for ‘pcx’ to ‘bitmap’ conversion.

    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(“rn”)
    Return result.ToString()

    End Function

Leave a Reply

Your email address will not be published. Required fields are marked *