diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05ea79d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.py[cod] +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c912612 --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +ESCPOS +====== + +Python library to manipulate ESC/POS Printers. + +1. Dependencies +------------------------------------------------------------------ + +In order to start getting access to your printer, you must ensure +you have previously installed the following python modules: + + * pyusb (python-usb) + * PIL (Python Image Library) + +2. Description +------------------------------------------------------------------ + +Python ESC/POS is a library which lets the user have access to all +those printers handled by ESC/POS commands, as defined by Epson, +from a Python application. + +The standard usage is send raw text to the printer, but in also +helps the user to enhance the experience with those printers by +facilitating the bar code printing in many different standards, +as well as manipulating images so they can be printed as brand +logo or any other usage images migh have. + +Text can be aligned/justified and fonts can be changed by size, +type and weight. + +Also, this module handles some hardware functionalities like, cut +paper, carrier return, printer reset and others concerned to the +carriage alignment. + +3. Define your printer +------------------------------------------------------------------ + +Before start create your Python ESC/POS printer instance, you must +see at your system for the printer parameters. This is done with +the 'lsusb' command. + +First run the command to look for the "Vendor ID" and "Product ID", +then write down the values, these values are displayed just before +the name of the device with the following format: + + xxxx:xxxx + +Example: + Bus 002 Device 001: ID 1a2b:1a2b Device name + +Write down the the values in question, then issue the following +command so you can get the "Interface" number and "End Point" + + lsusb -vvv -d xxxx:xxxx | grep iInterface + lsusb -vvv -d xxxx:xxxx | grep bEndpointAddress | grep OUT + +The first command will yields the "Interface" number that must +be handy to have and the second yields the "Output Endpoint" +address. + +By default the "Interface" number is "0" and the "Output Endpoint" +address is "0x82", if you have other values then you can define +with your instance. + +4. Define your instance +------------------------------------------------------------------ + +The following example shows how to initialize the Epson TM-TI88IV +*** NOTE: Always finish the sequence with Epson.cut() otherwise + you will endup with weird chars being printed. + + from escpos import * + + """ Seiko Epson Corp. Receipt Printer M129 Definitions (EPSON TM-T88IV) """ + Epson = escpos.Escpos(0x04b8,0x0202,0) + Epson.text("Hello World") + Epson.image("logo.gif") + Epson.fullimage("a.really.large.image.png") + Epson.barcode + Epson.barcode('1324354657687','EAN13',64,2,'','') + Epson.cut() + +5. Links +------------------------------------------------------------------ + +Please visit project homepage at: +http://repo.bashlinux.com/projects/escpos.html + +Manuel F Martinez + diff --git a/escpos/escpos.py b/escpos/escpos.py index 91d71fc..85be2e3 100644 --- a/escpos/escpos.py +++ b/escpos/escpos.py @@ -9,6 +9,8 @@ import Image import qrcode import time +import os +import operator from constants import * from exceptions import * @@ -51,8 +53,44 @@ class Escpos: buffer = "" cont = 0 + def fullimage(self, img, max_height=860, width=512, histeq=True): + """ Resizes and prints an arbitrarily sized image """ + if isinstance(img, Image.Image): + im = img.convert("RGB") + else: + im = Image.open(img).convert("RGB") - def _convert_image(self, im): + if histeq: + # Histogram equaliztion + h = im.histogram() + lut = [] + for b in range(0, len(h), 256): + # step size + step = reduce(operator.add, h[b:b+256]) / 255 + # create equalization lookup table + n = 0 + for i in range(256): + lut.append(n / step) + n = n + h[i+b] + im = im.point(lut) + + ratio = float(width) / im.size[0] + newheight = int(ratio * im.size[1]) + + # Resize the image + im = im.resize((width, newheight), Image.ANTIALIAS) + if im.size[1] > max_height: + im = im.crop((0, 0, im.size[0], max_height)) + + # Divide into bands + bandsize = 255 + current = 0 + while current < im.size[1]: + self.image(im.crop((0, current, width, min(im.size[1], current + bandsize)))) + current += bandsize + + + def image(self, img): """ Parse image and prepare it to a printable format """ pixels = [] pix_line = "" @@ -61,9 +99,13 @@ class Escpos: switch = 0 img_size = [ 0, 0 ] + if isinstance(img, Image.Image): + im = img.convert("RGB") + else: + im = Image.open(img).convert("RGB") if im.size[0] > 512: - print ("WARNING: Image is wider than 512 and could be truncated at print time ") + print "WARNING: Image is wider than 512 and could be truncated at print time " if im.size[1] > 255: raise ImageSizeError() @@ -99,15 +141,6 @@ class Escpos: self._print_image(pix_line, img_size) - - def image(self,path_img): - """ Open image file """ - im_open = Image.open(path_img) - im = im_open.convert("RGB") - # Convert the RGB image in printable image - self._convert_image(im) - - def qr(self,text): """ Print QR Code for the provided string """ qr_code = qrcode.QRCode(version=4, box_size=4, border=1) @@ -118,7 +151,6 @@ class Escpos: # Convert the RGB image in printable image self._convert_image(im) - def barcode(self, code, bc, width, height, pos, font): """ Print Barcode """ # Align Bar Code() @@ -226,7 +258,6 @@ class Escpos: elif align.upper() == "LEFT": self._raw(TXT_ALIGN_LT) - def cut(self, mode=''): """ Cut paper """ # Fix the size between last line and cut diff --git a/escpos/exceptions.py b/escpos/exceptions.py index adbe648..caad7a8 100644 --- a/escpos/exceptions.py +++ b/escpos/exceptions.py @@ -14,6 +14,9 @@ class Error(Exception): def __str__(self): return self.msg +class NotFoundError(Error): + """ Device wasn't found (not plugged in) """ + # Result/Exit codes # 0 = success # 10 = No Barcode type defined diff --git a/escpos/printer.py b/escpos/printer.py index 7cdedf3..4b2088b 100644 --- a/escpos/printer.py +++ b/escpos/printer.py @@ -38,7 +38,7 @@ class Usb(Escpos): """ Search device on USB tree and set is as escpos device """ self.device = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct) if self.device is None: - print "Cable isn't plugged in" + raise NotFoundError("Device not found or cable not plugged in.") if self.device.is_kernel_driver_active(0): try: @@ -137,7 +137,6 @@ class Network(Escpos): self.device.close() - class File(Escpos): """ Define Generic file printer """