199 lines
6.1 KiB
Python
199 lines
6.1 KiB
Python
import epaper
|
|
import microbmp
|
|
import time
|
|
import random
|
|
import os
|
|
import storage
|
|
import gc
|
|
|
|
gc.enable()
|
|
|
|
epd_resolution = [600, 448]
|
|
epd_colormap = [
|
|
[0x00, 0x00, 0x00], # black
|
|
[0xff, 0xff, 0xff], # white
|
|
[0x00, 0x90, 0x10], # green
|
|
[0x00, 0x00, 0xee], # blue
|
|
[0xff, 0x00, 0x00], # red
|
|
[0xff, 0xdd, 0x00], # yellow
|
|
[0xff, 0x77, 0x00], # orange
|
|
]
|
|
|
|
max_free_height = 200
|
|
|
|
def init_display():
|
|
#print("ePaper init ", str(time.localtime()))
|
|
epd = epaper.EPD_5in65()
|
|
epd.fill(epd.White)
|
|
return epd
|
|
|
|
def draw_image(filename):
|
|
global epd
|
|
global epd_colormap
|
|
global free_x, free_y, free_width, free_height
|
|
offset_x = 0
|
|
offset_y = 0
|
|
free_x = 0
|
|
free_y = 0
|
|
free_width = 0
|
|
free_height = 0
|
|
color_map = {}
|
|
def header_callback(header):
|
|
#print("header callback: ", str(header))
|
|
global epd_resolution
|
|
global offset_x, offset_y
|
|
global free_x, free_y, free_width, free_height
|
|
global max_free_height
|
|
w = header[0]
|
|
h = header[1]
|
|
rest_x = (epd_resolution[0] - w)
|
|
rest_y = (epd_resolution[1] - h)
|
|
free_x = 0
|
|
free_y = max(h, epd_resolution[1] - max_free_height)
|
|
free_width = epd_resolution[0]
|
|
free_height = min(rest_y, max_free_height)
|
|
offset_x = rest_x//2
|
|
offset_y = max(0, rest_y - max_free_height)//2
|
|
def pixel_callback(x, y, color):
|
|
global epd
|
|
global epd_colormap
|
|
global offset_x, offset_y
|
|
# translate color to color index
|
|
color_index = 0
|
|
color_key = color[0] + color[1] << 8 + color[2] << 16
|
|
if color_key in color_map:
|
|
color_index = color_map[color_key]
|
|
else:
|
|
# search for the best color
|
|
best_index = 0
|
|
best_score = 1000
|
|
for index in range(len(epd_colormap)):
|
|
c1 = epd_colormap[index]
|
|
c2 = color
|
|
score = abs(c1[0] - c2[0]) + abs(c1[1] - c2[1]) + abs(c1[2] - c2[2])
|
|
if score < best_score:
|
|
best_score = score
|
|
best_index = index
|
|
if score < 10:
|
|
break
|
|
color_index = best_index
|
|
color_map[color_key] = color_index
|
|
epd.pixel(offset_x + x, offset_y + y, color_index)
|
|
def pixel_row_callback(x, y, colors):
|
|
pass
|
|
#global epd
|
|
#print("PXL ", str([color, r,g,b, pixel]))
|
|
#for i in range(len(colors)):
|
|
# epd.pixel(offset_x + x + i, offset_y + y, color_to_index(colors[i]))
|
|
|
|
#print(str(time.localtime()), " BMP ", filename, " loading")
|
|
time_start = time.ticks_ms()
|
|
epd.fill(epd.White)
|
|
microbmp.MicroBMP(header_callback=header_callback, data_callback=pixel_callback).load(filename)
|
|
time_loaded = time.ticks_ms()
|
|
print(" time to load: ", (time_loaded - time_start) / 1000, " s")
|
|
#print(str(time.localtime()), " BMP loaded")
|
|
#epd.EPD_5IN65F_Display(epd.buffer)
|
|
#print(str(time.localtime()), " ePaper printed")
|
|
return [free_x, free_y, free_width, free_height]
|
|
|
|
def draw_pattern():
|
|
global epd
|
|
global epd_resolution
|
|
free_x = 0
|
|
free_y = 400
|
|
free_width = epd_resolution[0]
|
|
free_height = epd_resolution[1] - free_y
|
|
epd.fill_rect(0, 0, epd_resolution[0], free_y, random.randrange(2,7))
|
|
return [free_x, free_y, free_width, free_height]
|
|
|
|
def load_joke(root):
|
|
filename = root + "/jokes.json"
|
|
num_lines = sum(1 for line in open(filename))
|
|
with open(filename, mode="r") as f:
|
|
joke = None
|
|
start_pattern = "\"joke\": \""
|
|
end_pattern = "\""
|
|
for i in range(random.randrange(num_lines)):
|
|
line = f.readline()
|
|
for i in range(10):
|
|
line = f.readline()
|
|
joke_start = line.find(start_pattern)
|
|
joke_end = line.rfind(end_pattern)
|
|
if joke_start >= 0 and joke_end >= 0:
|
|
joke = line[joke_start+len(start_pattern):joke_end]
|
|
return joke
|
|
return None
|
|
|
|
|
|
def print_text(text, region, center=False):
|
|
global epd
|
|
fnt = 8
|
|
x = region[0]
|
|
y = region[1]
|
|
w = region[2]
|
|
h = region[3]
|
|
if center:
|
|
x = (w - len(text)*fnt) // 2
|
|
epd.text(text, x, y, epd.Black)
|
|
|
|
def draw_extra(region, caption):
|
|
fnt = 8
|
|
region[0] += 5
|
|
region[1] += 8
|
|
if region[2] < fnt or region[3] < fnt:
|
|
print("Not enough space for extra: ", str(region))
|
|
return
|
|
#epd.rect(region[0], region[1], region[2], region[3], epd.Black)
|
|
#region[0] += random.randrange(50)
|
|
#print_text(str(time.localtime()), region, center=True)
|
|
if caption is not None:
|
|
#region[1] += fnt * 2
|
|
print_text(caption, region)
|
|
print("Caption: ", caption)
|
|
else:
|
|
print("No caption")
|
|
|
|
# MAIN
|
|
|
|
epd = init_display()
|
|
disk = storage.Storage()
|
|
|
|
while True:
|
|
disk.mount()
|
|
images = list(filter(lambda x : x.endswith(".bmp"), os.listdir(disk.get_root_path())))
|
|
epd.EPD_5IN65F_Init()
|
|
epd.fill(epd.White)
|
|
filename = random.choice(images)
|
|
print("TV drawing image ", filename)
|
|
free_space = [0,0,0,0]
|
|
try:
|
|
free_space = draw_image(disk.get_root_path() + "/" + filename)
|
|
except Exception as e:
|
|
print("Failed drawing image from disk: ", e)
|
|
try:
|
|
free_space = draw_image("tiny.bmp")
|
|
except Exception as e:
|
|
print("Failed drawing fallback image: ", e)
|
|
free_space = draw_pattern()
|
|
caption = None
|
|
try:
|
|
caption = load_joke(disk.get_root_path())
|
|
except Exception as e:
|
|
print("Failed loading a joke: ", e)
|
|
try:
|
|
draw_extra(free_space, caption)
|
|
except Exception as e:
|
|
print("Failed drawing extra: ", e)
|
|
time_render_start = time.ticks_ms()
|
|
epd.EPD_5IN65F_Display(epd.buffer)
|
|
time_render_stop = time.ticks_ms()
|
|
print(" time to render: ", (time_render_stop - time_render_start) / 1000, " s")
|
|
print("TV showing ", filename)
|
|
epd.Sleep()
|
|
disk.umount()
|
|
|
|
print("")
|
|
gc.collect()
|
|
epd.delay_ms(60000 * 1)
|