generated from brennen/python_project
implement send_to_printer
add dithering to image preview
This commit is contained in:
@@ -12,6 +12,7 @@ from pathlib import Path
|
||||
from platform import system
|
||||
|
||||
from PIL import ImageOps
|
||||
from PIL.ImagePalette import ImagePalette
|
||||
from PIL.ImageTk import Image, PhotoImage
|
||||
from serial import Serial
|
||||
|
||||
@@ -20,7 +21,18 @@ IWII_RESOLUTION = Resolution(576, 720)
|
||||
|
||||
SUPPORTED_IMAGE_TYPES = sorted("*"+ext for ext, type_ in Image.registered_extensions().items() if type_ in ("PNG", "GIF", "JPEG", "WEBP", "BMP"))
|
||||
|
||||
def widget_action(func: Callable):
|
||||
IWII_PALETTE = ImagePalette(
|
||||
"P",
|
||||
[
|
||||
255, 255, 255, #white
|
||||
0, 255, 255, #cyan
|
||||
255, 0, 255, #magenta
|
||||
255, 255, 0, #yellow
|
||||
0, 0, 0, #black
|
||||
]
|
||||
)
|
||||
|
||||
def widget_action(func: Callable[[Event], None]) -> Callable[[Event], None]:
|
||||
# decorator to wrap widget actions in an error handler that displays exceptions in error message windows
|
||||
@wraps(func)
|
||||
def wrapper(event: Event):
|
||||
@@ -43,13 +55,14 @@ def widget_action(func: Callable):
|
||||
parent=event.widget.master
|
||||
)
|
||||
|
||||
event.widget.master.quit()
|
||||
quit_photobooth(event)
|
||||
exit(1)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@widget_action
|
||||
def open_preview(event: Event):
|
||||
def open_preview(event: Event) -> None:
|
||||
file = filedialog.askopenfilename(
|
||||
parent=event.widget.master,
|
||||
title="Open Image",
|
||||
@@ -64,17 +77,53 @@ def open_preview(event: Event):
|
||||
elif Path(file).exists() and Path(file).is_file():
|
||||
# load image data and resize to fit the IWII resolution preserving aspect ratio
|
||||
image_data = ImageOps.contain(Image.open(file), IWII_RESOLUTION)
|
||||
photo = PhotoImage(image_data, size=IWII_RESOLUTION)
|
||||
event.widget.create_image(0,0, anchor=NW, image=photo)
|
||||
|
||||
p_img = Image.new('P', image_data.size)
|
||||
p_img.putpalette(IWII_PALETTE)
|
||||
|
||||
conv = image_data.quantize(palette=p_img).convert("RGB")
|
||||
|
||||
photo = PhotoImage(conv, size=IWII_RESOLUTION)
|
||||
event.widget.create_image(0,0, anchor=CENTER, image=photo)
|
||||
# tkinter does not maintain a reference to the local variables of this function upon return
|
||||
# without references, the photo and its data get garbage collected and nothing is display
|
||||
# therefore we must create references to them to keep them around
|
||||
event.widget._displayed_photo=photo
|
||||
event.widget.master.photobooth_image = image_data
|
||||
event.widget.master.photobooth_image = conv
|
||||
|
||||
@widget_action
|
||||
def send_to_iwii(event: Event):
|
||||
raise NotImplementedError
|
||||
def send_to_printer(event: Event) -> None:
|
||||
if not event.widget.master.photobooth_image:
|
||||
messagebox.showwarning(
|
||||
title="Warning",
|
||||
message="Nothing to print. Please take a picture first.",
|
||||
parent=event.widget.master
|
||||
)
|
||||
else:
|
||||
with Serial(
|
||||
"/dev/ttyUSB0",
|
||||
baudrate=9600,
|
||||
xonxoff=True,
|
||||
rtscts=False
|
||||
) as printer:
|
||||
printer.write(event.widget.master.photobooth_image.tobytes())
|
||||
|
||||
|
||||
@widget_action
|
||||
def clear_preview(event: Event) -> None:
|
||||
if event.widget.master.photobooth_image:
|
||||
# remove the image data
|
||||
event.widget.master.photobooth_image = None
|
||||
# clear the canvas
|
||||
event.widget.delete("all")
|
||||
# remove the reference to the data formerly displayed on the canvas so it gets GC'd
|
||||
del event.widget._displayed_photo
|
||||
|
||||
|
||||
@widget_action
|
||||
def quit_photobooth(event: Event) -> None:
|
||||
event.widget.master.destroy()
|
||||
event.widget.master.quit()
|
||||
|
||||
|
||||
def photobooth():
|
||||
@@ -107,7 +156,9 @@ def photobooth():
|
||||
|
||||
preview = Canvas(master=app, height=IWII_RESOLUTION.height, width=IWII_RESOLUTION.width)
|
||||
preview.bind("<space>", open_preview)
|
||||
preview.bind("<Return>", send_to_iwii)
|
||||
preview.bind("<Return>", send_to_printer)
|
||||
preview.bind("c", clear_preview)
|
||||
preview.bind("q", quit_photobooth)
|
||||
preview.focus_set()
|
||||
preview.pack(side="top")
|
||||
app.mainloop()
|
||||
|
||||
Reference in New Issue
Block a user