Skip to content

Instantly share code, notes, and snippets.

@scruss
Last active June 8, 2024 23:14
Show Gist options
  • Save scruss/36c31a9b653779b2b7d1 to your computer and use it in GitHub Desktop.
Save scruss/36c31a9b653779b2b7d1 to your computer and use it in GitHub Desktop.
print image files to thermal printer ESC-POS on stdout
#!/usr/bin/env python3
# esc-pos-image.py - print image files given as command line arguments
# to simple ESC-POS image on stdout
# scruss - 2014-07-26 - WTFPL (srsly)
# - 2021-01-09 (made python3 compatible - tvm Carko!)
# if you want a proper CUPS driver for a 58mm thermal printer
# that uses this command set, go here:
# https://github.com/klirichek/zj-58
import sys
from PIL import Image
import PIL.ImageOps
import struct
# give usage and exit if no arguments
if (len(sys.argv) == 1):
print('Usage:', sys.argv[0],
'image1 image2 ... [ > printer_device ]')
exit(1)
# print all of the images!
for i in sys.argv[1:]:
im = Image.open(i)
# if image is not 1-bit, convert it
if (im.mode != '1'):
im = im.convert('1')
# if image width is not a multiple of 8 pixels, fix that
if (im.size[0] % 8):
im2 = Image.new('1', (im.size[0] + 8 - im.size[0] % 8,
im.size[1]), 'white')
im2.paste(im, (0, 0))
im = im2
# Invert image, via greyscale for compatibility
# (no, I don't know why I need to do this)
im = PIL.ImageOps.invert(im.convert('L'))
# ... and now convert back to single bit
im = im.convert('1')
# output header (GS v 0 \000), width, height, image data
sys.stdout.buffer.write(b''.join((bytearray(b'\x1d\x76\x30\x00'),
struct.pack('2B', int(im.size[0] / 8) % 256,
int(im.size[0] / (8 * 256))),
struct.pack('2B', im.size[1] % 256,
int(im.size[1] / 256)),
im.tobytes())))
@scruss
Copy link
Author

scruss commented Dec 5, 2020

Very lovely! Worked like nothing has ever have before in bluetooth.

Glad you like it! One day I'll update it to Python 3, but the bytes vs utf8 bit seems like work

@Carko
Copy link

Carko commented Jan 9, 2021

I made some changes to make it work with Pyton 3: https://gist.github.com/Carko/1507260d13eaa3e7cea6cecb713caca0

@scruss
Copy link
Author

scruss commented Jan 10, 2021

Much appreciated, Carko!

@abhigkar
Copy link

It really worked for me. I have used here.
Thanks!!!

@scruss
Copy link
Author

scruss commented Jul 12, 2023

It really worked for me. I have used here. Thanks!!!

That's really neat! I saw those little printers and wondered how well they would work.

@alifeee
Copy link

alifeee commented Jun 7, 2024

this was very helpful for my project with an ESC/POS ZJ-58 thermal printer :)

I had problems with images of specific resolutions (384x288 broke, while 384x289 worked fine) using this script (I think this was the problem, I added a row of pixels to the former image and it worked ok). The image would print once, and then break and print the raw data as ASCII.

So, I started using the https://github.com/python-escpos/python-escpos/ Python library. But thanks for this gist and the blog posts! they got me started really well :)

@scruss
Copy link
Author

scruss commented Jun 8, 2024

I had problems with images of specific resolutions (384x288 broke, while 384x289 worked fine)

Hey, thanks! I'm probably not finishing off the last line properly, so maybe data is getting corrupted. I haven't really done anything with this gist in a long time.

python-escpos didn't used to work for me, so I'm glad to see that it's getting some attention

@alifeee
Copy link

alifeee commented Jun 8, 2024

python-escpos didn't used to work for me, so I'm glad to see that it's getting some attention

it works for me, but maybe a bit too well... and by that I mean running python-escpos takes over control of the USB device and never hands it back (even using close()), so I can't use the simple printf "hi\n\n\n" > /dev/usb/lp0 after using it, and have to restart the printer to do so. Ah well, I guess I will do everything using the python library... >:(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment