Dùng ESC/POS Printing Command để in hình ảnh bằng máy in nhiệt

Việc là mình sử dụng POS command để gửi lệnh cho máy in. In chữ thì hoàn toàn bình thường. Tuy nhiên mình có gửi lệnh in hình máy không in hình mà in ra 1 loạt các ký tự. Đây là đoạn code mình làm để in

QByteArray printData = "\x12\x2A";
printData.append(image.width() );
printData.append(image.height() );
char bitIndex = 0;
char recordByte = 0x00;
// Convert the image to 32-bit format to handle transparency
QImage tempImage = image.convertToFormat(QImage::Format_ARGB32);
// Create a new image with 1-bit per pixel (monochrome)
QImage bitonalImage(tempImage.size(), QImage::Format_Mono);
bitonalImage.fill(Qt::white); // Set the background to white
// Iterate through each pixel in the image
for (int y = 0; y < tempImage.height(); ++y) {
    for (int x = 0; x < tempImage.width(); ++x) {
        // Get the color of the current pixel
        QRgb color = tempImage.pixel(x, y);
        // Calculate the intensity (brightness) of the pixel
        int intensity = qGray(color);
        if(intensity > 128){
            recordByte = recordByte | ( 0x01 << bitIndex);
            printf("*");
        }else{
            printf(" ");
        }
        bitIndex ++;
        if(bitIndex > 7){
            printData.append(recordByte);
            bitIndex = 0 ;
            recordByte = 0x00;
        }
    }
    printf("\n");
}
mRs232_printer->sendData(printData.data(),printData.size());

Kết quả trên terninal với 1 bức hình 120 * 120 :


Máy in :

Bạn mong muốn sẽ in được cái gì lên giấy?
Hình ảnh gồm các ký tự "*" và " " giống như trên màn hình terminal? Nếu đúng vậy thì trong code của bạn, chỗ nào sẽ in ký tự "*" ra máy in vậy?

À mình muốn in hình con mèo đó lên giấy á. dấu * và ’ ’ là mình log ra để minh họa thôi .

mRs232_printer->sendData(printData.data(),printData.size());

Mình gửi số byte này qua thiết bị thông qua đường Uart nối với máy

Hình như đã có câu trả lời trên SO của bạn, \x12\x1b.

1 Like

in cái printData kia ra coi có đúng w h ko, thử in hình đen thui 32x32 là 4x32 = 128 kí tự hay printData có 132 phần tử, in hết giá trị của 20 bytes này ra coi có đúng ko (decimal): 18 42 32 32 255 255 255 … 255

mà sao trong hình nó để d1 tới dn là sao, vậy n phải là 32/8 = 4 à??

https://github.com/adafruit/Adafruit-Thermal-Printer-Library/blob/54786351af1d84580c4ae555d439756679b0dc44/Adafruit_Thermal.cpp#L500 edit dòng 500 nó lấy (w+7)/8 thật, nghĩa là hình 32x32 thì 4 kí tự đầu tiên phải là (dec) 18 42 32 4. Mà code người ta còn in theo chunk 256 byte 1 lần gì nữa :crazy_face: thử in 1 hình sao cho cái mảng printData < 256 bytes xem. Nếu size > 255 thì cắt làm k hình mà in :crazy_face: Max size cái hình là 384 pixel wide hay n <= 48, cho n=120 thì nó in bậy in bạ, chắc vậy :thinking:

3 Likes

Thanks bác, để mình thử

In hết giá trị của 20 bytes này ra coi có đúng ko (decimal): 18 42 32 32 255 255 255 … 255

Nó hông thèm in luôn xD.

T cũng có tham khảo cái link Git, chỉnh lại rồi chạy thử thì nó toàn ra 1 mớ dấu (((
Hàm tui dùng
Nó gửi 64 byte : 0x12 0x2A 0x14 0x03 0xFF … 0xFF

void PrintImageState::PrintTest(BillMachine * ) {
    int w = 20;
    int h = 20;
    int maxChunkHeight = 255;
    int rowBytes, rowBytesClipped, rowStart, chunkHeight, chunkHeightLimit, x, y,
    i;

    rowBytes = (w + 7) / 8; // Round up to next byte boundary
    rowBytesClipped = (rowBytes >= 48) ? 48 : rowBytes; // 384 pixels max width

    chunkHeightLimit = 256 / rowBytesClipped;
    if (chunkHeightLimit > maxChunkHeight)
        chunkHeightLimit = maxChunkHeight;
    else if (chunkHeightLimit < 1)
        chunkHeightLimit = 1;
    QByteArray printData = "\x12\x2A";

    for (i = rowStart = 0; rowStart < h; rowStart += chunkHeightLimit) {
         chunkHeight = h - rowStart;
        if (chunkHeight > chunkHeightLimit)
            chunkHeight = chunkHeightLimit;

        printData.append(chunkHeight);
        printData.append(rowBytesClipped);

        for (y = 0; y < chunkHeight; y++) {
            for (x = 0; x < rowBytesClipped; x++, i++) {
                printData.append(0xFF);
            }
            i += rowBytes - rowBytesClipped;
        }
    }
    mRs232_printer -> sendData(printData.data(), printData.size());
}

đừng xài cái code git của nó, nó đòi w phải chia hết cho 8 mà. Cái article bitmap printing của Adafruit ở đây: https://learn.adafruit.com/mini-thermal-receipt-printer/bitmap-printing

1 mớ dấu ((( là máy in nhiệt in ra hay là in ra ký tự trên màn hình :crazy_face: send đúng 0x12 0x2A 20 3 và 60 kí tự mà nó vẫn in ra ( chứ ko phải bitmap thì toy bó tay rồi :V :V

edit ko phải :V

2 Likes

thử send DC2 T hay là \x12\x54 cho nó in test page thử, chắc có bitmap image ở trỏng :V

hasyimibhar/escpos-printer: C library for operating thermal printers by sending ESC/POS commands (github.com)

Mình in ra được rồi. Mình dựa vào thư viện của project này làm theo xD

2 Likes

vậy sai ở chỗ nào chỉ ra để người khác biết cách chữa nữa chứ :hocho:

3 Likes

Cũng hông biết nữa ông, tại t đập đi xây lại luôn, với đổi sang dùng lệnh in khác ( 0x1D 0x76) nên chịu. Cũng có thể là do máy in mình đang dùng hiện tại.

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?