¿Cómo puedo imprimir una imagen en una impresora Bluetooth en Android?

Tengo que imprimir algunos datos en la impresora térmica bluetooth, estoy haciendo esto:

String message="abcdef any message 12345"; byte[] send; send = message.getBytes(); mService.write(send); 

Funciona bien para texto, pero no para imágenes. Creo que necesito obtener el byte[] de los datos de la imagen. Intenté obtener los datos de la imagen de esta manera:

 Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.qrcode); ByteArrayOutputStream stream=new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); byte[] image=stream.toByteArray(); 

Lamentablemente, la impresora imprime muchos caracteres extraños (aproximadamente 50 cm de papel). No sé cómo imprimir la imagen.

Me gustaría intentar obtener los píxeles del bitmap y luego convertirlo en un byte[] y enviarlo, pero no sé cómo hacerlo.

Gracias

ACTUALIZAR:

Después de tanto tiempo, estoy haciendo esto: tengo un método llamado print_image (archivo String), que obtiene la ruta de la imagen que quiero imprimir:

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

Lo hice basado en esta publicación

Esta es la clase 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}; } 

Como se ve en el método print_image Estoy llamando a un método, llamado convertBitmap, y estoy enviando un bitmap, este es el código:

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

Esta es la impresora que estoy usando, resolución: 8 puntos / mm, 576 puntos / línea

Y esto es lo que me gusta hacer (lo hice con la misma impresora, pero con una aplicación descargada de Play Store) Imagen que quiero imprimir

Esto es lo que estoy obteniendo ahora Mi intento de impresión

Cerca: Una parte más cercana

Closer2: enter image description here

Se puede ver una pequeña parte de la imagen, así que creo que estoy más cerca de poder imprimir la imagen …

La imagen que estoy usando es esta (576×95): enter image description here

Y esta es la imagen convertida (la estoy convirtiendo con el código superior): imagen convertida

Invertido

Entonces, la respuesta es: ¿qué estoy haciendo mal ?, creo que el error está en este comando:

  public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, -128, 0}; 

Pero, ¿cómo puedo calcular los valores correctos para mi imagen ?, gracias

¡Resuelto! Estaba haciendo una inicialización errónea de la impresora … La forma correcta es:

  public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, 255, 3}; 

Por lo tanto, de esta manera la imagen se imprime completamente bien

Lo resuelvo convirtiendo Bitmap a Byte array. Recuerde que su imagen debe ser en blanco y negro.

Para obtener el código fuente completo: https://github.com/imrankst1221/Thermal-Printer-in-Android

enter image description here

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

EDITAR : Actualización basada en la lectura de su pregunta: https://stackoverflow.com/questions/16597789/print-bitmap-on-esc-pos-printer-java

Supongo que la impresora a la que está imprimiendo es la misma que la anterior, es decir, la Impresora térmica Rego. Esto, como usted nota, es compatible con el Lenguaje de descripción de página de ESC / POS .


Las impresoras interpretan los datos transmitidos a ellos como un documento marcado (de forma similar a cómo el navegador interpreta el HTML). En algunos casos, la impresora ejecuta literalmente el documento como un progtwig (por ejemplo, PostScript). Enlace: Idiomas de descripción de página .

Los idiomas comunes son:

  • Atentamente : ESC / POS .
  • Posdata
  • PCL
  • ZPL

Debe leer las especificaciones de su impresora para determinar qué idioma usar; si necesita admitir una impresora, entonces tiene un gran trabajo por delante 🙁

En ESC / POS, necesitará usar el comando GS v 0 (documentado en p33). Para ello, envíe los caracteres 0x1D7630 través del enlace en serie, seguidos de un conjunto de argumentos:

 ASCII: Gs v 0 Decimal: 29 118 48 m xL xH yL yH [d]k Hexadecimal: 1D 76 30 m xL xH yL yH [d]k 

Definiciones de parámetros:

  • metro:
    • 0,48: modo normal (escala 1: 1)
    • 1,49: doble ancho
    • 2,50: doble altura
    • 3,51: doble ancho + doble altura
  • xL, xH especifica (xL + xH × 256) bytes en dirección horizontal para la imagen de bit.
  • yL, yH especifica (yL + yH × 256) puntos en dirección vertical para la imagen de bit.
  • [d] k especifica los datos de imagen de bit (formato raster).
  • k indica la cantidad de datos de imagen de bit. k es un parámetro de explicación; por lo tanto, no necesita ser transmitido.

Notas:

  • Cuando los datos [d] k son 1, se especifica un bit impreso en 1 y no impreso en 0.
  • Si una imagen de bit ráster excede una línea del área de impresión, el exceso de datos no se imprime.
  • Este comando ejecuta la alimentación de papel para la cantidad necesaria para imprimir la imagen de bit independientemente de la configuración mediante ESC 2 o ESC 3.
  • Después de imprimir la imagen de bit, este comando establece la posición de impresión al comienzo de la línea y borra el búfer.
  • Cuando se ejecuta este comando, los datos se transmiten e imprimen de forma síncrona. Por lo tanto, no se requiere ningún otro comando de impresión.

Hay varias exposiciones más extensas:


Lamentablemente, no hay una API de impresora en Android. Si tiene una opinión fuerte sobre esto, siga estos problemas:

También probé esto y obtuve mi propia solución y creo que descubrí cómo funciona el comando SELECT_BIT_IMAGE_MODE .

El comando public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, 255, 3}; en la clase PrinterCommands es el comando POS para la impresión de imágenes.

Los primeros dos son bastante estándar, los siguientes tres determinan el modo y las dimensiones de la imagen que se imprimirá. Por el bien de esta solución, supongamos que el segundo elemento (33, estamos indexados a cero) siempre es 33.

Los dos últimos elementos de ese byte [] se refieren a la propiedad Ancho (en píxeles) de la imagen que desea imprimir, el elemento 3 a veces se denomina nL y el elemento 4 a veces se denomina nH . En realidad, ambos se refieren al ancho, nL es el Low Byte mientras nH es el High Byte . Esto significa que podemos tener como máximo una imagen con un ancho de 1111 1111 1111 1111b (binario) que es 65535d (decimal), aunque todavía no lo he probado. Si nL o nH no están configurados en los valores correctos, se imprimirán caracteres de papelera junto con la imagen.

De alguna manera, los documentos de Android nos dicen que los límites del valor para un byte en una matriz de bytes es -128 y +127, cuando traté de poner 255, Eclipse me pidió que lo transfiriera a Byte.

De todos modos, volviendo a nL y nW, para su caso, tiene una imagen con ancho 576, si convertimos 576 a Binario, obtenemos dos bytes que serían como:

0000 0010 0100 0000

En este caso, Low Byte es 0100 0000 mientras que High Byte es 0000 0010 . Convierta nuevamente a decimal y obtenemos nL = 64 y nH = 2 .

En mi caso, imprimí una imagen que tiene un ancho de 330px, convirtiendo 330 en binario que obtenemos:

0000 0001 0100 1010

En este caso ahora, el byte bajo es 0100 1010 y el byte alto es 0000 0001 . Convirtiendo a decimal, obtenemos nL = 74 y nH = 1 .

Para obtener más información, consulte estos documentos / tutoriales:

Documentación de la impresora móvil Star Asia

Guía de progtwigción ECS-POS – realmente extensa

Otra documentación

La versión ampliada del código anterior, con más explicaciones

Explicación del código anterior

Espero que esto ayude

Conozco las impresoras bluetooth evolute y AMDL. Primero, lea el documento de definación de protocolo de la impresora que le dice qué bytes específicos necesita para el dispositivo.

 public void connect() throws Exception { BluetoothDevice printer = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(connParams); Method m = printer.getClass().getMethod("createInsecureRfcommSocket",new Class[] { int.class }); sock = (BluetoothSocket)m.invoke(printer, Integer.valueOf(1)); sock.connect(); os=sock.getOutputStream(); in=sock.getInputStream(); } 

Después de conectarse a través del código anterior, obtendrá la salida del zócalo. Luego convierta su imagen al byte correspondiente a través de la herramienta provista con la impresora, obtendrá algo como

 public byte[] Packet1={ (byte)0X8A,(byte)0XC6,(byte)0X94,(byte)0XF4,(byte)0X0B,(byte)0X5E,(byte)0X30,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X04,(byte)0X24,(byte)0X01,(byte)0X0C,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X01,(byte)0X08,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X04,(byte)0X24,(byte)0X05,(byte)0X0C,(byte)0X00,(byte)0X60,(byte)0X00,(byte)0X18,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X30,(byte)0X1E,(byte)0X10,(byte)0X60,(byte)0X00,(byte)0X18,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X70,(byte)0X3F,(byte)0X18,(byte)0XF0,(byte)0X00,(byte)0X3E,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X70,(byte)0X3C,(byte)0X39,(byte)0XF1,(byte)0X80,(byte)0X3E,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0XF8,(byte)0X7C,(byte)0X9F,(byte)0XF1,(byte)0X80,(byte)0X7F,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0XF9,(byte)0X9E,(byte)0X1C,(byte)0XFF,(byte)0XC2,(byte)0X7E,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0XF9,(byte)0X9E,(byte)0X1C,(byte)0XE7,(byte)0XE2,(byte)0X7E,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0XFB,(byte)0X1E,(byte)0X1C,(byte)0XFF,(byte)0XE7,(byte)0XBE,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X7B,(byte)0X16,(byte)0X1C,(byte)0XFF,(byte)0XDF,(byte)0X3E,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X71,(byte)0X12,(byte)0X1C,(byte)0XE7,(byte)0XF7,(byte)0X34,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X51,(byte)0X12,(byte)0X1C,(byte)0XF7,(byte)0XF7,(byte)0X24,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X49,(byte)0X12,(byte)0X1C,(byte)0XFF,(byte)0XF3,(byte)0X24,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X49,(byte)0X12,(byte)0X3F,(byte)0XFD,(byte)0XF3,(byte)0X24,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0X49,(byte)0X96,(byte)0X3F,(byte)0XFC,(byte)0XF3,(byte)0X24,(byte)0X5E,(byte)0X27,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X05,(byte)0X49,(byte)0X80,(byte)0X00,(byte)0X08,(byte)0X10,(byte)0X5E,(byte)0X28,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X30,(byte)0X25,(byte) 0X01,(byte)0X5E,(byte)0X03,(byte)0X24,(byte)0X06,(byte)0XE0,(byte)0X74,(byte)0XA9,(byte)0X33,(byte)0X23,(byte)0X26,(byte)0X5E,(byte)0X27,(byte)0X25,(byte)0X04 }; 

donde 8A está comenzando byte C6 es byte de modo (diferente para tarjeta inteligente, deslizamiento y huella dactilar), 94 es byte de fuente y último byte 04 es el byte final que le dice al hardware que este es el final del paquete. Dependiendo del tamaño de la imagen usted obtenga varios de estos paquetes de 256 bytes de longitud (la mayoría de las impresoras). Escríbalas en outputStream.

 os.write(Packet1) 

Soy nuevo en ESC / POS y estoy luchando con eso. Encontré esta página que parece tener algunas funciones útiles: http://code.taobao.org/p/printer/src/trunk/prtest/src/com/enjar/plugins/PrintTools_58mm.java Está en chino, pero podría valer la pena. Si alguien lo descubre, me gustaría iluminarme también …

usa este código:

 public static void print(Context context) { String examplePath = "file:///sdcard/dcim/Camera/20111210_181524.jpg"; Intent sendIntent = new Intent(Intent.ACTION_SEND); sendIntent.setType("image/jpeg"); sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Photo"); sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(examplePath)); sendIntent.putExtra(Intent.EXTRA_TEXT, "Enjoy the photo"); context.startActivity(Intent.createChooser(sendIntent, "Email:")); }