Skip to content

Commit 16462e8

Browse files
committed
[dist] Improve logo ledgibility at small sizes
1 parent b661a1c commit 16462e8

6 files changed

Lines changed: 282 additions & 70 deletions

File tree

dist/generate_ico.py

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,67 @@
1313

1414
from PIL import Image, ImageFilter
1515

16-
# Different raster sizes to include in the ICO file.
17-
SIZES = [16, 24, 32, 48, 64, 128, 256]
16+
# Colors matching the SVG design
17+
BG = (224, 232, 240, 255) # #e0e8f0
18+
FG = (42, 53, 69, 255) # #2a3545
19+
20+
RASTER_SIZES = [16, 24, 32, 48, 64, 128, 256]
1821

19-
# Sharpen smaller sizes to improve ledgibility.
2022
SHARPEN_AMOUNT = {
21-
16: 200,
22-
24: 200,
23-
32: 100,
24-
48: 50,
25-
64: 50,
23+
24: 75,
24+
32: 75,
25+
48: 75,
26+
64: 100,
27+
128: 150,
28+
256: 150,
2629
}
2730

31+
SHARPEN_RADIUS = 0.5
32+
2833
DIST_DIR = Path(__file__).resolve().parent
29-
SVG_PATH = DIST_DIR / "pyscenedetect.svg"
34+
LOGO_DIR = DIST_DIR / "logo"
3035
ICO_PATH = DIST_DIR / "pyscenedetect.ico"
3136

37+
SVG_FOR_SIZE: dict[int, Path] = {
38+
24: LOGO_DIR / "pyscenedetect-24-48.svg",
39+
32: LOGO_DIR / "pyscenedetect-32.svg",
40+
48: LOGO_DIR / "pyscenedetect-24-48.svg",
41+
64: LOGO_DIR / "pyscenedetect-64+.svg",
42+
128: LOGO_DIR / "pyscenedetect-64+.svg",
43+
256: LOGO_DIR / "pyscenedetect-64+.svg",
44+
}
45+
46+
47+
def make_icon_16() -> Image.Image:
48+
"""Create a hand-crafted 16x16 clapperboard icon."""
49+
img = Image.new("RGBA", (16, 16), FG)
50+
px = img.load()
51+
52+
# Clear 1px padding on all sides
53+
for i in range(16):
54+
px[0, i] = BG
55+
px[15, i] = BG
56+
px[i, 0] = BG
57+
px[i, 15] = BG
58+
59+
# Arm stripe gaps (rows 2–4): clear pixels not part of a complete stripe.
60+
# A stripe x+y=s spans all 3 arm rows only when 5 <= s <= 16.
61+
for y in range(2, 5):
62+
for x in range(1, 15):
63+
if y < 4 and x < 3:
64+
continue
65+
if y > 2 and x > 12:
66+
continue
67+
if not ((x + y) % 4 < 2 and 5 <= (x + y) <= 16):
68+
px[x, y] = BG
69+
70+
# Slate interior (rows 8–12, cols 3–12)
71+
for y in range(8, 13):
72+
for x in range(3, 13):
73+
px[x, y] = BG
74+
75+
return img
76+
3277

3378
def find_inkscape() -> str:
3479
"""Find the Inkscape executable."""
@@ -55,15 +100,21 @@ def render_svg(inkscape: str, svg: Path, output: Path, size: int):
55100
def render_all_sizes(inkscape: str, work_dir: Path) -> list[Image.Image]:
56101
"""Render the SVG at all icon sizes, applying sharpening where configured."""
57102
images = []
58-
for size in SIZES:
103+
for size in RASTER_SIZES:
59104
png_path = work_dir / f"icon_{size}.png"
60-
print(f" Rendering {size}x{size}...")
61-
render_svg(inkscape, SVG_PATH, png_path, size)
62-
img = Image.open(png_path).copy()
63-
if size in SHARPEN_AMOUNT:
64-
img = img.filter(ImageFilter.UnsharpMask(radius=0.5, percent=SHARPEN_AMOUNT[size], threshold=0))
65-
print(f" Sharpened {size}x{size} (USM {SHARPEN_AMOUNT[size]}%)")
105+
if size == 16:
106+
print(f" Using hand-crafted {size}x{size} icon...")
107+
img = make_icon_16()
66108
img.save(png_path)
109+
else:
110+
svg_path = SVG_FOR_SIZE[size]
111+
print(f" Rendering {size}x{size} using {svg_path.name}...")
112+
render_svg(inkscape, svg_path, png_path, size)
113+
img = Image.open(png_path).copy()
114+
if size in SHARPEN_AMOUNT:
115+
img = img.filter(ImageFilter.UnsharpMask(radius=SHARPEN_RADIUS, percent=SHARPEN_AMOUNT[size], threshold=0))
116+
print(f" Sharpened {size}x{size} (USM {SHARPEN_AMOUNT[size]}%)")
117+
img.save(png_path)
67118
images.append(img)
68119
return images
69120

@@ -76,7 +127,7 @@ def main():
76127

77128
inkscape = find_inkscape()
78129
print(f"Using Inkscape: {inkscape}")
79-
print(f"Input SVG: {SVG_PATH}")
130+
print(f"Logo directory: {LOGO_DIR}")
80131

81132
ctx = contextlib.nullcontext(str(persist_dir)) if persist_dir else tempfile.TemporaryDirectory()
82133
with ctx as work:

dist/logo/pyscenedetect-24-48.svg

Lines changed: 72 additions & 0 deletions
Loading

dist/logo/pyscenedetect-32.svg

Lines changed: 72 additions & 0 deletions
Loading

dist/logo/pyscenedetect-64+.svg

Lines changed: 70 additions & 0 deletions
Loading

dist/pyscenedetect.ico

-2.67 KB
Binary file not shown.

dist/pyscenedetect.svg

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)