Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Daniel Schulte | 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 tweepy
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger("tweet-printer")
|
||||
|
||||
printer_line_width = 48
|
||||
printer_line_width = 52
|
||||
|
||||
def load_config():
|
||||
fn = "config.toml"
|
||||
|
@ -124,10 +125,82 @@ class Printer:
|
|||
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):
|
||||
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):
|
||||
def __init__(self, title, ignore_rt=False, printer=None):
|
||||
super().__init__()
|
||||
|
@ -137,7 +210,7 @@ class StreamListener(tweepy.StreamListener):
|
|||
self.printer = printer
|
||||
|
||||
@classmethod
|
||||
def split_and_encode_text(cls, text, extra_lines=[]):
|
||||
def split(cls, text, extra_lines=[]):
|
||||
lines = extra_lines
|
||||
for line in text.splitlines(True):
|
||||
stripped = line.strip()
|
||||
|
@ -145,7 +218,11 @@ class StreamListener(tweepy.StreamListener):
|
|||
lines += textwrap.wrap(stripped, printer_line_width)
|
||||
else:
|
||||
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):
|
||||
try:
|
||||
|
@ -179,6 +256,9 @@ class StreamListener(tweepy.StreamListener):
|
|||
header = format_header(status.user.screen_name, status.user.name, status.created_at)
|
||||
print(header)
|
||||
print(text)
|
||||
r = ImageRenderer("fonts/DejaVuSansMono.ttf")
|
||||
r.render([header]+self.split(text)).show()
|
||||
return True
|
||||
if self.printer:
|
||||
self.print_tweet(text, [header])
|
||||
else:
|
||||
|
@ -280,6 +360,10 @@ def main():
|
|||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
def test():
|
||||
r = ImageRenderer("fonts/DejaVuSans.ttf", font_size=20)
|
||||
r.render_header("trilader", "Daniel 🙏", datetime.datetime.now()).show()
|
||||
|
||||
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