Search code examples
imagekotlinprintingthermal-printer

how to print image to thermal printer in kotlin


i already able to print text using kotlin to thermal printer, but im still dont know how to print image to thermal printer in kotlin. please give me sample printing image to thermal printer in kotlin.i already search for the topics, but it written in java, i doesnt know java very much thanks for the help

private fun p1() {
    val namaToko = "Rose Medical"
    val alamatToko = "Pramuka raya no.1 Jakarta Timur"
    val telp = "021-85901642"
    val enter = "\n"
    val strip = "-"
    val rp ="Rp."
    val ex = " X "
    val textTotal = "Total Rp:"
    val ppnTv = "PPN :Rp."
    val chargeTv ="Charge :Rp."
    val totalTv = "Total Belanja :Rp."

    val scope = CoroutineScope(Dispatchers.IO)

    scope.launch {
        // chunks1
        try{
            writeWithFormat(namaToko.toByteArray(),Formatter().get(),Formatter.centerAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
            writeWithFormat(alamatToko.toByteArray(),Formatter().get(),Formatter.centerAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
            writeWithFormat(telp.toByteArray(),Formatter().get(),Formatter.centerAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
        }catch (e: Exception) {
            Log.e("PrintActivity", "Exe ", e)
        }
        // chunks2
        for(pointer in salesBody.indices){
            try {
                val merk = salesBody[pointer].merk
                writeWithFormat(merk!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
                writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign())
                val barang = salesBody[pointer].namaBrg
                writeWithFormat(barang!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
                writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
                val varian = salesBody[pointer].varian
                writeWithFormat(varian!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
                writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
                writeWithFormat(rp.toByteArray(),Formatter().get(),Formatter.leftAlign())
                val harga = ValidNumber().deciformat(salesBody[pointer].hargaJual.toString())
                writeWithFormat(harga.toByteArray(),Formatter().get(),Formatter.leftAlign())
                writeWithFormat(ex.toByteArray(),Formatter().get(),Formatter.leftAlign())
                val jumlah = ValidNumber().deciformat(salesBody[pointer].qty.toString())
                writeWithFormat(jumlah.toByteArray(),Formatter().get(),Formatter.leftAlign())
                val  satuan = salesBody[pointer].unit
                writeWithFormat(satuan!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
                writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
                writeWithFormat(textTotal.toByteArray(),Formatter().get(),Formatter.rightAlign())
                val total = ValidNumber().deciformat(salesBody[pointer].total.toString())
                writeWithFormat(total.toByteArray(),Formatter().get(),Formatter.leftAlign())
                writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())


            }catch (e: Exception) {
                Log.e("PrintActivity", "Exe ", e)
            }
        }
        // chunks3
        try{
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
            val tanggal = salesHeader[0].tanggal
            writeWithFormat(tanggal!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
            writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign())
            val jam = salesHeader[0].jam
            writeWithFormat(jam!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
            writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign())
            val idTag= salesHeader[0].idTag
            writeWithFormat(idTag!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
            val payment= salesHeader[0].payment
            writeWithFormat(payment!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())

            writeWithFormat(ppnTv.toByteArray(),Formatter().get(),Formatter.rightAlign())
            val ppnValue = ValidNumber().deciformat(salesHeader[0].ppn.toString())
            writeWithFormat(ppnValue.toByteArray(),Formatter().get(),Formatter.rightAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())

            writeWithFormat(chargeTv.toByteArray(),Formatter().get(),Formatter.rightAlign())
            val chargeValue = ValidNumber().deciformat(salesHeader[0].charge.toString())
            writeWithFormat(chargeValue.toByteArray(),Formatter().get(),Formatter.rightAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())

            writeWithFormat(totalTv.toByteArray(),Formatter().get(),Formatter.rightAlign())
            var totalValue = ValidNumber().deciformat(salesHeader[0].allTotal.toString())
            writeWithFormat(totalValue.toByteArray(),Formatter().get(),Formatter.rightAlign())

            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
            writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())


        }catch (e: Exception) {
            Log.e("PrintActivity", "Exe ", e)
        }


    }
}
//print code
class Formatter {
    /** The format that is being build on  */
    private val mFormat: ByteArray

    init {
        // Default:
        mFormat = byteArrayOf(27, 33, 0)
    }

    /**
     * Method to get the Build result
     *
     * @return the format
     */
    fun get(): ByteArray {
        return mFormat
    }

    fun bold(): Formatter {
        // Apply bold:
        mFormat[2] = (0x8 or mFormat[2].toInt()).toByte()
        return this
    }

    fun small(): Formatter {
        mFormat[2] = (0x1 or mFormat[2].toInt()).toByte()
        return this
    }

    fun height(): Formatter {
        mFormat[2] = (0x10 or mFormat[2].toInt()).toByte()
        return this
    }

    fun width(): Formatter {
        mFormat[2] = (0x20 or mFormat[2].toInt()).toByte()
        return this
    }

    fun underlined(): Formatter {
        mFormat[2] = (0x80 or mFormat[2].toInt()).toByte()
        return this
    }

    companion object {
        fun rightAlign(): ByteArray {
            return byteArrayOf(0x1B, 'a'.code.toByte(), 0x02)
        }

        fun leftAlign(): ByteArray {
            return byteArrayOf(0x1B, 'a'.code.toByte(), 0x00)
        }

        fun centerAlign(): ByteArray {
            return byteArrayOf(0x1B, 'a'.code.toByte(), 0x01)
        }
    }
}//last
fun writeWithFormat(buffer: ByteArray, pFormat: ByteArray?, pAlignment: ByteArray?): Boolean {
    val mmOutStream: OutputStream = mBluetoothSocket.outputStream
    return try {
        // Notify printer it should be printed with given alignment:
        mmOutStream.write(pAlignment)
        // Notify printer it should be printed in the given format:
        mmOutStream.write(pFormat)
        // Write the actual data:
        mmOutStream.write(buffer, 0, buffer.size)

        // Share the sent message back to the UI Activity
        //App.getInstance().getHandler().obtainMessage(MESSAGE_WRITE, buffer.size, -1, buffer).sendToTarget()
        true
    } catch (e: IOException) {
        Log.e(TAG, "Exception during write", e)
        false
    }
}
//print code close

Solution

  • Using Thermal Printer repo references, I managed to print image to Bluetooth thermal printer. Make sure to use a proper black and white image to print.

    Here is the piece of code I used to make a java class --BitmapHelper.java.

    public class BitmapHelper {
    
    private static String[] binaryArray = { "0000", "0001", "0010", "0011",
            "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011",
            "1100", "1101", "1110", "1111" };
    
    public static byte[] decodeBitmap(Bitmap bmp){
        //Bitmap bmp = Bitmap.createScaledBitmap(bitmap, 50, 50, false);
        int maxWidth = 350;
    
        int bmpWidth = bmp.getWidth();
        int bmpHeight = bmp.getHeight();
    
        if(bmpWidth > maxWidth){
            float aspectRatio = bmp.getWidth() /
                    (float) bmp.getHeight();
            bmpWidth = maxWidth;
            bmpHeight = Math.round(bmpWidth / aspectRatio);
            bmp = Bitmap.createScaledBitmap(bmp, bmpWidth, bmpHeight, false);
        }
    
        List<String> list = new ArrayList<>(); //binaryString list
        StringBuffer sb;
    
        int zeroCount = bmpWidth % 8;
    
        StringBuilder zeroStr = new StringBuilder();
        if (zeroCount > 0) {
            for (int i = 0; i < (8 - zeroCount); i++) {
                zeroStr.append("0");
            }
        }
    
        for (int i = 0; i < bmpHeight; i++) {
            sb = new StringBuffer();
            for (int j = 0; j < bmpWidth; j++) {
                int color = bmp.getPixel(j, i);
    
                int r = (color >> 16) & 0xff;
                int g = (color >> 8) & 0xff;
                int b = color & 0xff;
    
                // if color close to white,bit='0', else bit='1'
                if (r > 160 && g > 160 && b > 160)
                    sb.append("0");
                else
                    sb.append("1");
            }
            if (zeroCount > 0) {
                sb.append(zeroStr);
            }
            list.add(sb.toString());
        }
    
        List<String> bmpHexList = binaryListToHexStringList(list);
        String commandHexString = "1D763000";
        String widthHexString = Integer
                .toHexString(bmpWidth % 8 == 0 ? bmpWidth / 8
                        : (bmpWidth / 8 + 1));
        if (widthHexString.length() > 2) {
            Log.e("decodeBitmap error", " width is too large");
            return null;
        } else if (widthHexString.length() == 1) {
            widthHexString = "0" + widthHexString;
        }
        widthHexString = widthHexString + "00";
    
        String heightHexString = Integer.toHexString(bmpHeight);
        if (heightHexString.length() > 2) {
            Log.e("decodeBitmap error", " height is too large");
            return null;
        } else if (heightHexString.length() == 1) {
            heightHexString = "0" + heightHexString;
        }
        heightHexString = heightHexString + "00";
    
        List<String> commandList = new ArrayList<>();
        commandList.add(commandHexString+widthHexString+heightHexString);
        commandList.addAll(bmpHexList);
    
        return hexList2Byte(commandList);
    }
    
    private static List<String> binaryListToHexStringList(List<String> list) {
        List<String> hexList = new ArrayList<String>();
        for (String binaryStr : list) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < binaryStr.length(); i += 8) {
                String str = binaryStr.substring(i, i + 8);
    
                String hexString = myBinaryStrToHexString(str);
                sb.append(hexString);
            }
            hexList.add(sb.toString());
        }
        return hexList;
    }
    
    private static String myBinaryStrToHexString(String binaryStr) {
        StringBuilder hex = new StringBuilder();
        String f4 = binaryStr.substring(0, 4);
        String b4 = binaryStr.substring(4, 8);
        String hexStr = "0123456789ABCDEF";
        for (int i = 0; i < binaryArray.length; i++) {
            if (f4.equals(binaryArray[i]))
                hex.append(hexStr.substring(i, i + 1));
        }
        for (int i = 0; i < binaryArray.length; i++) {
            if (b4.equals(binaryArray[i]))
                hex.append(hexStr.substring(i, i + 1));
        }
    
        return hex.toString();
    }
    
    private static byte[] hexList2Byte(List<String> list) {
        List<byte[]> commandList = new ArrayList<byte[]>();
        for (String hexStr : list) {
            commandList.add(hexStringToBytes(hexStr));
        }
        return sysCopy(commandList);
    }
    
    private static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }
    
    private static byte[] sysCopy(List<byte[]> srcArrays) {
        int len = 0;
        for (byte[] srcArray : srcArrays) {
            len += srcArray.length;
        }
        byte[] destArray = new byte[len];
        int destLen = 0;
        for (byte[] srcArray : srcArrays) {
            System.arraycopy(srcArray, 0, destArray, destLen, srcArray.length);
            destLen += srcArray.length;
        }
        return destArray;
    }
    
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }
    

    }

    Then I use it in the print activity:

    private fun p2(){
        val convertBmp : Bitmap
            convertBmp = BitmapFactory.decodeResource(getResources(),com.example.ronibluetooth.R.drawable.poly)
        val decodeBmp = BitmapHelper.decodeBitmap(convertBmp)       
        val scope = CoroutineScope(Dispatchers.IO)
        scope.launch {
            try {
                    val os =mBluetoothSocket.outputStream
    
                        os.write(decodeBmp,0,decodeBmp.size)
                         }
                catch (e: Exception) {
                    Log.e("PrintActivity", "Exe ", e)
                }
        }
    }
    

    image to print

    result print