it-swarm.com.de

Wie kann ich ein Bild auf einem Bluetooth-Drucker in Android drucken?

Ich muss einige Daten auf einem Bluetooth-Thermodrucker drucken. Dabei mache ich Folgendes:

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

Es funktioniert gut für Text, aber nicht für Bilder. Ich glaube, ich muss den byte[] Der Bilddaten abrufen. Ich habe versucht, die Daten des Bildes auf folgende Weise abzurufen:

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

Leider druckt der Drucker viele seltsame Zeichen (ca. 50 cm Papier). Ich weiß nicht, wie ich das Bild ausdrucken soll.

Ich würde gerne versuchen, die Pixel der Bitmap zu bekommen und sie als nächstes in einen byte[] Umzuwandeln und zu senden, aber ich weiß nicht, wie ich das machen soll.

Vielen Dank

UPDATE:

Nach so viel Zeit mache ich Folgendes: Ich habe eine Methode namens print_image (String-Datei), die den Pfad des Bildes abruft, das ich drucken möchte:

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

Ich habe es basierend auf diesem Beitrag gemacht

Dies ist die Klasse 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};
}

Wie in der print_image-Methode zu sehen ist, rufe ich eine Methode namens convertBitmap auf und sende eine Bitmap. Dies ist der 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());
    }
}

Dies ist das Drucker , das ich verwende, Auflösung: 8 Punkte/mm, 576 Punkte/Zeile

Und das ist, was ich gerne mache (ich habe es mit demselben Drucker gemacht, aber mit einer App, die aus dem Play Store heruntergeladen wurde) Image that I want to print

Das ist es, was ich jetzt bekomme My printing trying

Näher: A closer part

Closer2: enter image description here

Ein kleiner Teil des Bildes ist zu sehen, daher denke ich, dass ich näher dran bin, um das Bild zu drucken ...

Das Bild, das ich benutze, ist dieses (576x95):enter image description here

Und dies ist das konvertierte Bild (ich konvertiere es mit dem oberen Code): converted image

Inverted

Die Antwort lautet also: Was mache ich falsch? Ich denke, dass der Fehler in diesem Befehl liegt:

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

Aber wie kann ich die korrekten Werte für mein Bild berechnen ?, danke

46
Leonardo Sapuy

Behoben !, ich habe einen falschen Drucker initialisiert ... Der richtige Weg ist:

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

Auf diese Weise wird das Bild vollständig fein gedruckt

9
Leonardo Sapuy

Ich löse es Bitmap in Byte Array konvertieren. Denken Sie daran, dass Ihr Bild schwarz-weiß sein muss.

Für den vollständigen Quellcode: 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");
        }
    }
14

Ich habe es auch versucht und bin zu meiner eigenen Lösung gekommen. Ich glaube, ich habe herausgefunden, wie der Befehl SELECT_BIT_IMAGE_MODE Funktioniert.

Der Befehl public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, 255, 3}; In der Klasse PrinterCommands ist der POS-Befehl zum Drucken von Bildern.

Die ersten beiden sind ziemlich normal, die nächsten drei bestimmen den Modus und die Abmessungen des zu druckenden Bildes. Für diese Lösung nehmen wir einfach an, dass das zweite Element (33, wir sind mit Null indiziert) immer 33 ist.

Die letzten beiden Elemente dieses Bytes [] beziehen sich auf die Eigenschaft Breite (in Pixel) des zu druckenden Bilds. Manchmal wird auf Element 3 verwiesen bis als nL und Element 4 wird manchmal als nH bezeichnet. Sie beziehen sich beide auf die Breite, nL ist der Low Byte, Während nH der High Byte Ist. Dies bedeutet, dass wir höchstens ein Bild mit einer Breite von 1111 1111 1111 1111b (binär) haben können, das 65535d (dezimal) ist, obwohl ich es noch nicht ausprobiert habe. Wenn nL oder nH nicht auf die richtigen Werte eingestellt sind, werden Papierkorbzeichen zusammen mit dem Bild gedruckt.

Irgendwie sagt uns Android docs, dass die Grenzen des Werts für ein Byte in einem Byte-Array -128 und +127 sind, als ich versuchte, 255 einzugeben, bat Eclipse mich, es in das Format umzuwandeln Byte.

Wie auch immer, wenn Sie zurück zu nL und nW gehen, haben Sie für Ihren Fall ein Bild mit der Breite 576. Wenn wir 576 in Binary konvertieren, erhalten wir zwei Bytes, die wie folgt lauten:

0000 0010 0100 0000

In diesem Fall ist das untere Byte 0100 0000, Während das obere Byte 0000 0010 Ist. Wandle es zurück in eine Dezimalzahl und wir erhalten nL = 64 Und nH = 2.

In meinem Fall habe ich ein Bild mit einer Breite von 330px gedruckt und dabei 330 in binär konvertiert.

0000 0001 0100 1010

In diesem Fall ist das untere Byte jetzt 0100 1010 Und das obere Byte ist 0000 0001. Bei der Umrechnung in eine Dezimalzahl erhalten wir nL = 74 Und nH = 1.

Weitere Informationen finden Sie in den folgenden Dokumentationen/Tutorials:

Star Asia Mobile-Druckerdokumentation

ECS-POS Programmieranleitung - sehr umfangreich

Eine andere Dokumentation

Die erweiterte Version des obigen Codes mit weiteren Erläuterungen

Erklärung des obigen Codes

Hoffe das hilft.

9
Razgriz

[~ # ~] edit [~ # ~] : Update basierend auf dem Lesen Ihrer Frage: https://stackoverflow.com/questions/16597789/print-bitmap-on-esc-pos-printer-Java

Ich gehe davon aus, dass der Drucker, auf dem Sie drucken, derselbe wie oben ist, d. H. Der Rego-Thermodrucker. Wie Sie bemerken, unterstützt dies die ESC/POS-Seitenbeschreibungssprache .


Drucker interpretieren die zu ihnen gestreamten Daten entweder als markiertes Dokument (ähnlich wie der Browser HTML interpretiert). In einigen Fällen führt der Drucker das Dokument buchstäblich als Programm aus (z. B. PostScript). Link: Seitenbeschreibungssprachen .

Gemeinsame Sprachen sind:

Sie müssen die technischen Daten Ihres Druckers lesen, um die zu verwendende Sprache zu bestimmen. Wenn Sie any Drucker unterstützen müssen, haben Sie einen sehr großen Auftrag vor sich :(

In ESC/POS müssen Sie das GS v 0 Befehl (dokumentiert auf S. 33). Dazu senden Sie die Zeichen 0x1D7630 über die serielle Verbindung, gefolgt von einer Reihe von Argumenten:

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 

Parameterdefinitionen:

  • m:
    • 0,48: Normalmodus (Maßstab 1: 1)
    • 1,49: doppelte Breite
    • 2,50: doppelte Höhe
    • 3,51: doppelte Breite + doppelte Höhe
  • xL, xH spezifiziert (xL + xH × 256) Bytes in horizontaler Richtung für das Bitbild.
  • yL, yH spezifiziert (yL + yH × 256) Punkte in vertikaler Richtung für das Bitbild.
  • [d] k gibt die Bitbilddaten an (Rasterformat).
  • k gibt die Anzahl der Bitbilddaten an. k ist ein Erklärungsparameter; Daher muss es nicht übertragen werden.

Anmerkungen:

  • Wenn Daten [d] k 1 ist, gibt dies ein Bit an, das auf 1 gedruckt und nicht auf 0 gedruckt wird.
  • Wenn ein Raster-Bit-Bild eine Zeile des Druckbereichs überschreitet, werden die überschüssigen Daten nicht gedruckt.
  • Dieser Befehl führt unabhängig von den Einstellungen von ESC 2 oder ESC 3 einen Papiervorschub für den zum Drucken des Bitbilds erforderlichen Betrag aus.
  • Nach dem Drucken des Bitbilds setzt dieser Befehl die Druckposition an den Zeilenanfang und löscht den Puffer.
  • Wenn dieser Befehl ausgeführt wird, werden die Daten synchron übertragen und gedruckt. Es ist also kein weiterer Druckbefehl erforderlich.

Es gibt mehrere ausführlichere Ausstellungen:


Leider gibt es in Android keine Drucker-API. Wenn Sie dies sehr ernst nehmen, befolgen Sie die folgenden Punkte:

8
Andrew Alcock

Ich bin neu in ESC/POS und habe Probleme damit. Ich bin auf diese Seite gestoßen, die einige nützliche Funktionen zu haben scheint: http://code.taobao.org/p/printer/src/trunk/prtest/src/com/enjar/plugins/PrintTools_58mm.Java = Es ist zwar auf Chinesisch, aber es könnte sich lohnen, es durchzuarbeiten. Wenn jemand es herausfindet, möchte ich auch aufgeklärt werden ...

3
just some guy

Ich kenne Evolute- und AMDL-Bluetooth-Drucker. Lesen Sie zunächst das Protokolldefinitionsdokument des Druckers, in dem angegeben ist, welche spezifischen Bytes für das Gerät erforderlich sind.

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

}

Nach dem Anschließen über den obigen Code erhalten Sie den Ausgabestream des Sockets. Dann konvertieren Sie Ihr Bild in das entsprechende Byte mit dem Tool, das mit dem Drucker geliefert wurde

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

wobei 8A das Startbyte C6 das Modusbyte ist (anders für Smartcard, Swipe und Fingerprint), 94 das Schriftartbyte und das letzte Byte 04 das Endbyte, das der Hardware mitteilt, dass dies das Ende des Pakets ist Holen Sie sich mehrere dieser Pakete mit einer Länge von 256 Byte (die meisten Drucker). Schreiben Sie sie in den outputStream.

os.write(Packet1)
2
mjosh