Skip to content

Instantly share code, notes, and snippets.

@MarkKoz
Last active June 7, 2020 06:38
Show Gist options
  • Save MarkKoz/a9ef1b025d4d8dea0a10c98c6e03cab5 to your computer and use it in GitHub Desktop.
Save MarkKoz/a9ef1b025d4d8dea0a10c98c6e03cab5 to your computer and use it in GitHub Desktop.
Convert SVGs into PNGs using Inkscape
#!/usr/bin/env bash
#
# Convert SVGs into PNGs using Inkscape.
#
# PNGs are saved to the same location as their corresponding SVG files.
# If sizes are specified, they are appended to the names of the PNGs.
#
# The env var INKSCAPE_BIN can be set to configure the path to Inkscape.
#
# Usage: ./export_svgs.sh <input_path> [size [size]...]
#
# input_path can be a file or a directory.
#
# If a size isn't specified, Inkscape will just do its default behaviour:
# ./export_svgs.sh image.svg
#
# A size can be specified as a single integer, which will be used for width
# and height:
# ./export_svgs.sh image.svg 900
#
# A size can also be specified as two integers joined by an 'x' character.
# The left integer is the width and the right is the height:
# ./export_svgs.sh image.svg 300x500
#
# Multiple sizes can be specified:
# ./export_svgs.sh image.svg 300x500 900 600x400 875
set -euo pipefail
shopt -s inherit_errexit
export_svg() {
local input_file="${1:?"export_svg: argument 1 'input_file' is unset"}"
local size="${2}"
local svg_name="${input_file%.*}"
local args=()
local size_suffix=""
local size_message="default size"
# Parse the size.
if [[ "${size}" ]]; then
# Split the size by an "x" character
readarray -tdx dimensions < <(printf '%s' "${size}")
# Check if there was a split.
if [[ "${#dimensions[@]}" = 1 ]]; then
# There's no split; use same value for width and height.
size_message="${size}x${size}"
size_suffix="_${size}"
args=(-w "${size}" -h "${size}")
else
# There is a split; left value is width and right is height.
size_message="${size}"
size_suffix="_${dimensions[0]}_${dimensions[1]}"
args=(-w "${dimensions[0]}" -h "${dimensions[1]}")
fi
fi
args+=(-o "${svg_name}${size_suffix}.png" "${input_file}")
printf '%s\n' "Exporting ${svg_name} at ${size_message}..."
if ! "${INKSCAPE_BIN:-"inkscape"}" "${args[@]}"; then
printf '%s\n' "Failed to export ${svg_name} at ${size_message}" >&2
return 1
fi
}
export_svgs() {
local input_files
local sizes=("${@:2}")
local argstr=""
local arg_n=2
# Check if argument 1 is a file or directory.
if [[ -d "$1" ]]; then
# Its a directory; get all SVG files in it.
input_files=("$1"/*.svg)
elif [[ -f "$1" ]]; then
input_files=("$1")
else
echo "Argument 1 is not an existing file or directory." >&2
return 1
fi
# Create a single string of arguments for all calls.
# xargs will split this string into arguments for each call.
for i in "${!input_files[@]}"; do
# Check if any sizes were specified.
if (( "${#sizes[@]}" )); then
# Add args for each size.
for size_i in "${!sizes[@]}"; do
argstr="${argstr} ${input_files[$i]} ${sizes[$size_i]}"
done
else
# No sizes were specified.
argstr="${argstr} ${input_files[$i]}"
arg_n=1
fi
done
# Export all SVGs in all sizes in parallel, up to 8 simultaneous calls.
export -f export_svg
export INKSCAPE_BIN
printf "%s" "${argstr}" | xargs -n "${arg_n}" -P 8 bash -c 'export_svg "${@}"' _
}
export_svgs "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment