#!/usr/bin/env bash # compressJPG.sh: compress a JPG with mozjpeg if the savings are worthwhile. # Author: Gwern Branwen # Date: 2020-02-07 # When: Time-stamp: "2026-05-08 17:33:15 gwern" # License: CC-0 set -e ## Inlining for portability # shellcheck source=./bash.sh # . ~/wiki/static/build/bash.sh # for 'get_image_files', 'green', 'red' red () { echo -e "\e[41m$@\e[0m"; } green () { echo -e "\e[32m$@\e[0m"; } warn () { printf 'Warning: %s\n' "$*" >&2; } SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" run_compressPNG () { if command -v compressPNG > /dev/null; then compressPNG "$@" elif [ -x "$SCRIPT_DIR/compressPNG" ]; then "$SCRIPT_DIR/compressPNG" "$@" else red "Error: compressPNG not found." >&2 return 1 fi } get_image_files () { mapfile -t "$1" < <(find . -maxdepth 1 -type f \ \( -iname "*.jpg" -o -iname "*.jpeg" \) \ | sort --version-sort) } args=("$@") if [ ${#args[@]} -eq 0 ]; then get_image_files args green "Attempting to use implied arguments: ${args[@]}" fi if [ ${#args[@]} -eq 0 ]; then red "Error: no arguments available!"; exit 1 else command -v file > /dev/null for FILE in "${args[@]}"; do MIME_TYPE="$(file --brief --mime-type -- "$FILE" 2>/dev/null)" || { red "Error: unable to determine file type for $FILE" >&2 continue } case "$MIME_TYPE" in image/png) red "compressJPG was called on PNG data in '$FILE'!" warn "Continuing by using 'compressPNG' without changing the extension…" run_compressPNG "$FILE" continue ;; image/jpeg) command -v jpegtran > /dev/null command -v mogrify > /dev/null ;; *) red "Error: $FILE is neither JPEG nor PNG data (file reports: $MIME_TYPE). Skipping." >&2 continue ;; esac JPG_OLD="$(mktemp /tmp/XXXXXX-original.jpg)" TMP_NEW="$(mktemp /tmp/XXXXXX-temp.jpg)" cp "$FILE" "$JPG_OLD" jpegtran -copy none -progressive -optimize -outfile "$TMP_NEW" "$JPG_OLD" mogrify -quality 60 "$TMP_NEW" ORIGINAL=$(wc -c < "$JPG_OLD") # NOTE: '-c' instead of '--bytes' for portability SMALL=$(wc -c < "$TMP_NEW") RATIO=$(echo "$ORIGINAL / $SMALL" | bc --mathlib) echo "$FILE : from $ORIGINAL to $SMALL ($RATIO)" if (( $(echo "$RATIO > 1.2" | bc --mathlib) )); then mv "$TMP_NEW" "$FILE" else green "(Not updating $FILE because savings insufficient.)" fi rm --force "$JPG_OLD" "$TMP_NEW" done fi