web-dev-qa-db-ja.com

AndroidのBluetoothプリンターで画像を印刷するにはどうすればよいですか?

私はサーマル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ストアからアプリをダウンロードしました) Image that I want to print

これは私が今得ているものです My printing trying

クローザー: A closer part

Closer2: enter image description here

画像の少しの部分が見えるので、私は画像を印刷するのに近いと思います...

私が使用している画像はこれです(576x95):enter image description here

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

Inverted

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

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

しかし、どのように画像の正しい値を計算できますか?、ありがとう

46
Leonardo Sapuy

解決!、間違ったプリンターの初期化を行っていました...正しい方法は:

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

したがって、この方法で画像は完全にきれいに印刷されます

9
Leonardo Sapuy

ビットマップをバイト配列に変換して解決します。画像は白黒フォーマットでなければならないことに注意してください。

完全なソースコードの場合: 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

私もこれを試してみましたが、私は自分の解決策に着手し、どのように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として参照されることがあります。これらは実際には両方とも幅を参照しています。nLLow BytenHHigh 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

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

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

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

別のドキュメント

上記のコードの拡張バージョン、詳細説明付き

上記のコードの説明

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

9
Razgriz

[〜#〜] 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 

パラメータ定義:

  • m:
    • 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はありません。これについて強く感じている場合は、次の問題に従ってください。

8
Andrew Alcock

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

3
just some guy

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)
2
mjosh