A few days ago i reactivated my blog and decided to switch from Wordpress to Jekyll . After I had solved most problems regarding the migration, I had to think about my new publishing process and the major issue I had to face was the preparation of my images. Wordpress scaled my images and reduced the image quality for me, now I have to do this on my own.
To do this, I have written a small script that checks the width and height of a given image and scales it down and reduces its quality. This script internally uses two commands of the ImageMagick software suite, the identify and convert command. While identify allows me to collect all important information about a given image, convert enables me to convert the image to another image format, scale the image and reduce the image quality.
$ identify images/cheat-cube.png
images/cheat-cube.png PNG 1024x724 1024x724+0+0 8-bit sRGB 403KB 0.000u 0:00.000
The above example of the identify command returns the type of the image, it’s dimensions, the used color scheme and it’s size. This could now be used to convert the image to a more storage safing format, scale the image down to the needed size and reduce the quality to reduce the download time.
As I always convert my images to *.jpg files, scale them to the same with and limit them to the same high, I wrote a script that will do the job for me:
#!/bin/bash
# Define the usage text.
USAGE = $( cat << EOF
Usage: `basename $0 ` [-hvd] [-W <max_width>] [-H <max_height>] [-c <target-format>] [-o <output-directory>] [-q <quality> \n
-h|--help:
\t Displays this help.
-v|--version
\t Displays the current version of this script.
-W|--max-width
\t Maximum image width.
-H|--max-height
\t Maximum image height.
-c|--convert
\t Format the image gets converted to.
-o|--output-directory
\t Directory to save the new files to.
-q|--quality
\t Quality of the newly generated image (value between 0 and 100).
EOF
)
# Declare all used variables.
MAX_WIDTH = ""
MAX_HEIGHT = ""
CONVERT = ""
QUALITY = ""
OUTPUT_DIR = ""
# Functions for messages.
function notice() {
echo -e " $* " > &2
}
function info() {
echo -e " $* " > &2
exit 0
}
function error() {
echo -e " $* " > &2
exit 1
}
# Check if a given program is installed.
haveProg() {
which $1 &> /dev/null
}
# Join array to string.
join () {
local IFS = " $1 "
shift
echo " $* "
}
# Declare a list of packages needed in order to use this script.
packages =( 'convert' 'identify' )
# Generate a list of missing packages.
missing =()
cnt = ${# packages [@] }
for (( i = 0; i<cnt; i++)) ; do
if ! haveProg " ${ packages [i] } " ; then
missing+=( " ${ packages [i] } " )
fi
done
# Dump an error message for missing packages.
if [[ ${# missing [@] } -ne 0 ]] ; then
missingStr = ` join ' ' ${ missing [@] } `
error "The following packages are missing: $missingStr "
fi
# Initialize the positional argument list ...
args =()
# ... and fetch command line options.
while [[ -n " ${ 1 +xxx } " ]] ; do
case " $1 " in
--help | -h )
info " $USAGE "
;;
--version | -v )
info " ` basename $0 ` version 1.0"
;;
--max-width | -W )
shift
MAX_WIDTH = $1
re = '^[0-9]+$'
if ! [[ $MAX_WIDTH = ~ $re ]] ; then
error "Given max width is not a number."
fi
shift
;;
--max-height | -H )
shift
MAX_HEIGHT = $1
re = '^[0-9]+$'
if ! [[ $MAX_HEIGHT = ~ $re ]] ; then
error "Given max height is not a number."
fi
shift
;;
--convert | -c )
shift
CONVERT = $1
if ! [[ " $CONVERT " ]] ; then
error "Missing target format to convert to."
fi
CONVERT = $( tr '[:upper:]' '[:lower:]' <<< $CONVERT )
shift
;;
--output-directory | -o )
shift
OUTPUT_DIR = ${ 1 %/ }
if [ -z " $OUTPUT_DIR " ] || [ ! -d " $OUTPUT_DIR " ] ; then
error "Missing or not existing output directory."
fi
shift
;;
--quality | -q )
shift
QUALITY = $1
re = '^(100|[1-9][0-9]|[0-9])$'
if ! [[ $QUALITY = ~ $re ]] ; then
error "Given quality is not valid."
fi
shift
;;
-* )
error "unrecognized option: $1 \n\n $USAGE "
;;
* )
args+=( " $1 " )
shift
;;
esac
done
cnt = ${# args [@] }
for (( i = 0; i<cnt; i++)) ; do
file = " ${ args [i] } "
# Extract the image dimensions from the info blob ...
identity = ` identify $file | awk '{print $3}' `
# ... and split dimensions to width and height.
dimensions =( ${ identity //x/ } )
width = ${ dimensions [0] }
height = ${ dimensions [1] }
# Extract the path, filename, basename and extension.
filename = $( basename " $file " )
extension = " ${ filename ##*. } "
filename = " ${ filename %.* } "
path = $( dirname " $file " )
# Set target directory.
outDir = " $path "
if [ ! -z " $OUTPUT_DIR " ] ; then
outDir = " $OUTPUT_DIR "
fi
# Identify the current file.
printf '\n-> %s (%s x % s) %s\n' " $file " " $width " " $height " " $extension "
# Generate the new filename.
newFile = $( printf '%s/%s.%s' " $outDir " " $filename " " $CONVERT " )
# Convert the file if needed.
if [ ! -z " $CONVERT " ] && [ " $extension " != " $CONVERT " ] ; then
printf 'Converting %s to %s\n' " $file " " $newFile "
convert " $file " " $newFile "
fi
if [ ! -f " $newFile " ] ; then
cp " $file " " $newFile "
fi
# Scale down the image in width if needed.
if [ ! -z " $MAX_WIDTH " ] && [ " ${ width :- 0 } " -ge " ${ MAX_WIDTH } " ] ; then
printf 'Scaling image down from a width of %s pixels to %s pixels.\n' " $width " " $MAX_WIDTH "
convert " $newFile " -resize " $MAX_WIDTH " " $newFile "
# Extract the image dimensions from the info blob ...
identity = ` identify $newFile | awk '{print $3}' `
# ... and split dimensions to width and height.
dimensions =( ${ identity //x/ } )
width = ${ dimensions [0] }
height = ${ dimensions [1] }
fi
# Scale down the image in height if needed.
if [ ! -z " $MAX_HEIGHT " ] && [ " ${ height :- 0 } " -ge " ${ MAX_HEIGHT } " ] ; then
printf 'Scaling image down from a height of %s pixels to %s pixels.\n' " $height " " $MAX_HEIGHT "
convert " $newFile " -resize "x $MAX_HEIGHT " " $newFile "
fi
# Reduce the quality of the image if needed.
if [ ! -z " $QUALITY " ] ; then
printf 'Reducing the image quality to %s percent\n' " $QUALITY "
convert " $newFile " -quality " $QUALITY " " $newFile "
fi
done
The resulting image fits nicely in my page and is about a factor ten smaller than the original.
$ identify images/cheat-cube.jpg
images/cheat-cube.jpg JPEG 565x400 565x400+0+0 8-bit sRGB 40.9KB 0.000u 0:00.000
Hope, you find this uselful. Stay tuned.