Skip to content

Commit b6e5f95

Browse files
committed
Replace optipng with pyoxipng
Avoid spawning a subprocess and installing an OS package.
1 parent 456a2bc commit b6e5f95

File tree

5 files changed

+19
-9
lines changed

5 files changed

+19
-9
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
- name: apt install
6060
run: |
6161
sudo apt-get update
62-
sudo apt-get install --no-install-suggests --no-install-recommends inkscape icoutils scour optipng
62+
sudo apt-get install --no-install-suggests --no-install-recommends inkscape icoutils scour
6363
6464
- uses: actions/[email protected]
6565
with:

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ The [conventions document](./conventions.md) describes some idioms used in the c
2424

2525
Grab the build dependencies with:
2626

27-
$ sudo apt install brotli inkscape icoutils git scour optipng \
27+
$ sudo apt install brotli inkscape icoutils git scour \
2828
python3-dev build-essential
2929

3030
[Install pip](https://pip.pypa.io/en/latest/installing/#get-pip), then install [Tox](http://tox.readthedocs.org/en/latest/).

bin/compile-static.py

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/python3
2-
# Copyright © 2018, 2019, 2020, 2022, 2024 Tom Most <[email protected]>
2+
# Copyright © 2018, 2019, 2020, 2022, 2024, 2025 Tom Most <[email protected]>
33
#
44
# This program is free software: you can redistribute it and/or modify
55
# it under the terms of the GNU General Public License as published by
@@ -55,6 +55,7 @@
5555
from typing import Optional, Sequence
5656

5757
import brotli
58+
import oxipng
5859
import tinycss2
5960
import zopfli.gzip
6061

@@ -220,7 +221,7 @@ async def rasterize_favicon(favicon: Path, build_dir: Path, w: Writer) -> None:
220221
"""
221222
Use Inkscape to generate two raster versions of the favicon:
222223
223-
- icon-[hexchars].png — a 152x152 PNG, optimized with optipng.
224+
- icon-[hexchars].png — a 152x152 PNG, optimized with oxipng.
224225
- icon-[hexchars].ico — ICO with 16x16, 24x24, 32x32, and 64x64 versions.
225226
Built with icotool.
226227
"""
@@ -240,13 +241,19 @@ async def rasterize_favicon(favicon: Path, build_dir: Path, w: Writer) -> None:
240241
raise ProcFailed(f"inkscape failed to write {outfile!r}", stdout, stderr)
241242

242243
png_path = Path(outfiles.pop())
243-
ico_path = build_dir / f"{favicon.stem}.ico"
244-
await asyncio.gather(
245-
_run(["optipng", "-quiet", str(png_path)]),
246-
_run(["icotool", "--create", "-o", str(ico_path), *outfiles]),
244+
oxipng.optimize(
245+
str(png_path),
246+
level=4,
247+
interlace=oxipng.Interlacing.Off,
248+
strip=oxipng.StripChunks.safe(),
249+
deflate=oxipng.Deflaters.zopfli(15),
250+
optimize_alpha=True,
247251
)
248-
249252
w.add_file(hashname("icon", "png", png_path.read_bytes()), png_path)
253+
254+
ico_path = build_dir / f"{favicon.stem}.ico"
255+
# icotool reencodes the PNGs with libpng, so there's no point optimizing them.
256+
await _run(["icotool", "--create", "-o", str(ico_path), *outfiles])
250257
w.add_file(hashname("icon", "ico", ico_path.read_bytes()), ico_path)
251258

252259

requirements_static.in

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
brotli
22
tinycss2
33
zopfli
4+
pyoxipng

requirements_static.txt

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#
77
brotli==1.1.0
88
# via -r requirements_static.in
9+
pyoxipng==9.1.0
10+
# via -r requirements_static.in
911
tinycss2==1.4.0
1012
# via -r requirements_static.in
1113
webencodings==0.5.1

0 commit comments

Comments
 (0)