Density-Aware Asset Rasterization
A modern Python replacement for a 2016 VBScript workflow that rasterized SVG artwork into Android drawable and mipmap density folders.
This modernizes the 2016 Android image script. The original used VBScript, Inkscape, ImageMagick, pngquant, and pngout. The durable mechanism is still useful: keep vector artwork as source, encode size rules in one place, and regenerate density-specific raster outputs on demand.
Code
from __future__ import annotations
import argparse
import subprocess
from pathlib import Path
ICON_SIZES = {
"drawable-mdpi": 48,
"drawable-hdpi": 72,
"drawable-xhdpi": 96,
"drawable-xxhdpi": 144,
"drawable-xxxhdpi": 192,
}
MENU_SIZES = {
"drawable-mdpi": 24,
"drawable-hdpi": 36,
"drawable-xhdpi": 48,
"drawable-xxhdpi": 72,
"drawable-xxxhdpi": 96,
}
LAUNCHER_SIZES = {
"mipmap-mdpi": 48,
"mipmap-hdpi": 72,
"mipmap-xhdpi": 96,
"mipmap-xxhdpi": 144,
"mipmap-xxxhdpi": 192,
}
def rules_for(svg: Path) -> dict[str, int]:
name = svg.stem.lower()
if name.startswith("ic_launcher"):
return LAUNCHER_SIZES
if name.startswith("ic_menu_"):
return MENU_SIZES
return ICON_SIZES
def render_svg(svg: Path, output: Path, size: int) -> None:
output.parent.mkdir(parents=True, exist_ok=True)
subprocess.run(
[
"magick",
"-background",
"none",
str(svg),
"-resize",
f"{size}x{size}",
str(output),
],
check=True,
)
def build_assets(source_dir: Path, res_dir: Path) -> None:
for svg in sorted(source_dir.glob("*.svg")):
for folder, size in rules_for(svg).items():
output = res_dir / folder / f"{svg.stem}.png"
render_svg(svg, output, size)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("source_dir", type=Path)
parser.add_argument("res_dir", type=Path)
args = parser.parse_args()
build_assets(args.source_dir, args.res_dir)
if __name__ == "__main__":
main()
Usage
python build_android_assets.py images app/src/main/res
Put source SVG files in images/. Files named ic_launcher*.svg are written to mipmap-*, files named ic_menu_*.svg use menu icon sizes, and other files use regular drawable icon sizes.
How It Works
The filename selects a size map. Each size map names the Android resource directory and the target pixel dimension. The renderer writes transparent PNG files into the correct resource folders.
Notes
This version uses ImageMagick’s magick command because it is scriptable and current. If your project requires exact SVG rendering parity with Inkscape, replace render_svg with an Inkscape CLI call and keep the same size maps.
The original script also compressed recently changed PNG files with pngquant and pngout. Add that as a second pass if binary size matters for your build.
Source
Original article: A script to generate android images
Full Explanation
The 2016 post shows the original VBScript workflow and the Android density mappings that inspired this smaller cross-platform version.