web-dev-qa-db-fra.com

Comment imprimer une image sur une imprimante Bluetooth sous Android?

Je dois imprimer des données sur une imprimante thermique Bluetooth, je fais ça:

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

Cela fonctionne bien pour le texte, mais pas pour les images. Je pense que je dois obtenir le byte[] des données d'image. J'ai essayé d'obtenir les données de l'image de cette façon:

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

Malheureusement, l'imprimante imprime beaucoup de caractères étranges (environ 50 cm de papier). Je ne sais pas comment imprimer l'image.

Je voudrais essayer d'obtenir les pixels du bitmap et de le convertir ensuite en byte[] et l'envoyer, mais je ne sais pas comment le faire.

Merci

MISE À JOUR:

Après tant de temps, je fais ceci: j'ai une méthode appelée print_image (fichier String), qui obtient le chemin de l'image que je veux imprimer:

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

Je l'ai fait sur cette base post

Voici la classe 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};
}

Comme on le voit dans la méthode print_image j'appelle une méthode, appelée convertBitmap, et j'envoie un bitmap, voici le 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());
    }
}

Ceci est le imprimante que j'utilise, résolution: 8 points/mm, 576 points/ligne

Et c'est ce que j'aime faire (je l'ai fait avec la même imprimante, mais avec une application téléchargée sur Play Store) Image that I want to print

C'est ce que je reçois maintenant My printing trying

Plus proche: A closer part

Closer2: enter image description here

Une petite partie de l'image peut être vue, donc je pense que je suis plus près de pouvoir imprimer l'image ...

L'image que j'utilise est la suivante (576x95):enter image description here

Et voici l'image convertie (je la convertis avec le code supérieur): converted image

Inverted

Donc, la réponse est: qu'est-ce que je fais mal?, Je pense que l'erreur est dans cette commande:

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

Mais, comment puis-je calculer les valeurs correctes pour mon image?, Merci

46
Leonardo Sapuy

Résolu !, Je faisais une mauvaise imprimante lors de l'initialisation ... La bonne façon est:

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

Ainsi, de cette façon, l'image est imprimée très bien

9
Leonardo Sapuy

Je le résous en convertissant Bitmap en tableau d'octets. N'oubliez pas que votre image doit être au format noir et blanc.

Pour le code source complet: 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
Md Imran Choudhury

J'ai aussi essayé cela et j'ai trouvé ma propre solution et je pense avoir compris comment le SELECT_BIT_IMAGE_MODE la commande fonctionne.

La commande public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, 255, 3}; dans la classe PrinterCommands est la commande POS pour l'impression d'images.

Les deux premiers sont assez standard, les trois suivants déterminent le mode et les dimensions de l'image à imprimer. Pour cette solution, supposons simplement que le deuxième élément (33, nous sommes indexés zéro) est toujours 33.

Les deux derniers éléments de cet octet [] font référence à la propriété Largeur (en pixels) de l'image que vous souhaitez imprimer, l'élément 3 est parfois appelé à nL et l'élément 4 est parfois appelé nH. Ils font tous deux référence à la largeur, nL est le Low Byte tandis que nH est le High Byte. Cela signifie que nous pouvons avoir au maximum une image d'une largeur de 1111 1111 1111 1111b (binaire) qui est 65535d (décimal), bien que je ne l'ai pas encore essayé. Si nL ou nH ne sont pas définis sur les valeurs appropriées, des caractères de corbeille seront imprimés avec l'image.

D'une manière ou d'une autre, Android docs nous dit que les limites de la valeur d'un octet dans un tableau d'octets sont -128 et +127, lorsque j'ai essayé d'en mettre 255, Eclipse m'a demandé de le convertir en Octet.

Quoi qu'il en soit, pour revenir à nL et nW, pour votre cas, vous avez une image de largeur 576, si nous convertissons 576 en binaire, nous obtenons deux octets qui ressembleraient à:

0000 0010 0100 0000

Dans ce cas, l'octet bas est 0100 0000 tandis que le High Byte est 0000 0010. Convertissez-le en décimal et nous obtenons nL = 64 et nH = 2.

Dans mon cas, j'ai imprimé une image qui a une largeur de 330 pixels, en convertissant 330 en binaire, nous obtenons:

0000 0001 0100 1010

Dans ce cas maintenant, le Low Byte est 0100 1010 et l'octet supérieur est 0000 0001. En convertissant en décimal, nous obtenons nL = 74 et nH = 1.

Pour plus d'informations, consultez ces documentations/tutoriels:

Documentation de l'imprimante mobile Star Asia

Guide de programmation ECS-POS - très complet

ne autre documentation

La version développée du code ci-dessus, avec plus d'explications

Explication du code ci-dessus

J'espère que ces aides.

9
Razgriz

[~ # ~] modifier [~ # ~] : mise à jour basée sur la lecture de votre question: https://stackoverflow.com/questions/16597789/print-bitmap-on-esc-pos-printer-Java

Je suppose que l'imprimante sur laquelle vous imprimez est la même que ci-dessus, c'est-à-dire l'imprimante thermique Rego. Comme vous le constatez, cela prend en charge le ESC/POS Page Description Language .


Les imprimantes interprètent les données qui leur sont transmises comme un document balisé (de la même manière que le navigateur interprète le HTML). Dans certains cas, l'imprimante exécute littéralement le document en tant que programme (par exemple PostScript). Lien: Langages de description de page .

Les langues courantes sont:

Vous devez lire les spécifications de votre imprimante pour déterminer la langue à utiliser - si vous devez prendre en charge l'imprimante n'importe laquelle, alors vous avez un très gros travail devant vous :(

Dans ESC/POS, vous devrez utiliser le GS v 0 commande (documentée à la p33). Pour ce faire, envoyez les caractères 0x1D7630 sur la liaison série, suivi d'un ensemble d'arguments:

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 

Définitions des paramètres:

  • m:
    • 0,48: mode normal (échelle 1: 1)
    • 1,49: double largeur
    • 2,50: double hauteur
    • 3,51: double largeur + double hauteur
  • xL, xH spécifie (xL + xH × 256) octets dans le sens horizontal pour l'image bit.
  • yL, yH spécifie (yL + yH × 256) des points dans la direction verticale pour l'image binaire.
  • [d] k spécifie les données d'image bit (format raster).
  • k indique le nombre de données d'image bit. k est un paramètre d'explication; par conséquent, il n'a pas besoin d'être transmis.

Remarques:

  • Lorsque data [d] k vaut 1, spécifie un bit imprimé à 1 et non imprimé à 0.
  • Si une image bit raster dépasse une ligne de la zone d'impression, les données en excès ne sont pas imprimées.
  • Cette commande exécute l'alimentation papier pour la quantité nécessaire à l'impression de l'image bit, quels que soient les paramètres définis par ESC 2 ou ESC 3.
  • Après avoir imprimé l'image bit, cette commande définit la position d'impression au début de la ligne et vide le tampon.
  • Lorsque cette commande est exécutée, les données sont transmises et imprimées de manière synchrone. Aucune autre commande d'impression n'est donc requise.

Il existe plusieurs expositions plus étendues:


Malheureusement, il n'y a pas d'API d'imprimante dans Android. Si cela vous tient à cœur, suivez ces points:

8
Andrew Alcock

Je suis nouveau à ESC/POS et je lutte avec lui. Je suis tombé sur cette page qui semble avoir des fonctions utiles: http://code.taobao.org/p/printer/src/trunk/prtest/src/com/enjar/plugins/PrintTools_58mm.Java = C'est en chinois cependant, mais ça pourrait valoir le coup. Si quelqu'un le comprend, j'aimerais aussi être éclairé ...

3
just some guy

Je connais les imprimantes Bluetooth évoluées et AMDL. Lisez d'abord le document de définition du protocole de l'imprimante qui vous indique les octets spécifiques dont vous avez besoin pour le périphérique.

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

}

Après vous être connecté via le code ci-dessus, vous obtenez le flux de sortie du socket.Puis convertissez votre image en octet correspondant via l'outil fourni avec l'imprimante, vous obtenez quelque chose comme

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

où 8A est l'octet de départ C6 est l'octet de mode (différent pour la carte à puce, le balayage et l'empreinte digitale), 94 est l'octet de police et le dernier octet 04 est l'octet de fin indiquant au matériel qu'il s'agit de la fin du paquet. Selon la taille de l'image que vous obtenir plusieurs de ces paquets de longueur 256 octets (la plupart des imprimantes). Ecrivez-les dans outputStream.

os.write(Packet1)
2
mjosh