From c9df38d22668d6670900f8efa1dcb33a63d7718b Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 22 May 2019 20:22:52 +0200 Subject: [PATCH] printing typewriterlike --- print.py | 157 ++++++++++++++++++------------------------------- print_image.py | 104 ++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 99 deletions(-) create mode 100644 print_image.py diff --git a/print.py b/print.py index fe3cdf7..72b90b5 100644 --- a/print.py +++ b/print.py @@ -4,102 +4,61 @@ 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 - - -parser = argparse.ArgumentParser(description='Process some imagefile') -parser.add_argument('--img',dest="img", - help='pass image to print') -args = parser.parse_args() -filename = args.img -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 - -line_height = 1 -blobs = _to_column_format (im, line_height * 8); - - -#generate random Data -for i in range(COLUMNS): - DATA.append(randint(0,255)) - -height_pixels, width_pixels = im.size - -with os.fdopen(sys.stdout.fileno(), 'wb') as fp: - fp.write(ESC+b"@") - fp.write(ESC + b"3" + six.int2byte(22)); # Adjust line-feed size - 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 +import curses +import sys, termios, tty, os, time + +def getch(): + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + +class Printer(): + ESC = b'\x1B' + CHANGE_EMULATION = ESC+b'\x7B'+b'\x65' + LINE_FEED = b'\n' + CARIDGE_RET = b'\x0D' + + strokes = 0 + + def printchar(self,char): + with open('/dev/usb/lp0', 'wb') as printer: + printer.write(self.ESC+b"\x7B"+b"\x41") + char=self.strokes*" "+char + printer.write(bytes(str(char), 'utf-8')) + printer.write(self.ESC+b"\x25"+b"\x46"+b"\x0F"+b"\x00"+b"\x04"+b"\x08"+b"\x00") + self.strokes += 1 + if(self.strokes>78): + printer.write(self.LINE_FEED) + self.strokes = 0 + + def newline(self): + global strokes + with open('/dev/usb/lp0', 'wb') as printer: + printer.write(self.LINE_FEED) + self.strokes = 0 + + +def waitforinput(): + while True: + char = getch() + + if (ord(char) == 27): + print("exited publication :-(") + exit(0) + if (ord(char) == 13): + printer.newline() + else: + printer.printchar(char) + + +print("POETIC SOFTWARE") +print("Let's boot into this publication together?") +print("cancel [ok]") +printer = Printer() +waitforinput() diff --git a/print_image.py b/print_image.py new file mode 100644 index 0000000..96434a9 --- /dev/null +++ b/print_image.py @@ -0,0 +1,104 @@ +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 + + +parser = argparse.ArgumentParser(description='Process some imagefile') +parser.add_argument('--img',dest="img", + help='pass image to print') +args = parser.parse_args() +filename = args.img +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 + +line_height = 1 +blobs = _to_column_format (im, line_height * 8); + + +#generate random Data +for i in range(COLUMNS): + DATA.append(randint(0,255)) + +height_pixels, width_pixels = im.size + +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(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