mirror of
https://github.com/9001/copyparty.git
synced 2025-08-16 08:32:13 -06:00
104 lines
3.5 KiB
Python
104 lines
3.5 KiB
Python
# coding: utf-8
|
|
from __future__ import print_function, unicode_literals
|
|
|
|
import argparse # typechk
|
|
import colorsys
|
|
import hashlib
|
|
import re
|
|
|
|
from .__init__ import PY2
|
|
from .th_srv import HAVE_PIL, HAVE_PILF
|
|
from .util import BytesIO, html_escape # type: ignore
|
|
|
|
|
|
class Ico(object):
|
|
def __init__(self, args: argparse.Namespace) -> None:
|
|
self.args = args
|
|
|
|
def get(self, ext: str, as_thumb: bool, chrome: bool) -> tuple[str, bytes]:
|
|
"""placeholder to make thumbnails not break"""
|
|
|
|
bext = ext.encode("ascii", "replace")
|
|
ext = bext.decode("utf-8")
|
|
zb = hashlib.sha1(bext).digest()[2:4]
|
|
if PY2:
|
|
zb = [ord(x) for x in zb] # type: ignore
|
|
|
|
c1 = colorsys.hsv_to_rgb(zb[0] / 256.0, 1, 0.3)
|
|
c2 = colorsys.hsv_to_rgb(zb[0] / 256.0, 0.8 if HAVE_PILF else 1, 1)
|
|
ci = [int(x * 255) for x in list(c1) + list(c2)]
|
|
c = "".join(["%02x" % (x,) for x in ci])
|
|
|
|
w = 100
|
|
h = 30
|
|
if as_thumb:
|
|
sw, sh = self.args.th_size.split("x")
|
|
h = int(100.0 / (float(sw) / float(sh)))
|
|
|
|
if chrome:
|
|
# cannot handle more than ~2000 unique SVGs
|
|
if HAVE_PILF:
|
|
# pillow 10.1 made this the default font;
|
|
# svg: 3.7s, this: 36s
|
|
try:
|
|
from PIL import Image, ImageDraw
|
|
|
|
# [.lt] are hard to see lowercase / unspaced
|
|
ext2 = re.sub("(.)", "\\1 ", ext).upper()
|
|
|
|
h = int(128.0 * h / w)
|
|
w = 128
|
|
img = Image.new("RGB", (w, h), "#" + c[:6])
|
|
pb = ImageDraw.Draw(img)
|
|
_, _, tw, th = pb.textbbox((0, 0), ext2, font_size=16)
|
|
xy = (int((w - tw) / 2), int((h - th) / 2))
|
|
pb.text(xy, ext2, fill="#" + c[6:], font_size=16)
|
|
|
|
img = img.resize((w * 2, h * 2), Image.NEAREST)
|
|
|
|
buf = BytesIO()
|
|
img.save(buf, format="PNG", compress_level=1)
|
|
return "image/png", buf.getvalue()
|
|
|
|
except:
|
|
pass
|
|
|
|
if HAVE_PIL:
|
|
# svg: 3s, cache: 6s, this: 8s
|
|
from PIL import Image, ImageDraw
|
|
|
|
h = int(64.0 * h / w)
|
|
w = 64
|
|
img = Image.new("RGB", (w, h), "#" + c[:6])
|
|
pb = ImageDraw.Draw(img)
|
|
try:
|
|
_, _, tw, th = pb.textbbox((0, 0), ext)
|
|
except:
|
|
tw, th = pb.textsize(ext) # type: ignore
|
|
|
|
tw += len(ext)
|
|
cw = tw // len(ext)
|
|
x = ((w - tw) // 2) - (cw * 2) // 3
|
|
fill = "#" + c[6:]
|
|
for ch in ext:
|
|
pb.text((x, (h - th) // 2), " %s " % (ch,), fill=fill)
|
|
x += cw
|
|
|
|
img = img.resize((w * 3, h * 3), Image.NEAREST)
|
|
|
|
buf = BytesIO()
|
|
img.save(buf, format="PNG", compress_level=1)
|
|
return "image/png", buf.getvalue()
|
|
|
|
svg = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<svg version="1.1" viewBox="0 0 100 {}" xmlns="http://www.w3.org/2000/svg"><g>
|
|
<rect width="100%" height="100%" fill="#{}" />
|
|
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" xml:space="preserve"
|
|
fill="#{}" font-family="monospace" font-size="14px" style="letter-spacing:.5px">{}</text>
|
|
</g></svg>
|
|
"""
|
|
svg = svg.format(h, c[:6], c[6:], html_escape(ext, True))
|
|
|
|
return "image/svg+xml", svg.encode("utf-8")
|