You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
3.3 KiB
Python

5 years ago
import argparse
import sys
import os
import six
from random import randint
from PIL import Image, ImageOps
ESC = b'\x1B'
ETX = b'\x03'
SO = b'\x0E'
GRAPHIC = b'\x1B'+b'\x2A'+b'\x01' #1B 2A
LINE_FEED = b'\n'
CARIDGE_RET = b'\x0D'
DATA = bytearray()
COLUMNS = 2000
H = COLUMNS // 256
L = COLUMNS % 256
def _to_column_format(im, line_height):
"""
Extract slices of an image as equal-sized blobs of column-format data.
:param im: Image to extract from
:param line_height: Printed line height in dots
"""
width_pixels, height_pixels = im.size
top = 0
left = 0
blobs = []
while left < width_pixels:
remaining_pixels = width_pixels - left
box = (left, top, left + line_height, top + height_pixels)
#transform: (size, method, data=None, resample=0, fill=1)
slice = im.transform((line_height, height_pixels), Image.EXTENT, box)
bytes = slice.tobytes()
blobs.append(bytes)
left += line_height
return blobs
def _int_low_high(inp_number, out_bytes):
""" Generate multiple bytes for a number: In lower and higher parts, or more parts as needed.
to generate the H and L value
:param inp_number: Input number
:param out_bytes: The number of bytes to output (1 - 4).
"""
max_input = (256 << (out_bytes * 8) - 1);
if not 1 <= out_bytes <= 4:
raise ValueError("Can only output 1-4 byes")
if not 0 <= inp_number <= max_input:
raise ValueError("Number too large. Can only output up to {0} in {1} byes".format(max_input, out_bytes))
outp = b'';
for _ in range(0, out_bytes):
outp += six.int2byte(inp_number % 256)
inp_number = inp_number // 256
return outp
5 years ago
def print(filename, getlines=False):
5 years ago
im = Image.open(filename)
basewidth = 350
# Initial rotate. mirror, and extract blobs for each 8 or 24-pixel row
# Convert to black & white via greyscale (so that bits can be inverted)
im = im.transpose(Image.ROTATE_270).transpose(Image.FLIP_LEFT_RIGHT)
height_pixels, width_pixels = im.size
if width_pixels > basewidth:
wpercent = (basewidth/float(im.size[0]))
hsize = int((float(im.size[1])*float(wpercent)))
im = im.resize((basewidth,hsize), Image.NEAREST)
height_pixels, width_pixels = im.size
im = im.resize((height_pixels,int(width_pixels*1.5)), Image.ANTIALIAS)
im = im.convert("L") # Invert: Only works on 'L' images
im = ImageOps.invert(im) # Bits are sent with 0 = white, 1 = black in ESC/POS
im = im.convert("1") # Pure black and white
#im.show()
line_height = 1
blobs = _to_column_format (im, line_height * 8);
height_pixels, width_pixels = im.size
5 years ago
if getlines:
return len(blobs)
else:
with open('/dev/usb/lp0', 'wb') as fp:
fp.write(ESC+b"@")
fp.write(ESC+b"\x7B"+b"\x41")
#fp.write(ESC + b"3" + six.int2byte(22)); # Adjust line-feed size
fp.write(ESC + b"\x33" + bytes([22]));
#fp.write(ESC + )
fp.write(CARIDGE_RET)
for blob in blobs:
fp.write(GRAPHIC + _int_low_high( width_pixels, 2 ) + blob)
fp.write(LINE_FEED)
#fp.write(GRAPHIC + bytes([L,H]) + DATA)
fp.write(ESC + b"2"); # Reset line-feed size