morristech
6/29/2019 - 12:51 AM

Generate Android drawables from SVGs

Generate Android drawables from SVGs

Generate Android drawables from SVGs

BASH script to generate and update Android drawable/mipmap resources from SVG sources.

Requires either Inkscape or Image Magick for conversion.

Sample:

$ ./update.sh res/drawable < list-of-svg-files

The first argument is the relative output path without resolution qualifier.

Input is read from stdin in the following format:

FILE [SIZE] [NEGATE]

Where SIZE is the size in pixels on mdpi displays. Default is 24px. And NEGATE is a binary value, either 0 or 1, to post invert images for dark themes.

#!/usr/bin/env bash

# Try to find Inkscape or ImageMagick's convert
find_converter()
{
	if [ -z "$INKSCAPE" ]
	then
		INKSCAPE=`which inkscape` ||
			INKSCAPE='/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
	fi

	if [ -x "$INKSCAPE" ]
	then
		converter()
		{
			"$INKSCAPE" \
				"$PWD/$1" \
				-e "$PWD/$2" \
				-w $3 \
				-h $3
		}
	elif which convert &>/dev/null
	then
		converter()
		{
			convert \
				-background none \
				"$1" \
				-thumbnail $3 \
				-strip \
				"$2"
		}
	else
		return 1
	fi
}

# Convert SVG files in multiple resolutions to PNG
#
# @param 1 - output path
update()
{
	[ "$1" ] || return 1

	type converter &>/dev/null || find_converter || {
		echo "error: no Inkscape and no ImageMagick convert" >&2
		return 1
	}

	local SVG SIZE NEGATE
	local DPI MULTIPLIER
	local DIR PNG

	while read SVG SIZE NEGATE
	do
		SIZE=${SIZE:-24}

		while read DPI MULTIPLIER
		do
			DIR="$1-$DPI"

			[ -d "$DIR" ] || mkdir -p "$DIR" || {
				echo "error: couldn't create $DIR" >&2
				return $?
			}

			PNG=${SVG##*/}
			PNG="$DIR/${PNG%.*}.png"

			# skip existing up to date files
			[ -r "$PNG" ] && [ -z "`find \
				"$SVG" \
				-type f \
				-newer "$PNG"`" ] && continue

			converter \
				"$SVG" \
				"$PNG" \
				`echo "$SIZE*$MULTIPLIER" |
					bc -l |
					cut -d '.' -f 1`

			if (( $NEGATE ))
			then
				convert "$PNG" -negate "$PNG"
			fi
		done <<EOF
xxxhdpi 4
xxhdpi 3
xhdpi 2
hdpi 1.5
mdpi 1
ldpi .75
EOF
done
}

if [ "$0" == "$BASH_SOURCE" ]
then
	if (( $# < 1 ))
	then
		cat <<EOF
usage: ${0##*/} PATH

PATH - output path without resolution qualifier, e.g. "res/drawable"

Reads a list of SVG files from STDIN and converts them in multiple
resolutions to PNG.

Row format:
FILENAME [SIZE] [NEGATE]

Where SIZE is the size in pixels on mdpi displays. Default is 24px.
And NEGATE is a binary value, either 0 or 1, to post invert images
for dark themes.
EOF

		exit 0
	fi

	update "$@"
fi