How to Convert Image to Zpl Code for Printing Using Zebra Printer

How to convert image to zpl code for printing using zebra printer?

I solved the problem and I am posting the answer so that other people can take benefit from the solution. The bitmap image can be converted to zpl code using following converter class.

public class ZPLConverter {
private int blackLimit = 380;
private int total;
private int widthBytes;
private boolean compressHex = false;
private static Map<Integer, String> mapCode = new HashMap<Integer, String>();

{
mapCode.put(1, "G");
mapCode.put(2, "H");
mapCode.put(3, "I");
mapCode.put(4, "J");
mapCode.put(5, "K");
mapCode.put(6, "L");
mapCode.put(7, "M");
mapCode.put(8, "N");
mapCode.put(9, "O");
mapCode.put(10, "P");
mapCode.put(11, "Q");
mapCode.put(12, "R");
mapCode.put(13, "S");
mapCode.put(14, "T");
mapCode.put(15, "U");
mapCode.put(16, "V");
mapCode.put(17, "W");
mapCode.put(18, "X");
mapCode.put(19, "Y");
mapCode.put(20, "g");
mapCode.put(40, "h");
mapCode.put(60, "i");
mapCode.put(80, "j");
mapCode.put(100, "k");
mapCode.put(120, "l");
mapCode.put(140, "m");
mapCode.put(160, "n");
mapCode.put(180, "o");
mapCode.put(200, "p");
mapCode.put(220, "q");
mapCode.put(240, "r");
mapCode.put(260, "s");
mapCode.put(280, "t");
mapCode.put(300, "u");
mapCode.put(320, "v");
mapCode.put(340, "w");
mapCode.put(360, "x");
mapCode.put(380, "y");
mapCode.put(400, "z");
}

public String convertFromImage(Bitmap image, Boolean addHeaderFooter) {
String hexAscii = createBody(image);
if (compressHex) {
hexAscii = encodeHexAscii(hexAscii);
}

String zplCode = "^GFA," + total + "," + total + "," + widthBytes + ", " + hexAscii;

if (addHeaderFooter) {
String header = "^XA " + "^FO0,0^GFA," + total + "," + total + "," + widthBytes + ", ";
String footer = "^FS" + "^XZ";
zplCode = header + zplCode + footer;
}
return zplCode;
}

private String createBody(Bitmap bitmapImage) {
StringBuilder sb = new StringBuilder();
int height = bitmapImage.getHeight();
int width = bitmapImage.getWidth();
int rgb, red, green, blue, index = 0;
char auxBinaryChar[] = {'0', '0', '0', '0', '0', '0', '0', '0'};
widthBytes = width / 8;
if (width % 8 > 0) {
widthBytes = (((int) (width / 8)) + 1);
} else {
widthBytes = width / 8;
}
this.total = widthBytes * height;
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
rgb = bitmapImage.getPixel(w, h);
red = (rgb >> 16) & 0x000000FF;
green = (rgb >> 8) & 0x000000FF;
blue = (rgb) & 0x000000FF;
char auxChar = '1';
int totalColor = red + green + blue;
if (totalColor > blackLimit) {
auxChar = '0';
}
auxBinaryChar[index] = auxChar;
index++;
if (index == 8 || w == (width - 1)) {
sb.append(fourByteBinary(new String(auxBinaryChar)));
auxBinaryChar = new char[]{'0', '0', '0', '0', '0', '0', '0', '0'};
index = 0;
}
}
sb.append("\n");
}
return sb.toString();
}

private String fourByteBinary(String binaryStr) {
int decimal = Integer.parseInt(binaryStr, 2);
if (decimal > 15) {
return Integer.toString(decimal, 16).toUpperCase();
} else {
return "0" + Integer.toString(decimal, 16).toUpperCase();
}
}

private String encodeHexAscii(String code) {
int maxlinea = widthBytes * 2;
StringBuilder sbCode = new StringBuilder();
StringBuilder sbLinea = new StringBuilder();
String previousLine = null;
int counter = 1;
char aux = code.charAt(0);
boolean firstChar = false;
for (int i = 1; i < code.length(); i++) {
if (firstChar) {
aux = code.charAt(i);
firstChar = false;
continue;
}
if (code.charAt(i) == '\n') {
if (counter >= maxlinea && aux == '0') {
sbLinea.append(",");
} else if (counter >= maxlinea && aux == 'F') {
sbLinea.append("!");
} else if (counter > 20) {
int multi20 = (counter / 20) * 20;
int resto20 = (counter % 20);
sbLinea.append(mapCode.get(multi20));
if (resto20 != 0) {
sbLinea.append(mapCode.get(resto20)).append(aux);
} else {
sbLinea.append(aux);
}
} else {
sbLinea.append(mapCode.get(counter)).append(aux);
}
counter = 1;
firstChar = true;
if (sbLinea.toString().equals(previousLine)) {
sbCode.append(":");
} else {
sbCode.append(sbLinea.toString());
}
previousLine = sbLinea.toString();
sbLinea.setLength(0);
continue;
}
if (aux == code.charAt(i)) {
counter++;
} else {
if (counter > 20) {
int multi20 = (counter / 20) * 20;
int resto20 = (counter % 20);
sbLinea.append(mapCode.get(multi20));
if (resto20 != 0) {
sbLinea.append(mapCode.get(resto20)).append(aux);
} else {
sbLinea.append(aux);
}
} else {
sbLinea.append(mapCode.get(counter)).append(aux);
}
counter = 1;
aux = code.charAt(i);
}
}
return sbCode.toString();
}

public void setCompressHex(boolean compressHex) {
this.compressHex = compressHex;
}

public void setBlacknessLimitPercentage(int percentage) {
blackLimit = (percentage * 768 / 100);
}

}

Example usage:
You need to convert the your image to bitmap, convert to monochrome image and do hex acii conversion. The generated zpl code can be checked at labelary viewer.

public class Utils {

public static String getZplCode(Bitmap bitmap, Boolean addHeaderFooter) {
ZPLConverter zp = new ZPLConverter();
zp.setCompressHex(true);
zp.setBlacknessLimitPercentage(50);
Bitmap grayBitmap = toGrayScale(bitmap);
return zp.convertFromImage(grayBitmap, addHeaderFooter);
}

public static Bitmap toGrayScale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();

Bitmap grayScale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(grayScale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return grayScale;
}
}

The converter code has been referenced from here and added support for android use.

How to generate a dynamic GRF image to ZPL ZEBRA print

Try the following code. Not tested!

public static string CreateGRF(string filename, string imagename)
{
Bitmap bmp = null;
BitmapData imgData = null;
byte[] pixels;
int x, y, width;
StringBuilder sb;
IntPtr ptr;

try
{
bmp = new Bitmap(filename);
imgData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
width = (bmp.Width + 7) / 8;
pixels = new byte[width];
sb = new StringBuilder(width * bmp.Height * 2);
ptr = imgData.Scan0;
for (y = 0; y < bmp.Height; y++)
{
Marshal.Copy(ptr, pixels, 0, width);
for (x = 0; x < width; x++)
sb.AppendFormat("{0:X2}", (byte)~pixels[x]);
ptr = (IntPtr)(ptr.ToInt64() + imgData.Stride);
}
}
finally
{
if (bmp != null)
{
if (imgData != null) bmp.UnlockBits(imgData);
bmp.Dispose();
}
}
return String.Format("~DG{0}.GRF,{1},{2},", imagename, width * y, width) + sb.ToString();
}

How to use the ^DG command send image to a zebra printer in java?

It's not easy. You have to convert the image to 1-bit per pixel b/w, and then calculate the size including the bytes per row, and then properly form up the parameters of the ~DG command to store it.

Or...

Zebra provides an API to convert images to GRFs (Zebra internal image type). There are a bunch of developer demos in the package, including a demo on how to print/store an image as a GRF on your printer

Zebra Link-OS SDK download

Hope this helps



Related Topics



Leave a reply



Submit