|
1 | | -from __future__ import division |
2 | | -import math |
3 | | -import io |
4 | | -import base64 |
5 | | -import numpy as np |
6 | 1 | import usb.core |
7 | 2 | from functools import wraps |
8 | | -from PIL import Image |
| 3 | + |
9 | 4 |
|
10 | 5 | ESC = 27 |
11 | 6 | GS = 29 |
@@ -87,82 +82,6 @@ def set_print_speed(speed): |
87 | 82 | speed] |
88 | 83 | return byte_array |
89 | 84 |
|
90 | | - |
91 | | -class PrintableImage: |
92 | | - """ |
93 | | - Container for image data ready to be sent to the printer |
94 | | - The transformation from bitmap data to PrintableImage data is explained at the link below: |
95 | | - http://nicholas.piasecki.name/blog/2009/12/sending-a-bit-image-to-an-epson-tm-t88iii-receipt-printer-using-c-and-escpos/ |
96 | | - """ |
97 | | - |
98 | | - def __init__(self, data, height): |
99 | | - self.data = data |
100 | | - self.height = height |
101 | | - |
102 | | - @classmethod |
103 | | - def from_image(cls, image): |
104 | | - """ |
105 | | - Create a PrintableImage from a PIL Image |
106 | | - :param image: a PIL Image |
107 | | - :return: |
108 | | - """ |
109 | | - (w, h) = image.size |
110 | | - |
111 | | - # Thermal paper is 512 pixels wide |
112 | | - if w > 512: |
113 | | - ratio = 512. / w |
114 | | - h = int(h * ratio) |
115 | | - image = image.resize((512, h), Image.ANTIALIAS) |
116 | | - if image.mode != '1': |
117 | | - image = image.convert('1') |
118 | | - |
119 | | - pixels = np.array(list(image.getdata())).reshape(h, w) |
120 | | - |
121 | | - # Add white pixels so that image fits into bytes |
122 | | - extra_rows = int(math.ceil(h / 24)) * 24 - h |
123 | | - extra_pixels = np.ones((extra_rows, w), dtype=bool) |
124 | | - pixels = np.vstack((pixels, extra_pixels)) |
125 | | - h += extra_rows |
126 | | - nb_stripes = h / 24 |
127 | | - pixels = pixels.reshape(nb_stripes, 24, w).swapaxes(1, 2).reshape(-1, 8) |
128 | | - |
129 | | - nh = int(w / 256) |
130 | | - nl = w % 256 |
131 | | - data = [] |
132 | | - |
133 | | - pixels = np.invert(np.packbits(pixels)) |
134 | | - stripes = np.split(pixels, nb_stripes) |
135 | | - |
136 | | - for stripe in stripes: |
137 | | - |
138 | | - data.extend([ |
139 | | - ESC, |
140 | | - 42, # * |
141 | | - 33, # double density mode |
142 | | - nl, |
143 | | - nh]) |
144 | | - |
145 | | - data.extend(stripe) |
146 | | - data.extend([ |
147 | | - 27, # ESC |
148 | | - 74, # J |
149 | | - 48]) |
150 | | - |
151 | | - # account for double density mode |
152 | | - height = h * 2 |
153 | | - return cls(data, height) |
154 | | - |
155 | | - def append(self, other): |
156 | | - """ |
157 | | - Append a Printable Image at the end of the current instance. |
158 | | - :param other: another PrintableImage |
159 | | - :return: PrintableImage containing data from both self and other |
160 | | - """ |
161 | | - self.data.extend(other.data) |
162 | | - self.height = self.height + other.height |
163 | | - return self |
164 | | - |
165 | | - |
166 | 85 | class EpsonPrinter: |
167 | 86 | """ An Epson thermal printer based on ESC/POS""" |
168 | 87 |
|
@@ -226,57 +145,6 @@ def cut(self): |
226 | 145 | """Full paper cut.""" |
227 | 146 | return FULL_PAPER_CUT |
228 | 147 |
|
229 | | - @write_this |
230 | | - def print_image(self, printable_image): |
231 | | - dyl = printable_image.height % 256 |
232 | | - dyh = int(printable_image.height / 256) |
233 | | - # Set the size of the print area |
234 | | - byte_array = [ |
235 | | - ESC, |
236 | | - 87, # W |
237 | | - 46, # xL |
238 | | - 0, # xH |
239 | | - 0, # yL |
240 | | - 0, # yH |
241 | | - 0, # dxL |
242 | | - 2, # dxH |
243 | | - dyl, |
244 | | - dyh] |
245 | | - |
246 | | - # Enter page mode |
247 | | - byte_array.extend([ |
248 | | - 27, |
249 | | - 76]) |
250 | | - |
251 | | - byte_array.extend(printable_image.data) |
252 | | - |
253 | | - # Return to standard mode |
254 | | - byte_array.append(12) |
255 | | - |
256 | | - return byte_array |
257 | | - |
258 | | - def print_images(self, *printable_images): |
259 | | - """ |
260 | | - This method allows printing several images in one shot. This is useful if the client code does not want the |
261 | | - printer to make pause during printing |
262 | | - """ |
263 | | - printable_image = reduce(lambda x, y: x.append(y), list(printable_images)) |
264 | | - self.print_image(printable_image) |
265 | | - |
266 | | - def print_image_from_file(self, image_file, rotate=False): |
267 | | - image = Image.open(image_file) |
268 | | - if rotate: |
269 | | - image = image.rotate(180) |
270 | | - printable_image = PrintableImage.from_image(image) |
271 | | - self.print_image(printable_image) |
272 | | - |
273 | | - def print_image_from_buffer(self, data, rotate=False): |
274 | | - image = Image.open(io.BytesIO(base64.b64decode(data))) |
275 | | - if rotate: |
276 | | - image = image.rotate(180) |
277 | | - printable_image = PrintableImage.from_image(image) |
278 | | - self.print_image(printable_image) |
279 | | - |
280 | 148 | @write_this |
281 | 149 | def underline_on(self, weight=1): |
282 | 150 | """ Activate underline |
|
0 commit comments