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
How to Place an Imageview on Top of Another Imageview in Android
How to Get Context in Android Mvvm Viewmodel
Error Androidmanifest.Xml Doesn't Exist or Has Incorrect Root Tag
How to Scroll Scrollview to Bottom Programmatically in Android
Convert File: Uri to File in Android
Android Studio - Textview Not Showing in Design View Layout
How to Remove the Black Bar Appearing At the Bottom
How to Restrict Entry of Numbers But Allow All the Special Characters and Alphabets in Edittext
Apk Signing Error:Failed to Read Key from Keystore
How to Remove Android Auto-Suggest Underlining in Edittext
Remove Old Fragment from Fragment Manager
How to Get the Currently Displayed Fragment
How to Hide Action Bar for Fragment
How to Completely Disable Selinux in Android L in the Init.Rc File
How to Fix Attempt to Invoke Interface Method on a Null Object Reference