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)
C'est ce que je reçois maintenant
Plus proche:
Closer2:
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):
Et voici l'image convertie (je la convertis avec le code supérieur):
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
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
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
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");
}
}
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
La version développée du code ci-dessus, avec plus d'explications
J'espère que ces aides.
[~ # ~] 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:
Remarques:
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:
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é ...
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)