I have to print some data on thermal bluetooth printer, I'm doing with this:
String message="abcdef any message 12345"; byte[] send; send = message.getBytes(); mService.write(send);
It works well for text, but not for images. I think I need to get the byte[]
of the image data. I tried getting the data of the image this way:
Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.qrcode); ByteArrayOutputStream stream=new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); byte[] image=stream.toByteArray();
Unfortunately the printer prints a lot of strange characters (approx. 50 cm of paper). I don't know how to print the image.
I would like to try getting the pixels of the bitmap and next converting it to a byte[]
and sending it, but i don't know how to do it.
Thanks
UPDATE:
After so much time, i'm doing this: I have a method called print_image(String file), the which gets the path of the image that i want to print:
private void print_image(String file) { File fl = new File(file); if (fl.exists()) { Bitmap bmp = BitmapFactory.decodeFile(file); convertBitmap(bmp); mService.write(PrinterCommands.SET_LINE_SPACING_24); int offset = 0; while (offset < bmp.getHeight()) { mService.write(PrinterCommands.SELECT_BIT_IMAGE_MODE); for (int x = 0; x < bmp.getWidth(); ++x) { for (int k = 0; k < 3; ++k) { byte slice = 0; for (int b = 0; b < 8; ++b) { int y = (((offset / 8) + k) * 8) + b; int i = (y * bmp.getWidth()) + x; boolean v = false; if (i < dots.length()) { v = dots.get(i); } slice |= (byte) ((v ? 1 : 0) << (7 - b)); } mService.write(slice); } } offset += 24; mService.write(PrinterCommands.FEED_LINE); mService.write(PrinterCommands.FEED_LINE); mService.write(PrinterCommands.FEED_LINE); mService.write(PrinterCommands.FEED_LINE); mService.write(PrinterCommands.FEED_LINE); mService.write(PrinterCommands.FEED_LINE); } mService.write(PrinterCommands.SET_LINE_SPACING_30); } else { Toast.makeText(this, "file doesn't exists", Toast.LENGTH_SHORT) .show(); } }
I did it based on this post
This is the class PrinterCommands:
public class PrinterCommands { public static final byte[] INIT = {27, 64}; public static byte[] FEED_LINE = {10}; public static byte[] SELECT_FONT_A = {27, 33, 0}; public static byte[] SET_BAR_CODE_HEIGHT = {29, 104, 100}; public static byte[] PRINT_BAR_CODE_1 = {29, 107, 2}; public static byte[] SEND_NULL_BYTE = {0x00}; public static byte[] SELECT_PRINT_SHEET = {0x1B, 0x63, 0x30, 0x02}; public static byte[] FEED_PAPER_AND_CUT = {0x1D, 0x56, 66, 0x00}; public static byte[] SELECT_CYRILLIC_CHARACTER_CODE_TABLE = {0x1B, 0x74, 0x11}; public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, -128, 0}; public static byte[] SET_LINE_SPACING_24 = {0x1B, 0x33, 24}; public static byte[] SET_LINE_SPACING_30 = {0x1B, 0x33, 30}; public static byte[] TRANSMIT_DLE_PRINTER_STATUS = {0x10, 0x04, 0x01}; public static byte[] TRANSMIT_DLE_OFFLINE_PRINTER_STATUS = {0x10, 0x04, 0x02}; public static byte[] TRANSMIT_DLE_ERROR_STATUS = {0x10, 0x04, 0x03}; public static byte[] TRANSMIT_DLE_ROLL_PAPER_SENSOR_STATUS = {0x10, 0x04, 0x04}; }
As is seen in the print_image method I'm calling a method, called convertBitmap, and im sending a bitmap, this is the code:
public String convertBitmap(Bitmap inputBitmap) { mWidth = inputBitmap.getWidth(); mHeight = inputBitmap.getHeight(); convertArgbToGrayscale(inputBitmap, mWidth, mHeight); mStatus = "ok"; return mStatus; } private void convertArgbToGrayscale(Bitmap bmpOriginal, int width, int height) { int pixel; int k = 0; int B = 0, G = 0, R = 0; dots = new BitSet(); try { for (int x = 0; x < height; x++) { for (int y = 0; y < width; y++) { // get one pixel color pixel = bmpOriginal.getPixel(y, x); // retrieve color of all channels R = Color.red(pixel); G = Color.green(pixel); B = Color.blue(pixel); // take conversion up to one single value by calculating // pixel intensity. R = G = B = (int) (0.299 * R + 0.587 * G + 0.114 * B); // set bit into bitset, by calculating the pixel's luma if (R < 55) { dots.set(k);//this is the bitset that i'm printing } k++; } } } catch (Exception e) { // TODO: handle exception Log.e(TAG, e.toString()); } }
This is the printer that i'm using, resolution: 8 dots/mm, 576 dots/line
And this is what I like to do (i did it with the same printer, but with an app downloaded from play store)
This is what i'm getting now
Closer:
Closer2:
A little part of the image can be seen, so I think that i'm closer to can print the image...
The image that i'm using is this (576x95):
And this is the converted image (i'm converting it with the upper code):
So, the answer is: what I'm doing wrong?, I think that the error is in this command:
public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, -128, 0};
But, how can I calculate the correct values for my image?, thanks
To print from android to Bluetooth printer: select a document in your android phone that you want to print. 3. Click on the menu of the document and select “share via Bluetooth.”
To do that, make sure your printer's Bluetooth setting is turned on and is discoverable. On your phone, start the Settings app, tap Connected devices and tap Pair new device. When your phone finds the Bluetooth printer, select it and complete the pairing process. Once paired, you should be able to print normally.
Connecting the Printer to Your Android DeviceGo to Settings > Wireless & Network and turn on Bluetooth. Wait while your device scans for the printer. The printer is displayed when your device finds it. Tap the printer.
I solve it converting Bitmap to Byte array. Remember that your image must be black & white format.
For full source code: https://github.com/imrankst1221/Thermal-Printer-in-Android
public void printPhoto() { try { Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.img); if(bmp!=null){ byte[] command = Utils.decodeBitmap(bmp); printText(command); }else{ Log.e("Print Photo error", "the file isn't exists"); } } catch (Exception e) { e.printStackTrace(); Log.e("PrintTools", "the file isn't exists"); } }
I also tried this and I got to my own solution and I think I figured out how the SELECT_BIT_IMAGE_MODE
command works.
The command public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, 255, 3};
in the class PrinterCommands
is the POS Command for image printing.
The first two are pretty standard, the next three determine the mode and the dimensions of the image to be printed. For the sake of this solution, let's just assume that the second element (33, we are indexed zero) is always 33.
The last two elements of that byte[] refers to the Width (in pixels) property of the image that you want to print, element 3 is sometimes referred to as nL
and element 4 is sometimes referred to as nH
. They are actually both referring to the Width, nL
is the Low Byte
while nH
is the High Byte
. This means that we can have at the most an image with a width of 1111 1111 1111 1111b (binary) which is 65535d (decimal), though I haven't tried it yet. If nL or nH aren't set to the proper values, then there will be trash characters printed along with the image.
Somehow, Android docs tells us that the limits of the value for a byte in a byte array is -128 and +127, when I tried to put in 255, Eclipse asked me to cast it to Byte.
Anyway, going back to nL and nW, for your case, you have an image with width 576, if we convert 576 to Binary, we get two bytes which would go like:
0000 0010 0100 0000
In this case, the Low Byte is 0100 0000
while the High Byte is 0000 0010
. Convert it back to decimal and we get nL = 64
and nH = 2
.
In my case, I printed an image that has width of 330px, converting 330 to binary we get:
0000 0001 0100 1010
In this case now, the Low Byte is 0100 1010
and the High Byte is 0000 0001
. Converting to decimal, we get nL = 74
and nH = 1
.
For more information, look at these documentation/tutorials:
Star Asia Mobile Printer Documentation
ECS-POS programming guide - really extensive
Another Documentation
The expanded version of the code above, with more explanation
Explanation of the code above
Hope these helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With