Skip to content

Instantly share code, notes, and snippets.

@acorn1010
Last active November 25, 2022 14:46
Show Gist options
  • Save acorn1010/31cc595805dd4f795651f297b6bfb926 to your computer and use it in GitHub Desktop.
Save acorn1010/31cc595805dd4f795651f297b6bfb926 to your computer and use it in GitHub Desktop.
Foony Generate Images Script (credit keraion)
#!/usr/bin/env bash
# Credit to keraion for huge readability improvements and parallelization.
set -e
# Creates webp / avif images for images that don't already exist and places them in the public folder
# This script can take a while to run
# Install deps
# sudo apt-get install -f webp ffmpeg
# MacOS deps
# brew install zopfli
# brew install ffmpeg
# brew install joedrago/repo/avifenc
# Ensure deps are executable
chmod +x ./avifenc
chmod +x ./zopflipng
chmod +x ./magick
# Path variables for conversion
DESIGN_IMG_PATH=design/images
ITEM_DESIGN_IMG_PATH=${DESIGN_IMG_PATH}/items
CURSOR_DESIGN_IMG_PATH=${DESIGN_IMG_PATH}/games/account/items/Cursors
GAME_DESIGN_IMG_PATH=${DESIGN_IMG_PATH}/games
SITE_DESIGN_IMG_PATH=${DESIGN_IMG_PATH}/site
PUB_IMG_PATH=client/public/img
ITEM_PUB_IMG_PATH=${PUB_IMG_PATH}/items
CURSOR_PUB_IMG_PATH=${PUB_IMG_PATH}/games/account/items/Cursors
GAME_PUB_IMG_PATH=${PUB_IMG_PATH}/games
SITE_PUB_IMG_PATH=${PUB_IMG_PATH}
POST_PUB_IMG_PATH=${PUB_IMG_PATH}/posts
# Increase degree of parallelism
NUM_PROCESSES=8
# Convert PNG to WEBP and AVIF.
function convert_images() {
input_file=${1?}
design_path=${2?}
pub_path=${3?}
image_type=${4?} # icon, cursor, other
if [ "${image_type}" == 'icon' ]; then
img_basename=$(sed -E "s#${design_path}/(.*)\.png#\1#" <<< ${input_file})
else
img_basename=$(sed -E "s#${design_path}/(.*)\..{3}#\1#" <<< ${input_file})
fi
png_path=${pub_path}/${img_basename}.png
png_path_2x=${pub_path}/${img_basename}.2x.png
webp_path=${pub_path}/${img_basename}.webp
avif_path=${pub_path}/${img_basename}.avif
unset png_source_path[@]
unset magick_options[@]
case "${image_type}" in
'icon')
png_source_path[0]=${png_path_2x}
png_source_path[1]=${png_path}
magick_options[0]="-resize 300x300> -gravity center -trim"
magick_options[1]="-resize 150x150> -gravity center -trim"
avifenc_options="--min 23 --max 53 --minalpha 23 --maxalpha 53"
;;
'cursor')
png_source_path[0]=${png_path}
magick_options[0]="-resize 40x40>"
avifenc_options="--min 14 --max 21 --minalpha 14 --maxalpha 21"
;;
*)
png_source_path[0]=${png_path}
avifenc_options="--min 14 --max 21 --minalpha 14 --maxalpha 21"
;;
esac
# Create paths if it does not exist.
mkdir -p "$(dirname "${png_source_path[0]}")"
# Move file if necessary.
if [ ! -f "${png_source_path[0]}" ]; then
index=0
for i in "${png_source_path[@]}"; do
./magick convert "${input_file}" -profile ./design/color_profiles/sRGBz.icc ${magick_options[index]} "${png_source_path[index]}"
./zopflipng -y --keepchunks=iCCP --lossy_transparent "${png_source_path[index]}" "${png_source_path[index]}"
index=$((index+1))
done
fi
# Convert to WEBP if necssary.
if [ ! -f "${webp_path}" ]; then
cwebp -metadata icc -quiet -q 90 "${png_source_path[0]}" -o "${webp_path}"
fi
# Convert to AVIF if necessary.
if [ ! -f "${avif_path}" ]; then
# Firefox messes up on depth 10. If we use a limited range and depth 8, then we get the correct
# sRGB rednering.
./avifenc -c aom --speed 0 --jobs 12 --range limited --ignore-icc --yuv 444 ${avifenc_options} "${png_source_path[0]}" "${avif_path}"
fi
}
# export to access in bash subshell
export -f convert_images
# Convert GIF to WEBM.
function convert_gifs() {
input_file=${1?}
pub_path=${2?}
img_basename=$(sed -E "s#${pub_path}/(.*)\..{3}#\1#" <<< ${input_file})
full_path=${pub_path}/${img_basename}
# Create paths if it does not exist.
mkdir -p "$(dirname "${full_path}")"
# Move file if necessary.
if [ ! -f "${full_path}.webm" ]; then
ffmpeg -y -i "${full_path}.gif" -c vp9 -b:v 0 -crf 40 "${full_path}.webm"
fi
}
# export to access in bash subshell
export -f convert_gifs
# These functions can run in parallel using xargs "-P #" value
find "${ITEM_DESIGN_IMG_PATH}" -type f -and -iname "*.png" -print0 | xargs -0 -P ${NUM_PROCESSES} -I {} bash -c 'convert_images "$@"' _ {} "${ITEM_DESIGN_IMG_PATH}" "${ITEM_PUB_IMG_PATH}" icon
find "${CURSOR_DESIGN_IMG_PATH}" -type f -and \( -iname "*.png" -o -iname "*.jpg" \) -print0 | xargs -0 -P ${NUM_PROCESSES} -I {} bash -c 'convert_images "$@"' _ {} "${CURSOR_DESIGN_IMG_PATH}" "${CURSOR_PUB_IMG_PATH}" cursor
find "${GAME_DESIGN_IMG_PATH}" -type f -and \( -iname "*.png" -o -iname "*.jpg" \) -print0 | xargs -0 -P ${NUM_PROCESSES} -I {} bash -c 'convert_images "$@"' _ {} "${GAME_DESIGN_IMG_PATH}" "${GAME_PUB_IMG_PATH}" other
find "${SITE_DESIGN_IMG_PATH}" -type f -and \( -iname "*.png" -o -iname "*.jpg" \) -print0 | xargs -0 -P ${NUM_PROCESSES} -I {} bash -c 'convert_images "$@"' _ {} "${SITE_DESIGN_IMG_PATH}" "${SITE_PUB_IMG_PATH}" other
find ${POST_PUB_IMG_PATH} -type f -and -iname "*.gif" -print0 | xargs -0 -P ${NUM_PROCESSES} -I {} bash -c 'convert_gifs "$@"' _ {} ${POST_PUB_IMG_PATH}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment