DantSu / ESCPOS-ThermalPrinter-Android

Useful library to help Android developpers to print with (Bluetooth, TCP, USB) ESC/POS thermal printer.
MIT License
1.18k stars 359 forks source link

Size of the image #70

Closed asaadbaw closed 3 years ago

asaadbaw commented 3 years ago

Hello

Is there any way to make the image large? I have base64 image that I convert to bitmap and then pass it to bitmapToHexadecimalString.

Ex. image

20201021_165012

DantSu commented 3 years ago

You have to generate a bitmap in the good dpi and size. Assume you have a printer with a definition of 201 dpi and printing width of 70mm, you have to generate a picture of : 201 * 7 / 2.54 = 554 px width.

asaadbaw commented 3 years ago

I am still facing the same issue. can you share a sample code for generating that picture passing base64 string?

MustafaAlsihati commented 3 years ago

We managed to get the image print at full width, but i think there is a height restriction, we want to print the image at its full height.

here is the code we did:

String receipt = "...base64 image";

byte[] decodedString = Base64.decode(receipt, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

Bitmap resizedBitmap = Bitmap.createScaledBitmap(decodedByte, (int) (201 * 77 / 2.54), (int) ((201 * 77 / 2.54) * 2.5), false);
decodedByte.recycle();

printer.printFormattedTextAndCut( "[C]<img>" + PrinterTextParserImg.bitmapToHexadecimalString(printer, resizedBitmap) + "</img>\n");

IMG_20201022_104940__01.jpg

As you can see in the picture, in the left i made the height of the bitmap larger the the width, but the right side one i made the height less than width, which made it have the full width of the paper.

DantSu commented 3 years ago

Yes, you have to split every 256px.

MustafaAlsihati commented 3 years ago

Thanks, i managed to do it with the following code:

        new Thread(new Runnable() {
            public void run() {
                try {
                    byte[] decodedString = Base64.decode(receipt, Base64.DEFAULT);
                    List<Bitmap> segments = new ArrayList<Bitmap>();
                    Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

                    int width = decodedByte.getWidth();
                    int height = decodedByte.getHeight();

                    for(int y = 0; y < height; y += 256) {
                        y = y >= height? height : y;
                        int limit = y + 256 >= height? height - y : 256;
                        Bitmap bitmap = Bitmap.createBitmap(decodedByte, 0, y, width, limit);
                        segments.add(bitmap);
                    }

                    TcpConnection tcpConnection = new TcpConnection(ipAddress.getText().toString(), Integer.parseInt(portAddress.getText().toString()));
                    EscPosPrinter printer = new EscPosPrinter(tcpConnection, 201, 77f, 1);

                    for (Bitmap segment : segments) {
                        printer.printFormattedText("[C]<img>" + PrinterTextParserImg.bitmapToHexadecimalString(printer, segment) + "</img>", 0);
                    }

                    printer.printFormattedTextAndCut("[C]Printed!!!\n");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

The only problem is that each split have a space after, it seems that the img tag is causing this, any solution?

IMG_20201022_123311__01.jpg

MustafaAlsihati commented 3 years ago

Tried it, still the same problem

DantSu commented 3 years ago

Great but you do it wrong.

        new Thread(new Runnable() {
            public void run() {
                try {
                    byte[] decodedString = Base64.decode(receipt, Base64.DEFAULT);
                    List<Bitmap> segments = new ArrayList<Bitmap>();
                    Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

                    int width = decodedByte.getWidth();
                    int height = decodedByte.getHeight();

                    for(int y = 0; y < height; y += 256) {
                        y = y >= height? height : y;
                        int limit = y + 256 >= height? height - y : 256;
                        Bitmap bitmap = Bitmap.createBitmap(decodedByte, 0, y, width, limit);
                        segments.add(bitmap);
                    }

                    TcpConnection tcpConnection = new TcpConnection(ipAddress.getText().toString(), Integer.parseInt(portAddress.getText().toString()));
                    EscPosPrinter printer = new EscPosPrinter(tcpConnection, 201, 77f, 1);
                    StringBuilder printText = new StringBuilder();
                    for (Bitmap segment : segments) {
                        printText.append("[C]<img>" + PrinterTextParserImg.bitmapToHexadecimalString(printer, segment) + "</img>\n");
                    }
                    printText.append("[C]Printed!!!\n");
                    printer.printFormattedTextAndCut(printText.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
MustafaAlsihati commented 3 years ago

Great but you do it wrong.

        new Thread(new Runnable() {
            public void run() {
                try {
                    byte[] decodedString = Base64.decode(receipt, Base64.DEFAULT);
                    List<Bitmap> segments = new ArrayList<Bitmap>();
                    Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

                    int width = decodedByte.getWidth();
                    int height = decodedByte.getHeight();

                    for(int y = 0; y < height; y += 256) {
                        y = y >= height? height : y;
                        int limit = y + 256 >= height? height - y : 256;
                        Bitmap bitmap = Bitmap.createBitmap(decodedByte, 0, y, width, limit);
                        segments.add(bitmap);
                    }

                    TcpConnection tcpConnection = new TcpConnection(ipAddress.getText().toString(), Integer.parseInt(portAddress.getText().toString()));
                    EscPosPrinter printer = new EscPosPrinter(tcpConnection, 201, 77f, 1);
                    StringBuilder printText = new StringBuilder();
                    for (Bitmap segment : segments) {
                        printText.append("[C]<img>" + PrinterTextParserImg.bitmapToHexadecimalString(printer, segment) + "</img>\n");
                    }
                    printText.append("[C]Printed!!!\n");
                    printer.printFormattedTextAndCut(printText.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

Tried this solution, still the same problem unfortunately.

DantSu commented 3 years ago

Very weird, this should works. :/

Try this :

        new Thread(new Runnable() {
            public void run() {
                try {
                    TcpConnection tcpConnection = new TcpConnection(ipAddress.getText().toString(), Integer.parseInt(portAddress.getText().toString()));
                    EscPosPrinter printer = new EscPosPrinter(tcpConnection, 203, 70f, 48);

                    byte[] decodedString = Base64.decode(receipt, Base64.DEFAULT);
                    Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

                    int width = decodedByte.getWidth(), height = decodedByte.getHeight();

                    StringBuilder textToPrint = new StringBuilder();
                    for(int y = 0; y < height; y += 256) {
                        Bitmap bitmap = Bitmap.createBitmap(decodedByte, 0, y, width, (y + 256 >= height) ? height - y : 256);
                        textToPrint.append("[C]<img>" + PrinterTextParserImg.bitmapToHexadecimalString(printer, bitmap) + "</img>\n");
                    }

                    textToPrint.append("[C]Printed!!!\n");
                    printer.printFormattedTextAndCut(textToPrint.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
DantSu commented 3 years ago

Do you find the solution ?

MustafaAlsihati commented 3 years ago

Do you find the solution ?

Sorry for not replying earlier i was off on the weekend. Unfortunately it did not solve the issue, it managed to reduce the empty space size but it still visible.

image

DantSu commented 3 years ago

I don't understand where does this spaces come from.

MustafaAlsihati commented 3 years ago

I think it's something related to the '\n' making margin between each img tag, not sure though. I tried many solutions but no luck so far

DantSu commented 3 years ago

\n is just use for spliting line. There are not printed.

nhuttrung commented 3 years ago

I got the same problem. The issue is on the file https://github.com/DantSu/ESCPOS-ThermalPrinter-Android/blob/master/escposprinter/src/main/java/com/dantsu/escposprinter/EscPosPrinterSize.java

It scales the image to maxHeight of 255.

DantSu commented 3 years ago

yes i know and is not an issue.

romaia commented 3 years ago

Same problem for me here.

One thing I noticed is that if i split every 256px (or 128 and probably true for other powers of 2) I get a much bigger space than if i split every 255px (or 127).

I could also guess that the printer is adding the extra space after each image, but printing images using some other applications from the play store work fine, and I also guess that they also have to handle this max height of 256 pixels - but I could be totally wrong here.

AlexandreLumertz commented 3 years ago

The problem is here: http://prntscr.com/vdcdqd

this.printer.newLine(); If printing images only, ignore this command.

Add params newLine.

DantSu commented 3 years ago

Instead of your extra param newLine, try this ;)

        for (PrinterTextParserLine line : linesParsed) {
            PrinterTextParserColumn[] columns = line.getColumns();

            IPrinterTextParserElement lastElement = null;
            for (PrinterTextParserColumn column : columns) {
                IPrinterTextParserElement[] elements = column.getElements();
                for (IPrinterTextParserElement element : elements) {
                    element.print(this.printer);
                    lastElement = element;
                }
            }

            if(!(lastElement instanceof PrinterTextParserImg) && !(lastElement instanceof PrinterTextParserBarcode)) {
                this.printer.newLine();
            }
        }
DantSu commented 3 years ago

say me if it works, I will publish a new release !

Elblassy commented 3 years ago

@DantSu Do you solve the problem ?

Elblassy commented 3 years ago

@DantSu this solution work for me , you can update library with this solution

DantSu commented 3 years ago

Ok thx i will publish a new release.

DantSu commented 3 years ago

Ok v2.0.7 is out.

romaia commented 3 years ago

I can confirm this release fixed the issue.

DantSu commented 2 years ago

If you only print image and do not use formatted text, you can do that :

The image must have a correct width :

       int targetWidth = 383; // 48mm printing zone with 203dpi => 383px
       Bitmap rescaledBitmap = Bitmap.createScaledBitmap(
           originalBitmap, 
           targetWidth, 
           Math.round(((float) originalBitmap.getHeight()) * ((float) targetWidth) / ((float) originalBitmap.getWidth())), 
           true
       );

       EscPosPrinterCommands printerCommands = new EscPosPrinterCommands(BluetoothPrintersConnections.selectFirstPaired());
        try {
            printerCommands.connect();
            printerCommands.reset();
            printerCommands.printImage(EscPosPrinterCommands.bitmapToBytes(rescaledBitmap));
            printerCommands.feedPaper(50);
            printerCommands.cutPaper();
        } catch (EscPosConnectionException e) {
            e.printStackTrace();
        }
Elblassy commented 2 years ago

this work for width of image but some of height not printed

Elblassy commented 2 years ago

it work fine when increase feed , nice solution thanks

laithbzour commented 2 years ago

@DantSu
still have errorr : Buffer not large enough for pixels

when try print bitmap image

DantSu commented 2 years ago

I think the error message is explicit.... your printer haven't enougth memory for the image you try to print...

laithbzour commented 2 years ago

@DantSu thanks for reply i try split image to chunk but still have same issue

just print image 60*60.

POS device type Aisino A90

DantSu commented 2 years ago

Try to use useEscAsteriskCommand(true)

Method : useEscAsteriskCommand(boolean enable)

Active "ESC *" command for image printing.

laithbzour commented 2 years ago

@DantSu i try this method print Chinese char

this is my code

 int targetWidth = 383; // 48mm printing zone with 203dpi => 383px
                Bitmap rescaledBitmap = Bitmap.createScaledBitmap(
                        bmp,
                        targetWidth,
                        Math.round(((float) bmp.getHeight()) * ((float) targetWidth) / ((float) bmp.getWidth())),
                        true
                );

                EscPosPrinterCommands printerCommands = new EscPosPrinterCommands(MyBluetoothPrintersConnections.selectFirstPairedOne());
                try {
                    printerCommands.connect();
                    printerCommands.useEscAsteriskCommand(true);
                    printerCommands.printImage(EscPosPrinterCommands.bitmapToBytes(rescaledBitmap));
                    printerCommands.feedPaper(50);
                } catch (EscPosConnectionException e) {
                    e.printStackTrace();
                }
laithbzour commented 2 years ago

@DantSu my Thermal Printer specification Paper Width: 58mm Diameter: 40mm Android 7.1 RAM: 1GB

laithbzour commented 2 years ago

PrintImage

DantSu commented 2 years ago

Cant help you more

laithbzour commented 2 years ago

@DantSu thanks i fix isssue

DantSu commented 2 years ago

How ?

laithbzour commented 2 years ago

@DantSu i split Text contain (Arabic & english) word to chunk then convert it to bitmap image then send it to printer and print it

laithbzour commented 2 years ago

7e2326ef-4d85-4e67-8db7-73e231ab2bc7

AshuBhutani commented 1 year ago

Hi my image is accurate. but the quality of the image is too low

i am using this below code new Thread(new Runnable() { public void run() { try { TcpConnection tcpConnection = new TcpConnection(ipAddress.getText().toString(), Integer.parseInt(portAddress.getText().toString())); EscPosPrinter printer = new EscPosPrinter(tcpConnection, 203, 70f, 48);

                byte[] decodedString = Base64.decode(receipt, Base64.DEFAULT);
                Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

                int width = decodedByte.getWidth(), height = decodedByte.getHeight();

                StringBuilder textToPrint = new StringBuilder();
                for(int y = 0; y < height; y += 256) {
                    Bitmap bitmap = Bitmap.createBitmap(decodedByte, 0, y, width, (y + 256 >= height) ? height - y : 256);
                    textToPrint.append("[C]<img>" + PrinterTextParserImg.bitmapToHexadecimalString(printer, bitmap) + "</img>\n");
                }

                textToPrint.append("[C]Printed!!!\n");
                printer.printFormattedTextAndCut(textToPrint.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();
8unique commented 10 months ago

to get full sized bitmap, use this code in EscPosPrinterSize class.

    public byte[] bitmapToBytes(Bitmap bitmap, boolean gradient) {
    boolean isSizeEdit = false;
    int bitmapWidth = bitmap.getWidth(),
            bitmapHeight = bitmap.getHeight(),
            maxWidth = bitmapWidth,  // Increase the maximum width
            maxHeight = bitmapHeight; // Increase the maximum height

    if (bitmapWidth > maxWidth) {
        bitmapHeight = Math.round(((float) bitmapHeight) * ((float) maxWidth) / ((float) bitmapWidth));
        bitmapWidth = maxWidth;
        isSizeEdit = true;
    }
    if (bitmapHeight > maxHeight) {
        bitmapWidth = Math.round(((float) bitmapWidth) * ((float) maxHeight) / ((float) bitmapHeight));
        bitmapHeight = maxHeight;
        isSizeEdit = true;
    }

    if (isSizeEdit) {
        bitmap = Bitmap.createScaledBitmap(bitmap, bitmapWidth, bitmapHeight, true);
    }

    return EscPosPrinterCommands.bitmapToBytes(bitmap, gradient);
}
mlhtnc commented 6 months ago

it work fine when increase feed , nice solution thanks

Inreasing feed did not work for me. Actually it looks like any parameter passed to feedPaper is ignored for the printer i use.