#!/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 <<EOL
Usage: ${0:A:t} [-lh] IMAGE [IMAGE2 [IMAGE3 [...]]]

  -l    enable lossy compression
  -h    this help
EOL
}

_filesize() {
  case $OSTYPE in
    darwin*) stat -c%s "$1" ;;
    *) stat --printf="%s" "$1" ;;
  esac
}

#
while getopts hl opt; do
  case $opt in
    h) _usage; exit;;
    l) lossy=1;;
    :) >&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 )
[[ -n $lossy ]] && cmds=( $cmds pngquant jpegoptim )
for cmd in ${cmds[@]}; do
  if ! command -v $cmd >/dev/null; then
    >&2 echo "$cmd isn't installed"
    error=1
  fi
done
if [[ -n $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)
        [[ -n $lossy ]] && pngquant $file
        optipng -nc -nb -o7 $file
        ;;
      gif)
        gifsicle --batch --optimize=3 "$file"
        ;;
      jpg|jpeg)
        [[ -n $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