TRX/tools/shared/icons.py

79 lines
2 KiB
Python
Raw Permalink Normal View History

2024-10-02 10:23:23 +02:00
import tempfile
from dataclasses import dataclass
from pathlib import Path
from subprocess import check_call
@dataclass
class IconSpec:
size: int
type: str
SPECS = [
IconSpec(size=32, type="bmp"),
IconSpec(size=16, type="bmp"),
IconSpec(size=256, type="png"),
IconSpec(size=128, type="png"),
IconSpec(size=64, type="png"),
IconSpec(size=48, type="png"),
IconSpec(size=32, type="png"),
IconSpec(size=16, type="png"),
]
def resize_transformer(path: Path, spec: IconSpec) -> None:
check_call(
[
"convert",
f"{path}[0]",
"-filter",
"lanczos",
"-resize",
f"{spec.size}x{spec.size}",
f"PNG:{path}",
]
)
def quantize_transformer(path: Path, spec: IconSpec) -> None:
quantized_path = path.with_stem(f"{path.stem}-quantized")
check_call(["pngquant", path, "--output", quantized_path])
path.write_bytes(quantized_path.read_bytes())
quantized_path.unlink()
def optimize_transformer(path: Path, spec: IconSpec) -> None:
check_call(["zopflipng", "-y", path, path])
def convert_transformer(path: Path, spec: IconSpec) -> None:
if spec.type != "png":
check_call(["convert", path, f"{spec.type.upper()}:{path}"])
TRANSFORMERS = [
resize_transformer,
quantize_transformer,
optimize_transformer,
convert_transformer,
]
def generate_icon(source_path: Path, target_path: Path) -> None:
aux_paths = []
with tempfile.TemporaryDirectory() as tmpdir:
tmp_path = Path(tmpdir)
for spec in SPECS:
aux_path = tmp_path / f"{spec.size}-{spec.type}.tmp"
aux_path.write_bytes(source_path.read_bytes())
for transform in TRANSFORMERS:
transform(aux_path, spec)
aux_paths.append(aux_path)
# NOTE: image order is important for certain software.
check_call(["identify", *aux_paths])
check_call(["convert", *aux_paths, target_path])