57

サーマル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[]送信したいのですが、その方法がわかりません。

ありがとう

アップデート:

長い間、私はこれをやっています:私は印刷したい画像のパスを取得する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();
    }
}

この記事を参考に作りました

これはクラス 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 ドット/ライン

そして、これは私がやりたいことです(私は同じプリンターでそれをしましたが、プレイストアからダウンロードしたアプリを使用しました) 印刷したい画像

これは私が今得ているものです 私の印刷の試み

クローザー: より近い部分

クローザー2: ここに画像の説明を入力

画像の一部が見えているので、画像を印刷するのに近いと思います...

私が使用している画像はこれです(576x95):ここに画像の説明を入力

そして、これは変換された画像です(私は上のコードで変換しています): 変換された画像

反転

だから、答えは: 私が間違っているのは何ですか?, エラーは次のコマンドにあると思います:

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

しかし、どうすれば自分の画像の正しい値を計算できますか?, ありがとう

4

8 に答える 8

14

SELECT_BIT_IMAGE_MODE私もこれを試してみましたが、私は自分の解決策にたどり着きました。コマンドがどのように機能するかを理解したと思います。

このpublic static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, 255, 3};クラスのコマンドは、PrinterCommandsイメージ印刷用の POS コマンドです。

最初の 2 つはかなり標準的なもので、次の 3 つは印刷するイメージのモードと寸法を決定します。この解決策のために、2 番目の要素 (33、インデックスは 0 です) が常に 33 であると仮定しましょう。

その byte[] の最後の 2 つの要素は、印刷するイメージの幅 (ピクセル単位)プロパティを参照します。要素 3 は と呼ばれることもnLあり、要素 4 は と呼ばれることもありnHます。それらは実際には両方とも幅を参照しており、nLはです。これは、まだ試していませんが、せいぜい 1111 1111 1111 1111b (2 進数)、つまり 65535d (10 進数) の画像を持つことができることを意味します。nL または nH が適切な値に設定されていない場合、画像とともにゴミ文字が印刷されます。Low BytenHHigh Byte

どういうわけか、Android のドキュメントによると、バイト配列内のバイトの値の制限は -128 と +127 で、255 を入力しようとすると、Eclipse から Byte にキャストするように求められました。

とにかく、nL と nW に戻ると、あなたの場合、幅 576 の画像があり、576 をバイナリに変換すると、次のような 2 バイトが得られます。

0000 0010 0100 0000

この場合、下位バイトは で0100 0000あり、上位バイトは0000 0010です。それを 10 進数に戻すと、 と が得られnL = 64ますnH = 2

私の場合、幅 330px の画像を印刷し、330 をバイナリに変換して次のようにしました。

0000 0001 0100 1010

この場合、下位バイトは0100 1010で、上位バイトは0000 0001です。10 進数に変換すると、 と が得られnL = 74ますnH = 1

詳細については、次のドキュメント/チュートリアルを参照してください。

スター アジア モバイル プリンターのドキュメント

ECS-POS プログラミング ガイド - 非常に広範囲

別のドキュメント

上記のコードの拡張バージョンと詳細な説明

上記コードの説明

これらが役立つことを願っています。

于 2013-07-22T08:41:37.557 に答える
10

EDIT:あなたの質問を読んで更新:https://stackoverflow.com/questions/16597789/print-bitmap-on-esc-pos-printer-java

印刷先のプリンターは上記と同じ、つまり Rego Thermal Printer であると仮定します。お気づきのように、これはESC/POS Page Description Languageをサポートしています。


プリンターは、ストリーミングされたデータをマークアップされたドキュメントとして解釈します (ブラウザーが HTML を解釈するのと同様の方法で)。場合によっては、プリンタが文字どおりドキュメントをプログラム (PostScript など) として実行します。リンク:ページ記述言語.

一般的な言語は次のとおりです。

使用する言語を決定するには、プリンターの仕様を読む必要があります。プリンターをサポートする必要がある場合は、非常に大きな仕事が待っています :(

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 

パラメータの定義:

  • 母:
    • 0,48: 通常モード (1:1 スケール)
    • 1,49: 倍幅
    • 2,50: ダブルハイト
    • 3,51: 倍幅 + 倍高
  • xL, xH は、ビットイメージの横方向の (xL + xH × 256) バイトを指定します。
  • yL, yH は、ビットイメージの縦方向 (yL + yH × 256) ドットを指定します。
  • [d]k は、ビット イメージ データ (ラスター形式) を指定します。
  • kはビットイメージデータの数を示します。k は説明パラメーターです。したがって、送信する必要はありません。

ノート:

  • データ [d]k が 1 の場合、1 に印刷され、0 に印刷されないビットを指定します。
  • ラスタービットイメージが印刷領域の 1 行を超える場合、余分なデータは印刷されません。
  • このコマンドは、ESC 2 または ESC 3 の設定に関係なく、ビットイメージの印刷に必要な量の紙送りを実行します。
  • ビットイメージを印刷した後、このコマンドは印刷位置を行の先頭に設定し、バッファをクリアします。
  • このコマンドを実行すると、データが同期して送信され、印刷されます。したがって、他の印刷コマンドは必要ありません。

より広範な説明がいくつかあります。


残念ながら、Android にはプリンター API がありません。これについて強く感じる場合は、次の問題に従ってください。

于 2013-05-23T06:55:55.303 に答える
3

私は ESC/POS を初めて使用し、苦労しています。いくつかの便利な機能があると思われるこのページに出くわしました: http://code.taobao.org/p/printer/src/trunk/prtest/src/com/enjar/plugins/PrintTools_58mm.java 中国語ですが、通う価値があるかもしれません。誰かがそれを理解するなら、私も悟りを得たいです...

于 2013-11-14T11:53:33.230 に答える
2

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)
于 2013-05-26T19:53:57.883 に答える