Site icon GetPageSpeed

Optimize website images automatically

You might have read our previous post on best tools for optimizing images, and now wondering how to automate those optimizations.

An instinctive solution is a cron job that runs optimization utilities against website files which have been added recently, e.g.:

0 1 * * 1 find /path/to/dir/ -name '*.jpg' -type f -mtime -7 -exec jpegoptim -q -s -p --all-progressive -m 65 {} \; >/dev/null 2>&1

Why this approach is wrong?

So what is the proper solution? Meet xattr and inotify Linux kernel subsystems:

Leveraging xattr

#!/bin/bash
# expects: dir (or current)
# for setfattr command
yum -y install attr

find $1 -iname '*.jpg' -exec sh -c '
  for i do
    getfattr -n user.q --only-values "$i" 2>&1 | grep "No such attribute" >/dev/null && jpegoptim --strip-all --force --all-progressive "$i" && setfattr -n user.q -v 100 "$i"
  done' sh {} +

find . -type f -iname '*.png' -exec \
  getfattr -n user.optimized --only-values {} 2>&1 | \
  grep "No such attribute" >/dev/null && \
  setfattr -n user.optimized -v 1 {} \
  && zopflipng -m -y {} {} \;

Leveraging inotify

This script will help with automatic images performance optimization.

#!/bin/bash

# The backup directory to create where the image file is found before compressing it.
BACKUPDIR=backup

if [ "$#" -eq 1 ]; then
    WATCH_DIR=$1
else
    WATCH_DIR=`pwd`
    echo -e "\e[1;31mNo watch directory provided as script parameter. Using current working directory as watch dir \e[0m "
fi

inotifywait -o /var/log/compressImage.log -dr --timefmt '%d/%m/%y %H:%M' --format '%T %w %f' \
-e close_write $WATCH_DIR | while read date time DIR FILE; do
       NEW_FILE=${DIR}${FILE}
       echo "${NEW_FILE} found"
       # Use appropriate if clause if you want to optimize other formats, beware output is always png
       #if [[ ${FILE} = *.png ]] || [[ ${FILE} = *.gif ]] || [[ ${FILE} = *.bmp ]]  || [[ ${FILE} = *.tiff ]]; then 
       if [[ ${FILE} = *.png ]]; then   
       echo "processing $NEW_FILE"
       # As a result of optipng optimization below, a new close_write gets fired for the same file. 
       #But no loop as optipng won't be able to optimze it any further on second run and we will be ok.
           optipng -o2 -keep -preserve -quiet ${NEW_FILE}
       BACKUPDIR_PATH=${DIR}/backup
           mkdir -p ${BACKUPDIR_PATH}
       mv ${DIR}${FILE}.bak ${BACKUPDIR_PATH}/${FILE}
       elif [[ ${FILE} = *.jpg ]] || [[ ${FILE} = *.jpeg ]]; then  
          echo "processing $NEW_FILE"  
          # As a result of optipng optimization below, a new close_write gets fired for the same file. 
      #But no loop as optipng won't be able to optimze it any further on second run and we will be ok.
          jpegoptim -p -t --strip-all --strip-icc --strip-iptc $NEW_FILE
       fi       
done
Exit mobile version