GPN
This commit is contained in:
parent
a4a7e137f7
commit
f6a73c00d2
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
92
printer.py
92
printer.py
|
@ -17,11 +17,12 @@ import textwrap
|
||||||
|
|
||||||
import toml
|
import toml
|
||||||
import tweepy
|
import tweepy
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger("tweet-printer")
|
logger = logging.getLogger("tweet-printer")
|
||||||
|
|
||||||
printer_line_width = 48
|
printer_line_width = 52
|
||||||
|
|
||||||
def load_config():
|
def load_config():
|
||||||
fn = "config.toml"
|
fn = "config.toml"
|
||||||
|
@ -124,10 +125,82 @@ class Printer:
|
||||||
10 # extra*Y Unit exta space
|
10 # extra*Y Unit exta space
|
||||||
]))
|
]))
|
||||||
|
|
||||||
|
def write_image(self, img):
|
||||||
|
def size_for_printer(w,h):
|
||||||
|
return [math.ceil(w/8), (w//8)//256, h%256, h//256]
|
||||||
|
|
||||||
|
w, h = img.size
|
||||||
|
if w!=576:
|
||||||
|
logger.error("Currently images with width other than 576 can't be printed")
|
||||||
|
return
|
||||||
|
|
||||||
|
data = [0x1d, 0x76, 0x30, 0x00] + size_for_printer(*img.size)
|
||||||
|
for y in range(img.height):
|
||||||
|
current_byte = 0
|
||||||
|
current_bit = 0
|
||||||
|
for x in range(img.width):
|
||||||
|
l = img.getpixel((x, y))
|
||||||
|
to_add = 1<<(7-current_bit)
|
||||||
|
current_byte += to_add if l<127 else 0
|
||||||
|
current_bit += 1
|
||||||
|
if current_bit>7:
|
||||||
|
data.append(current_byte)
|
||||||
|
current_bit = 0
|
||||||
|
current_byte = 0
|
||||||
|
if current_bit != 0:
|
||||||
|
data.append(current_byte)
|
||||||
|
self.printer.write(bytes(data))
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
self.printer.flush()
|
self.printer.flush()
|
||||||
|
|
||||||
|
|
||||||
|
class ImageRenderer:
|
||||||
|
def __init__(self, font_file, font_size=None):
|
||||||
|
self.font = ImageFont.truetype(font_file, font_size or 18)
|
||||||
|
self.line_height = self.font.getsize("x")[1]
|
||||||
|
self.line_spacing = 4
|
||||||
|
|
||||||
|
def render_header(self, handle, name, dt, is_rt=None):
|
||||||
|
h = self.font.getsize("0@"+handle+name)[1] # Figure out, how high this line will be
|
||||||
|
w = 576
|
||||||
|
if is_rt is None:
|
||||||
|
is_rt = False
|
||||||
|
handle_text = f"@{handle} "
|
||||||
|
if is_rt:
|
||||||
|
handle_text = "RT by "+handle_text
|
||||||
|
name_text = f"({name})"
|
||||||
|
dt_text = dt.strftime(" %Y-%m-%d %H:%M:%S")
|
||||||
|
space_for_dt = self.font.getsize(dt_text)
|
||||||
|
space_for_handle = self.font.getsize(handle_text)
|
||||||
|
space_for_name = self.font.getsize(name_text)
|
||||||
|
|
||||||
|
print(space_for_handle, space_for_name, space_for_dt)
|
||||||
|
|
||||||
|
w_left_for_name = w-space_for_handle[0]-space_for_dt[0]
|
||||||
|
while len(name_text) and space_for_name[0]>w_left_for_name:
|
||||||
|
name_text = name_text[-2]+"\u2026)"
|
||||||
|
space_for_name = self.font.getsize(name_text)
|
||||||
|
|
||||||
|
print(handle_text, name_text, dt_text, sep="")
|
||||||
|
img = Image.new("1", (576, h), 0)
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
draw.text((0,0), handle_text, font=self.font, fill=1)
|
||||||
|
draw.text((space_for_handle[0], 0), name_text, font=self.font, fill=1)
|
||||||
|
draw.text((w-space_for_dt[0], 0), dt_text, font=self.font, fill=1)
|
||||||
|
return img
|
||||||
|
|
||||||
|
def render(self, lines):
|
||||||
|
spacing = self.line_height + self.line_spacing
|
||||||
|
img = Image.new("1", (576, len(lines)*spacing), 0)
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
|
for i,line in enumerate(lines):
|
||||||
|
draw.text((0, i*spacing), line, font=self.font, fill=1)
|
||||||
|
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
class StreamListener(tweepy.StreamListener):
|
class StreamListener(tweepy.StreamListener):
|
||||||
def __init__(self, title, ignore_rt=False, printer=None):
|
def __init__(self, title, ignore_rt=False, printer=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -137,7 +210,7 @@ class StreamListener(tweepy.StreamListener):
|
||||||
self.printer = printer
|
self.printer = printer
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def split_and_encode_text(cls, text, extra_lines=[]):
|
def split(cls, text, extra_lines=[]):
|
||||||
lines = extra_lines
|
lines = extra_lines
|
||||||
for line in text.splitlines(True):
|
for line in text.splitlines(True):
|
||||||
stripped = line.strip()
|
stripped = line.strip()
|
||||||
|
@ -145,7 +218,11 @@ class StreamListener(tweepy.StreamListener):
|
||||||
lines += textwrap.wrap(stripped, printer_line_width)
|
lines += textwrap.wrap(stripped, printer_line_width)
|
||||||
else:
|
else:
|
||||||
lines.append(stripped)
|
lines.append(stripped)
|
||||||
return [line.encode("latin-1") for line in lines]
|
return lines
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def split_and_encode_text(cls, text, extra_lines=[]):
|
||||||
|
return [line.encode("latin-1") for line in split(text, extra_lines)]
|
||||||
|
|
||||||
def print_tweet(self, text, headers):
|
def print_tweet(self, text, headers):
|
||||||
try:
|
try:
|
||||||
|
@ -179,6 +256,9 @@ class StreamListener(tweepy.StreamListener):
|
||||||
header = format_header(status.user.screen_name, status.user.name, status.created_at)
|
header = format_header(status.user.screen_name, status.user.name, status.created_at)
|
||||||
print(header)
|
print(header)
|
||||||
print(text)
|
print(text)
|
||||||
|
r = ImageRenderer("fonts/DejaVuSansMono.ttf")
|
||||||
|
r.render([header]+self.split(text)).show()
|
||||||
|
return True
|
||||||
if self.printer:
|
if self.printer:
|
||||||
self.print_tweet(text, [header])
|
self.print_tweet(text, [header])
|
||||||
else:
|
else:
|
||||||
|
@ -280,6 +360,10 @@ def main():
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test():
|
||||||
|
r = ImageRenderer("fonts/DejaVuSans.ttf", font_size=20)
|
||||||
|
r.render_header("trilader", "Daniel 🙏", datetime.datetime.now()).show()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
#main()
|
||||||
|
test()
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
img = Image.new("RGB", (100, 100), (47,47,47))
|
||||||
|
font = ImageFont.truetype("fonts/unifont-10.0.07.ttf", 20)
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
draw.text((0,25), "A🙏B", font=font, fill=(255,255,255))
|
||||||
|
img.show()
|
|
@ -0,0 +1,85 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import math
|
||||||
|
import PIL
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
def line(w, h=1):
|
||||||
|
out = [0x1d, 0x76, 0x30, 0x00]
|
||||||
|
out += [math.ceil(w/8), (w//8)//256]
|
||||||
|
out += [h%256, h//256]
|
||||||
|
print(w,h,out)
|
||||||
|
|
||||||
|
data = [0xFF]*(w//8)
|
||||||
|
last = 0
|
||||||
|
for i in range(w%8):
|
||||||
|
last += 2**(7-i)
|
||||||
|
if last != 0:
|
||||||
|
data.append(last)
|
||||||
|
|
||||||
|
print(len(data))
|
||||||
|
|
||||||
|
for i in range(h):
|
||||||
|
out += data
|
||||||
|
|
||||||
|
print(len(out))
|
||||||
|
|
||||||
|
return bytes(out)
|
||||||
|
|
||||||
|
def size_for_printer(w,h):
|
||||||
|
return [math.ceil(w/8), (w//8)//256, h%256, h//256]
|
||||||
|
|
||||||
|
def print_image(filename):
|
||||||
|
img = Image.open(filename)
|
||||||
|
w, h = img.size
|
||||||
|
needs_resize = False
|
||||||
|
if w>576:
|
||||||
|
f = 576/w
|
||||||
|
nw = int(w*f)
|
||||||
|
nh = int(h*f)
|
||||||
|
needs_resize=True
|
||||||
|
|
||||||
|
img = img.convert("1")
|
||||||
|
if needs_resize:
|
||||||
|
img = img.resize((nw, nh), PIL.Image.NEAREST)
|
||||||
|
|
||||||
|
data = [0x1d, 0x76, 0x30, 0x00] + size_for_printer(*img.size)
|
||||||
|
for y in range(img.height):
|
||||||
|
current_byte = 0
|
||||||
|
current_bit = 0
|
||||||
|
for x in range(img.width):
|
||||||
|
l = img.getpixel((x, y))
|
||||||
|
to_add = 1<<(7-current_bit)
|
||||||
|
current_byte += to_add if l<127 else 0
|
||||||
|
current_bit += 1
|
||||||
|
if current_bit>7:
|
||||||
|
data.append(current_byte)
|
||||||
|
current_bit = 0
|
||||||
|
current_byte = 0
|
||||||
|
if current_bit != 0:
|
||||||
|
data.append(current_byte)
|
||||||
|
return bytes(data)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
with open("/dev/usb/lp1", "wb") as lp:
|
||||||
|
lp.write(bytes([0x1b, 0x40]))
|
||||||
|
lp.write(bytes([0x1b, 0x74, 0x06]))
|
||||||
|
lp.write(" 0123456789ABCDEF0123456789ABCDEF".encode("latin-1"))
|
||||||
|
lp.write(bytes([13,10]))
|
||||||
|
for offs in range(7):
|
||||||
|
lp.write((hex(2+2*offs)[-1]+" ").encode("latin-1"))
|
||||||
|
for c in range(32):
|
||||||
|
lp.write(bytes([(1+offs)*0x20+c]))
|
||||||
|
lp.write(bytes([13,10]))
|
||||||
|
#lp.write("Hier kommt ein ".encode("latin-1"))
|
||||||
|
#lp.write(print_image("inline.bmp"))
|
||||||
|
#lp.write("-Emoji".encode("latin-1"))
|
||||||
|
#lp.write(bytes([0x0d, 0x0a]))
|
||||||
|
|
||||||
|
#lp.write(print_image("test6.bmp"))
|
||||||
|
#lp.write(bytes([0x0d, 0x0a]))
|
||||||
|
lp.write(bytes([0x1d, 0x56, 0x42, 25]))
|
||||||
|
lp.flush();
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
def main():
|
||||||
|
out = Image.new("1", (576, 400), 0)
|
||||||
|
d = ImageDraw.Draw(out)
|
||||||
|
|
||||||
|
font1 = ImageFont.truetype("fonts/DejaVuSansMono.ttf", 18)
|
||||||
|
font2 = ImageFont.truetype("fonts/NotoMono-Regular.ttf", 18)
|
||||||
|
font3 = ImageFont.truetype("fonts/VeraMono.ttf", 18)
|
||||||
|
|
||||||
|
font = font3
|
||||||
|
|
||||||
|
line_height = d.textsize("-", font=font)[1]
|
||||||
|
line_spacing = 4 + line_height
|
||||||
|
|
||||||
|
lines = ["Test",
|
||||||
|
"1234567890123456789012345678901234567890123456789012",
|
||||||
|
"---------+---------+---------+---------+---------+--",
|
||||||
|
"Hallo, das hier ist ein Test mit Sonderzeichen!",
|
||||||
|
"äöüßÄÖܵ¹²³¼€¬{[]}\\",
|
||||||
|
"/\\/\\/\\/\\/\\/\\/\\~~~+++---___^^^°°°%%$$§§"]
|
||||||
|
|
||||||
|
for i,line in enumerate(lines):
|
||||||
|
d.text((0, i*line_spacing), line, font=font, fill=1)
|
||||||
|
|
||||||
|
out.show()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue