This commit is contained in:
Daniel Schulte 2018-05-11 10:40:35 +02:00
parent a4a7e137f7
commit f6a73c00d2
10 changed files with 212 additions and 4 deletions

BIN
fonts/DejaVuSans.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
fonts/DejaVuSansMono.ttf Normal file

Binary file not shown.

BIN
fonts/NotoMono-Regular.ttf Normal file

Binary file not shown.

BIN
fonts/VeraMono.ttf Normal file

Binary file not shown.

BIN
fonts/unifont-10.0.07.ttf Normal file

Binary file not shown.

View File

@ -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()

8
rendertest.py Normal file
View File

@ -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()

85
test.py Executable file
View File

@ -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()

31
test2.py Normal file
View File

@ -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()