2

So I have a project where I send text to an Arduino, which is then printed out as a QR code on a thermal printer that can take a bitmap image with a given width and height.

Is there a way I can "scale up" the "image," making it so one pixel is scaled up to 4 or 8 pixels?

Additionally, would it be possible to add a "quiet zone" of sorts on the left side of the image, as I am not able to offset/justify it to the middle.

QR Code lib: https://github.com/ricmoo/QRCode

Thermal printer lib: https://github.com/adafruit/Adafruit-Thermal-Printer-Library

asked Aug 25, 2019 at 3:52
3
  • Trying to splice in the QRPrint library causes the ESP32 to crash over and over. Commented Aug 25, 2019 at 4:19
  • Which Arduino? Most of them wouldn't have enough RAM for that. Commented Aug 25, 2019 at 8:49
  • @NickGammon I am using an ESP32, which has an Arduino core. :) Commented Aug 25, 2019 at 20:02

1 Answer 1

1

You didn't tell use the size of your QRCode, nor the type of Arduino you are using. So I am just going to guess that your problem is that you may have enough RAM to store the raw QRCode, but not enough to store a scaled bitmap version.

The Adafruit tutorial for their thermal printer library suggests printing bitmaps with the method:

printBitmap(width, height, tablename)

where tablename is an array holding the bitmap data. This will obviously not work if you don't have enough RAM to store the array. Fortunately, there is an overloaded method:

void Adafruit_Thermal::printBitmap(int w, int h, Stream *fromStream)

that allows you to stream the image data instead of preparing it in RAM. You can create a stream that delivers arbitrary data by writing a class that derives from Stream. Here is a tentative, untested implementation, that delivers a scaled-up QRCode one pixel at a time:

// Stream a scaled QRCode one pixel at a time.
class QRCodeStream : public Stream
{
public:
 QRCodeStream(const QRCode &code, uint8_t scale = 1)
 : qrcode(code), scale(scale) {}
 // Output: writing to this stream is a no-op.
 size_t write(uint8_t) {}
 void flush() {}
 // Input delivers the QRCode pixels.
 int available();
 int peek();
 int read();
private:
 QRCode &qrcode;
 uint8_t scale;
 bool done = false;
 uint8_t code_x = 0; // coordinates of the QRCode module
 uint8_t code_y = 0;
 uint8_t pix_x = 0; // pixel coordinates within the module
 uint8_t pix_y = 0;
};
int QRCodeStream::available()
{
 // For simplicity, pretend the bytes come one at a time.
 if (done) return 0;
 else return 1;
}
int QRCodeStream::peek()
{
 if (done) return -1;
 if (qrcode_getModule(&qrcode, code_x, code_y)) {
 return 0; // black
 } else {
 return 255; // white
 }
}
int QRCodeStream::read()
{
 if (done) return -1;
 int data = peek();
 // Move to the next pixel.
 if (++pix_x >= scale) {
 pix_x = 0;
 if (++code_x >= qrcode.size) {
 code_x = 0;
 if (++pix_y >= scale) {
 pix_y = 0;
 if (++code_y >= qrcode.size) {
 done = true;
 }
 }
 }
 }
 return data;
}

This would be used as

printer.printBitmap(width, height, QRCodeStream(qrcode, scale));

Note that QRCodeStream delivers the image data as 8-bit gray scale, where each pixel is returned as one byte, either 0 (for black) or 255 (for white). This is likely not the format expected by the thermal printer library, which seems to expect 1-bit black and white data, with 8 pixels packed in each byte. You will have to adapt the code for the right format, which will likely be tedious, but not overly complex. I leave that "as an exercise to the reader".

answered Aug 25, 2019 at 12:33
4
  • Apologies. I am using an ESP32, and the Arduino IDE reports a Max Mem of 327680 bytes. And I am aiming for a Version 3 QR Code at minimum :) Commented Aug 25, 2019 at 20:04
  • And here is the results of scales 1-3: i.imgur.com/7gBl0c1.jpg - Not sure if it's due to the format of the code itself, or something else... Commented Aug 25, 2019 at 20:23
  • @TonySesek: Looks like it's working, but every pixel gets converted to a line of 8 pixels because of the 1-bit vs. 8-bits format difference. Commented Aug 25, 2019 at 21:12
  • Ohh, my brain skipped over the important part of your postscript, my bad. Alright, that shouldn't be too bad. Maybe I can make another stream to take the stream, haha. Commented Aug 25, 2019 at 21:52

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.