2"""Renders icons/icon.png to the PNG sizes the manifest lists. Needs Pillow (python3 -m pip install pillow).
4The source is the full-size app icon. Its transparent margin is trimmed first so the rounded square fills the
516 and 32 px toolbar icons; the larger sizes keep a little padding, as Chrome's extension page expects.
7from pathlib import Path
9from PIL import Image, ImageFilter
11ICONS = Path(__file__).resolve().parent.parent / "icons"
12# size -> padding in px on each side at that size
13SIZES = {16: 0, 32: 0, 48: 2, 128: 8}
16def trimmed(src: Image.Image) -> Image.Image:
17 # Near-invisible specks around the shape would otherwise widen the bounding box.
18 solid = src.getchannel("A").point(lambda a: 255 if a > 32 else 0)
19 left, top, right, bottom = solid.getbbox()
20 side = max(right - left, bottom - top)
21 cx, cy = (left + right) / 2, (top + bottom) / 2
22 box = (round(cx - side / 2), round(cy - side / 2), round(cx + side / 2), round(cy + side / 2))
26def render(art: Image.Image, size: int, pad: int) -> Image.Image:
27 inner = size - 2 * pad
28 small = art.resize((inner, inner), Image.LANCZOS)
30 small = small.filter(ImageFilter.UnsharpMask(radius=0.6, percent=60, threshold=0))
31 out = Image.new("RGBA", (size, size), (0, 0, 0, 0))
32 out.paste(small, (pad, pad))
37 art = trimmed(Image.open(ICONS / "icon.png").convert("RGBA"))
38 for size, pad in SIZES.items():
39 render(art, size, pad).save(ICONS / f"{size}.png", optimize=True)
40 print("icons written")
43if __name__ == "__main__":
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list