Skip to content

Commit

Permalink
Merge pull request #14 from benoitguigal/fix_#13
Browse files Browse the repository at this point in the history
Fix #13
  • Loading branch information
benoitguigal committed Jan 3, 2015
2 parents bf7b22d + 456f6e4 commit a091ebc
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 72 deletions.
183 changes: 112 additions & 71 deletions epson_printer/epsonprinter.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,74 +86,88 @@ def set_print_speed(speed):
return byte_array


def marshall_pixels(pixels, w, h):
class PrintableImage:
"""
Container for image data ready to be sent to the printer
The transformation from bitmap data to PrintableImage data is explained at the link below:
http://nicholas.piasecki.name/blog/2009/12/sending-a-bit-image-to-an-epson-tm-t88iii-receipt-printer-using-c-and-escpos/
"""

def __init__(self, data, height):
self.data = data
self.height = height

@classmethod
def from_image(cls, image):
"""
Create a PrintableImage from a PIL Image
:param image: a PIL Image
:return:
"""
(w, h) = image.size
if w > 512:
ratio = 512. / w
h = int(h * ratio)
image = image.resize((512, h), Image.ANTIALIAS)
image = image.convert('1')
pixels = list(image.getdata())

# account for double density and page mode approximate
height = int(math.ceil(h / 24) * 48)
data = []
# account for double density and page mode approximate
height = int(math.ceil(h / 24) * 48)

dyl = height % 256
dyh = int(height / 256)
# Calculate nL and nH
nh = int(w / 256)
nl = w % 256

# Set the size of the print area
byte_array = [
ESC,
87, # W
46, # xL
0, # xH
0, # yL
0, # yH
0, # dxL
2, # dxH
dyl,
dyh]

# Enter page mode
byte_array.extend([
27,
76])

# Calculate nL and nH
nh = int(w / 256)
nl = w % 256

offset = 0

while offset < h:
byte_array.extend([
ESC,
42, # *
33, # double density mode
nl,
nh])

for x in range(w):
for k in range(3):
slice = 0
for b in range(8):
y = offset + (k * 8) + b
i = (y * w) + x
v = 0
if i < len(pixels):
if pixels[i] != 255:
v = 1
slice |= (v << (7 - b))

byte_array.append(slice)

offset += 24
offset = 0

byte_array.extend([
27, # ESC
74, # J
48])
while offset < h:
data.extend([
ESC,
42, # *
33, # double density mode
nl,
nh])

# Return to standard mode
byte_array.append(12)
for x in range(w):
for k in range(3):
slice = 0
for b in range(8):
y = offset + (k * 8) + b
i = (y * w) + x
v = 0
if i < len(pixels):
if pixels[i] != 255:
v = 1
slice |= (v << (7 - b))

data.append(slice)

offset += 24

data.extend([
27, # ESC
74, # J
48])

return cls(data, height)


def append(self, other):
"""
Append a Printable Image at the end of the current instance.
:param other: another PrintableImage
:return: PrintableImage containing data from both self and other
"""
self.data.extend(other.data)
self.height = self.height + other.height
return self

return byte_array


class EpsonPrinter:
""" An Epson thermal printer based on ESC/POS"""

printer = None

Expand Down Expand Up @@ -217,21 +231,48 @@ def cut(self):
"""Full paper cut."""
return FULL_PAPER_CUT


@write_this
def print_image(self, image):
"""Print an image from a file."""
i = Image.open(image)
(w, h) = i.size
if w > 512:
ratio = 512. / w
h = int(h * ratio)
i = i.resize((512, h), Image.ANTIALIAS)
w, h = i.size
i = i.convert('1')
byte_array = marshall_pixels(list(i.getdata()), w, h)
def print_image(self, printable_image):
dyl = printable_image.height % 256
dyh = int(printable_image.height / 256)
# Set the size of the print area
byte_array = [
ESC,
87, # W
46, # xL
0, # xH
0, # yL
0, # yH
0, # dxL
2, # dxH
dyl,
dyh]

# Enter page mode
byte_array.extend([
27,
76])

byte_array.extend(printable_image.data)

# Return to standard mode
byte_array.append(12)

return byte_array

def print_images(self, *printable_images):
"""
This method allows printing several images in one shot. This is useful if the client code does not want the
printer to make pause during printing
"""
printable_image = reduce(lambda x, y: x.append(y), list(printable_images))
self.print_image(printable_image)

def print_image_from_file(self, image_file):
image = Image.open(image_file)
printable_image = PrintableImage.from_image(image)
self.print_image(printable_image)

@write_this
def underline_on(self, weight=1):
""" Activate underline
Expand Down
2 changes: 1 addition & 1 deletion epson_printer/testpage.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
printer.linefeed()
printer.print_text("Following is a bitmap")
printer.linefeed()
printer.print_image("logo.png")
printer.print_image_from_file("logo.png")
printer.linefeed()
printer.print_text("Feeding paper 10 lines before cutting")
printer.linefeed(10)
Expand Down

0 comments on commit a091ebc

Please sign in to comment.