mirror of
https://github.com/ihabunek/toot
synced 2025-01-10 16:52:40 +01:00
105 lines
3.6 KiB
Python
105 lines
3.6 KiB
Python
import urwid
|
|
import math
|
|
import requests
|
|
import warnings
|
|
|
|
# If term_image is loaded use their screen implementation which handles images
|
|
try:
|
|
from term_image.widget import UrwidImageScreen, UrwidImage
|
|
from term_image.image import BaseImage, KittyImage, ITerm2Image, BlockImage
|
|
from term_image import disable_queries # prevent phantom keystrokes
|
|
from PIL import Image, ImageDraw
|
|
|
|
TuiScreen = UrwidImageScreen
|
|
disable_queries()
|
|
|
|
def image_support_enabled():
|
|
return True
|
|
|
|
def can_render_pixels(image_format):
|
|
return image_format in ['kitty', 'iterm']
|
|
|
|
def get_base_image(image, image_format) -> BaseImage:
|
|
# we don't autodetect kitty, iterm; we choose based on option switches
|
|
BaseImage.forced_support = True
|
|
if image_format == 'kitty':
|
|
return KittyImage(image)
|
|
elif image_format == 'iterm':
|
|
return ITerm2Image(image)
|
|
else:
|
|
return BlockImage(image)
|
|
|
|
def resize_image(basewidth: int, baseheight: int, img: Image.Image) -> Image.Image:
|
|
if baseheight and not basewidth:
|
|
hpercent = baseheight / float(img.size[1])
|
|
width = math.ceil(img.size[0] * hpercent)
|
|
img = img.resize((width, baseheight), Image.Resampling.LANCZOS)
|
|
elif basewidth and not baseheight:
|
|
wpercent = (basewidth / float(img.size[0]))
|
|
hsize = int((float(img.size[1]) * float(wpercent)))
|
|
img = img.resize((basewidth, hsize), Image.Resampling.LANCZOS)
|
|
else:
|
|
img = img.resize((basewidth, baseheight), Image.Resampling.LANCZOS)
|
|
|
|
if img.mode != 'P':
|
|
img = img.convert('RGB')
|
|
return img
|
|
|
|
def add_corners(img, rad):
|
|
circle = Image.new('L', (rad * 2, rad * 2), 0)
|
|
draw = ImageDraw.Draw(circle)
|
|
draw.ellipse((0, 0, rad * 2, rad * 2), fill=255)
|
|
alpha = Image.new('L', img.size, "white")
|
|
w, h = img.size
|
|
alpha.paste(circle.crop((0, 0, rad, rad)), (0, 0))
|
|
alpha.paste(circle.crop((0, rad, rad, rad * 2)), (0, h - rad))
|
|
alpha.paste(circle.crop((rad, 0, rad * 2, rad)), (w - rad, 0))
|
|
alpha.paste(circle.crop((rad, rad, rad * 2, rad * 2)), (w - rad, h - rad))
|
|
img.putalpha(alpha)
|
|
return img
|
|
|
|
def load_image(url):
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore") # suppress "corrupt exif" output from PIL
|
|
try:
|
|
img = Image.open(requests.get(url, stream=True).raw)
|
|
if img.format == 'PNG' and img.mode != 'RGBA':
|
|
img = img.convert("RGBA")
|
|
return img
|
|
except Exception:
|
|
return None
|
|
|
|
def graphics_widget(img, image_format="block", corner_radius=0) -> urwid.Widget:
|
|
if not img:
|
|
return urwid.SolidFill(fill_char=" ")
|
|
|
|
if can_render_pixels(image_format) and corner_radius > 0:
|
|
render_img = add_corners(img, 10)
|
|
else:
|
|
render_img = img
|
|
|
|
return UrwidImage(get_base_image(render_img, image_format), '<', upscale=True)
|
|
# "<" means left-justify the image
|
|
|
|
except ImportError:
|
|
from urwid.raw_display import Screen
|
|
TuiScreen = Screen
|
|
|
|
def image_support_enabled():
|
|
return False
|
|
|
|
def can_render_pixels(image_format: str):
|
|
return False
|
|
|
|
def get_base_image(image, image_format: str):
|
|
return None
|
|
|
|
def add_corners(img, rad):
|
|
return None
|
|
|
|
def load_image(url):
|
|
return None
|
|
|
|
def graphics_widget(img, image_format="block", corner_radius=0) -> urwid.Widget:
|
|
return urwid.SolidFill(fill_char=" ")
|