#!/usr/bin/env zsh # Optimize image files (losslessly by default) # # Examples: # imgoptim image.jpg image.png image.gif # imgoptim directory_of_images/ # imgoptim directory_of_images/*.png # # Requires: # PNGs: optipng, pngquant (lossy) # JPGs: jpegtran, jpegoptim (lossy) # GIFs: gifsicle # # Packages (same name on homebrew & arch linux) # optipng [pngquant] libjpeg-turbo [jpegoptim] gifsicle set -e unset CDPATH _usage() { cat <&2 echo "$OPTARG requires an argument"; _usage; exit 1;; *) >&2 echo "Not a valid arg: $opt"; _usage; exit 1;; esac done shift $((OPTIND-1)) cmds=( optipng jpegtran gifsicle ) [[ $lossy ]] && cmds=( $cmds pngquant jpegoptim ) for cmd in "optipng jpegtran gifsicle"; do if ! command -v $cmd >/dev/null; then >&2 echo "$cmd isn't installed" error=1 fi done if [[ $error ]]; then >&2 echo "There were errors, aborting" exit 1 fi for file in $@; do if [[ -d $file ]]; then imgoptim $file/* elif [[ -f $file ]]; then pre_size=$(_filesize "$file") case ${file##*.} in png) [[ $lossy ]] && pngquant $file optipng -nc -nb -o7 $file ;; gif) gifsicle --batch --optimize=3 "$file" ;; jpg|jpeg) [[ $lossy ]] && jpegoptim --max=90 "$file" jpegtran -copy none -optimize -progressive -outfile "$file" "$file" ;; *) printf "Unrecognized file '$file': ignored" ;; esac post_size=$(_filesize "$file") perc=$(echo "((${pre_size} - ${post_size}) / ${pre_size}) * 100" | bc -l) printf "* %s: %d => %d (%.2f%% reduction)\n" "$file" "${pre_size}" "${post_size}" "$perc" fi done