私はサーマルBluetoothプリンターでいくつかのデータを印刷する必要があります、私はこれでやっています:
String message="abcdef any message 12345";
byte[] send;
send = message.getBytes();
mService.write(send);
テキストには適していますが、画像には適していません。画像データのbyte[]
を取得する必要があると思います。この方法で画像のデータを取得しようとしました:
Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.qrcode);
ByteArrayOutputStream stream=new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
byte[] image=stream.toByteArray();
残念ながら、プリンターは奇妙な文字をたくさん印刷します(約50 cmの紙)。画像の印刷方法がわかりません。
ビットマップのピクセルを取得して、次にそれをbyte[]
に変換して送信してみたいと思いますが、どうすればいいのかわかりません。
ありがとう
UPDATE:
かなりの時間が経った後、私はこれをやっています:print_image(String file)というメソッドがあり、これは印刷したい画像のパスを取得します:
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();
}
}
私はこれに基づいてそれをしました post
これは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};
}
Print_imageメソッドで見られるように、私はconvertBitmapと呼ばれるメソッドを呼び出しており、ビットマップを送信しています。これはコードです:
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());
}
}
これは プリンター 私が使用している、解像度:8ドット/ mm、576ドット/行
そして、これは私がやりたいことです(同じプリンターで行いましたが、Playストアからアプリをダウンロードしました)
これは私が今得ているものです
クローザー:
Closer2:
画像の少しの部分が見えるので、私は画像を印刷するのに近いと思います...
私が使用している画像はこれです(576x95):
そして、これは変換された画像です(私はそれを上のコードで変換しています):
だから、答えは次のとおりです:私が間違っているのは何ですか?、私はエラーがこのコマンドにあると思う:
public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, -128, 0};
しかし、どのように画像の正しい値を計算できますか?、ありがとう
解決!、間違ったプリンターの初期化を行っていました...正しい方法は:
public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, 255, 3};
したがって、この方法で画像は完全にきれいに印刷されます
ビットマップをバイト配列に変換して解決します。画像は白黒フォーマットでなければならないことに注意してください。
完全なソースコードの場合: 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");
}
}
私もこれを試してみましたが、私は自分の解決策に着手し、どのようにSELECT_BIT_IMAGE_MODE
コマンドは機能します。
コマンド public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, 255, 3};
クラスのPrinterCommands
は、画像印刷用のPOSコマンドです。
最初の2つはかなり標準的なもので、次の3つは印刷する画像のモードとサイズを決定します。このソリューションのために、2番目の要素(33、インデックスはゼロ)は常に33であると仮定します。
そのbyte []の最後の2つの要素は、印刷する画像のWidth(ピクセル単位)プロパティを参照します。要素3は時々参照されますto nL
として、要素4はnH
として参照されることがあります。これらは実際には両方とも幅を参照しています。nL
はLow Byte
nH
はHigh Byte
。これは、まだ試したことはありませんが、最大で11535 1111 1111 1111b(バイナリ)の幅65535d(10進数)の画像を作成できることを意味します。 nLまたはnHが適切な値に設定されていない場合、画像とともにゴミ文字が印刷されます。
どういうわけか、Android docsは、バイト配列のバイトの値の制限が-128と+127であることを教えてくれました。255を入れようとすると、Eclipseはバイト。
とにかく、nLとnWに戻ると、あなたの場合、幅576の画像があります。576をバイナリに変換すると、次のような2バイトになります。
0000 0010 0100 0000
この場合、下位バイトは0100 0000
上位バイトが0000 0010
。 10進数に戻すと、nL = 64
およびnH = 2
。
私の場合、幅330ピクセルの画像を印刷し、330をバイナリに変換します:
0000 0001 0100 1010
この場合、低バイトは0100 1010
および上位バイトは0000 0001
。 10進数に変換すると、nL = 74
およびnH = 1
。
詳細については、次のドキュメント/チュートリアルをご覧ください。
これらが役立つことを願っています。
[〜#〜] edit [〜#〜]:質問の読み取りに基づいて更新します: https://stackoverflow.com/questions/16597789/print-bitmap-on-esc-pos-printer-Java
印刷先のプリンター、つまりRego Thermal Printerは上記と同じであると想定します。ご指摘のとおり、これは ESC/POSページ記述言語 をサポートします。
プリンターは、ストリームされたデータをマークアップされたドキュメントとして解釈します(ブラウザーがHTMLを解釈する方法と同様の方法で)。場合によっては、プリンターは文字通りドキュメントをプログラム(PostScriptなど)として実行します。リンク: ページ記述言語 。
一般的な言語は次のとおりです。
使用する言語を決定するには、プリンターの仕様を読む必要があります-anyプリンターをサポートする必要がある場合は、前に非常に大きな仕事があります:(
ESC/POSでは、GS v 0
コマンド(p33に記載)を使用する必要があります。これを行うには、シリアルリンクを介して文字0x1D7630
を送信し、その後に一連の引数を送信します。
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
パラメータ定義:
ノート:
さらに大規模な説明がいくつかあります。
残念ながら、AndroidにはプリンターAPIはありません。これについて強く感じている場合は、次の問題に従ってください。
私はESC/POSが初めてで、それに苦労しています。いくつかの便利な機能があると思われるこのページに出会いました: http://code.taobao.org/p/printer/src/trunk/prtest/src/com/enjar/plugins/PrintTools_58mm.Java =ただし、中国語ですが、通してみる価値があるかもしれません。誰かがそれを理解したら、私も悟りたいです...
EvoluteおよびAMDL Bluetoothプリンターについて知っています。最初に、プリンターに必要な特定のバイトを示すプリンターのプロトコル定義文書を読んでください。
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();
}
上記のコードを介して接続した後、ソケットの出力ストリームを取得します。次に、プリンタに付属のツールを使用して、画像を対応するバイトに変換します。
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
};
8Aは開始バイトC6はモードバイト(スマートカード、スワイプ、指紋で異なる)、94はフォントバイト、最後のバイト04はハードウェアにこれがパケットの終わりであることを伝える終了バイトです。画像のサイズに応じて長さ256バイト(ほとんどのプリンター)のこれらのパケットをいくつか取得します。それらをoutputStreamに書き込みます。
os.write(Packet1)