Image Resizing
SSI
There is no way to test if a file exists with SSI (well apart from generating an error message, which can be customised) but we do have the original image size so we can test if width >= 640 and it's it's 2011/06 or later and then embed a scaled image, but it's not so simple when you have only string' comparisons not numeric ones!
So we can have code like this to test if the image width is greater than 640 in SSI:
<!--#set var="IMG_WIDTH" value="${image["img_width"]}"-->
<!--#set var="IMG_HEIGHT" value="${image["img_height"]}"-->
<noparse><!--#if expr="(${IMG_WIDTH} = /^....$/) || (${IMG_WIDTH} = /^.....$/) || (${IMG_WIDTH} = /^......$/)"--></noparse>
<comment>if we have more that 4 digits set SCALED=on</comment> <!--#set var="SCALED" value="on"-->
<noparse><!--#elif expr="(${IMG_WIDTH} = /^...$/) && (${IMG_WIDTH} = /^7/) || (${IMG_WIDTH} = /^8/) || (${IMG_WIDTH} = /^9/)" --></noparse>
<comment>if we have 3 digits and the first one is greater than 6</comment> <!--#set var="SCALED" value="on"-->
<noparse><!--#elif expr="(${IMG_WIDTH} = /^...$/) && (${IMG_WIDTH} = /^6/) && (${IMG_WIDTH} = /^.5/) || (${IMG_WIDTH} = /^.6/) || (${IMG_WIDTH} = /^.7/) || (${IMG_WIDTH} = /^.8/) || (${IMG_WIDTH} = /^.9/)" --></noparse>
<comment>if we have 3 digits and the first one is 6 and the second is greater or equal 5</comment> <!--#set var="SCALED" value="on"-->
<noparse><!--#elif expr="(${IMG_WIDTH} = /^...$/) && (${IMG_WIDTH} = /^6/) && (${IMG_WIDTH} = /^.4/) && (${IMG_WIDTH} = /^..1/) || (${IMG_WIDTH} = /^..2/) || (${IMG_WIDTH} = /^..3/) || (${IMG_WIDTH} = /^..4/) || (${IMG_WIDTH} = /^..5/) || (${IMG_WIDTH} = /^..6/) || (${IMG_WIDTH} = /^..7/) || (${IMG_WIDTH} = /^..8/) || (${IMG_WIDTH} = /^..9/)" --></noparse>
<comment>if we have 3 digits and the first one is 6 and the second is 4 and the 3rd is greater than 0</comment> <!--#set var="SCALED" value="on"-->
<!--#else-->
<comment>we appear to have a number less or equal 640</comment> <!--#set var="SCALED" value="off"-->
<!--#endif-->
And code like this to check the date is 2011/06 or later:
<!--#set var="YEAR" value="${article.creationdate.formatted["yyyy"]}"-->
<!--#set var="MONTH" value="${article.creationdate.formatted["MM"]}"-->
<noparse><!--#if expr="${YEAR} != /^.0/"--></noparse>
<comment>if the year is greater than 2100</comment> <!--#set var="NEW_IMG" value="on"-->
<noparse><!--#elif expr="${YEAR} != /^..0/"--></noparse>
<comment>if the year is greater than or equal to 2010</comment>
<noparse><!--#if expr="${YEAR} != /^...0/"--></noparse>
<comment>if the year is greater than or equal to 2011</comment>
<noparse><!--#if expr="${YEAR} = 2011"--></noparse>
<comment>it's 2011</comment>
<noparse><!--#if expr="(${MONTH} != 01) && (${MONTH} != 02) && (${MONTH} != 03) && (${MONTH} != 04) && (${MONTH} != 05)"--></noparse>
<comment>it's 2011/06 or later</comment> <!--#set var="NEW_IMG" value="on"-->
<!--#else-->
<comment>it's 2011/05 or earlier</comment> <!--#set var="NEW_IMG" value="off"-->
<!--#endif-->
<!--#else-->
<comment>it's later than 2011</comment> <!--#set var="NEW_IMG" value="on"-->
<!--#endif-->
<!--#endif-->
<noparse><!--#elif expr="${YEAR} = /^200./"--></noparse>
<comment>if the year is less than 2010</comment> <!--#set var="NEW_IMG" value="off"-->
<!--#endif-->
A lot of the above would probably be better off written in Free Marker Classic... if we were running a version that supported numeric operators but it appears we are not...
Script for incron
incron can be set up to run on file creation but you have to be careful not to cause loops by creating new content in the same directory, see:
- http://inotify.aiken.cz/?section=incron&page=doc&lang=en
- http://www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-directories/
Update the incron tab at the start of each month, run a script called /usr/local/bin/incron-update which contains:
#!/bin/bash
YEAR=$(date +%Y)
MONTH=$(date +%m)
DIR=/imc/mir/mayday/images/$YEAR/$MONTH
echo "$DIR IN_CLOSE_WRITE /usr/local/bin/exif-strip-resize \$@ \$#" > /etc/incron.d/mayday.conf
Via this crontab:
0 0 1 * * /usr/local/bin/incron-update ; /etc/init.d/incron restart
Save this script as /usr/local/bin/exif-strip-resize:
#!/bin/bash
# this script takes the full path to a jpeg file
# and the filename, paased from incrond
# it scale big ones and also remove all exif metadata
# from the jpeg
# sub-directory for sacled images
SCALED=scaled
# check for the first command line argument
if [[ $1 ]]; then
# check it's a directory
if [[ -d $1 ]]; then
DIR=$1
else
echo "$1 isn't a directory"
exit
fi
else
echo "You need to specify the path to a file as the first argument"
exit
fi
# make a directory for the scaled images
if [[ -d $DIR/$SCALED ]]; then
echo $DIR/$SCALED exists
else
mkdir $DIR/$SCALED
fi
if [[ $2 ]]; then
FILE=$2
echo file is $DIR/$FILE
# check the file exists
if [[ -f $DIR/$FILE ]]; then
# check if it's really a jpg
TYPE=$(file -bi $DIR/$FILE)
if [[ $TYPE = "image/jpeg; charset=binary" ]]; then
# remove exif metadata preserving the image date
DATE=$(date -r $DIR/$FILE)
exiv2 rm "$DIR/$FILE"
# check is a sub-directory for scaled images is writable
if [[ -w $DIR/$SCALED ]]; then
# generate scaled versions of images if they are greater than 640px wide
# or 1024px high, maintaining the aspect ratio
WIDTH=$(identify -format %w $DIR/$FILE)
if [[ $WIDTH -gt 640 ]]; then
convert "$DIR/$FILE" -resize 640x1024 -format jpeg -quality 80 "$DIR/$SCALED/$FILE"
touch -d "$DATE" "$DIR/$SCALED/$FILE"
fi
# reset the file date
touch -d "$DATE" "$DIR/$SCALED/$FILE"
else
echo $DIR/$SCALED is not writable
fi
else
echo "$DIR/$FILE is not a jpeg"
fi
else
echo "$DIR/$FILE does not exist"
fi
else
echo "$DIR/$FILE isn't a file"
fi
Script to run via cron
This is a script to be run via cron, perhaps once a min to remove exif metadata and to scale jpeg images if they need it.
#!/bin/bash
# this script takes a directory with some jpeg files in and
# will scale the big ones and also remove all exif metadata
# from the jpegs
# you can set an optional AGE vairable here, if it's set then only
# files that are newer than AGE will be looked at -- this is handy
# if the script is running on a cron job, set it to a tile just longer
# than the cron interval, use mins for the value
AGE=200
# Directory of images is passed to this script via $1, if it's
# not then we assume that we should run in the current directory.
if [[ $1 ]]; then
# change to the directory where the images are
cd $1
DIR=$(pwd)
else
DIR=$(pwd)
fi
# get a list of the files, omitting ones that have already been scaled
if [[ $AGE ]]; then
FILES=$(find -P $DIR -type f -cmin -$AGE -name '*.jpg' ! -name '*\.indyscaled\.jpg')
else
FILES=$(find -P $DIR -type f -name '*.jpg' ! -name '*\.indyscaled\.jpg')
fi
for file in $FILES; do
#echo file: $file
# check the file exists
if [[ -f $file ]]; then
# check if we can write to the file
if [[ -w $file ]]; then
# check if it's really a jpg
TYPE=$(file -bi $file)
if [[ $TYPE = "image/jpeg; charset=binary" ]]; then
# remove exif metadata preserving the image date
DATE=$(date -r $file)
exiv2 rm "$file"
# generate scaled versions of images if they are greater than 640px wide
# or 1024px high, maintaining the aspect ratio
WIDTH=$(identify -format %w $file)
if [[ $WIDTH -gt 640 ]]; then
echo scalling $file
convert "$file" -resize 640x1024 -format jpeg -quality 80 "$file.indyscaled.jpg"
touch -d "$DATE" "$file.indyscaled.jpg"
fi
# reset the file date
touch -d "$DATE" "$file"
else
echo $file is not a jpeg
fi
else
echo $file is not writable
fi
else
echo $file does not exist
fi
done