#!/bin/bash ###################################################################### # Program: mkthumbnail # Purpose: Generates HTML code for thumbnails. # Arguments: See usage. # Author: Perette Barella # Version: @(#) $Id: mkthumbnails,v 1.16 2008/12/12 21:26:07 perette Exp $ #--------------------------------------------------------------------- ###################################################################### # Function: usage # Purpose: Displays the usage of this command. # Author: Perette Barella #--------------------------------------------------------------------- function usage { echo "Usage: $arg0 [options] images-per-line max-width max-height [file ....]" echo " $arg0 [options] images-per-line max-width max-height [file ...]" echo "Options:" echo " -c file Read captions from file" echo " -o Insert image in order listed in caption file." echo " -s attributes Create single image and include specified HTML attributes" echo " Images-per-line is left out when using -s option." echo " -q percent Image quality, 1 = crap and 99=great" exit 1 } ##### End of function usage ##### ###################################################################### # Function: parse_arguments # Purpose: Parses the command line arguments # Arguments: The command line arguments. # Returns: Number of arguments parsed. # Author: Perette Barella #--------------------------------------------------------------------- function parse_arguments { typeset option single=false captions="" ordered=false comments="" quality=50 while getopts 's:oc:q:?' option do case "$option" in c) captions="$OPTARG" if [ ! -e "$captions" ] then echo "`pwd`/$captions: caption file not found." 1>&2 exit 1 fi ;; o) ordered=true ;; s) single=true comments="$OPTARG" ;; q) quality="$OPTARG" if ! expr "$quality" : '[0-9]\{1,2\}$' >/dev/null then usage fi ;; *) usage ;; esac done if $ordered && [ "$captions" = "" ] then echo "$arg0: Need provide caption file for ordered thumbnails" 1>&2 exit 1 fi return $((OPTIND - 1)) } ##### End of function parse_arguments ##### ###################################################################### # Function: resize_this # Purpose: Calculates the destination size given the actual # image sizes. Generates the HTML. # Arguments: $1 - width # $2 - height # $3 - filename # Returns: 0 on success, non-0 on failure. # newwidth, newheight - size the image must result in. # Author: Perette Barella #--------------------------------------------------------------------- function resize_this { typeset x="$1" y="$2" file="$3" thumbfile="$4" status=0 alternate="" if ! expr "$x $y" : "[0-9][0-9]* [0-9][0-9]*\$" >/dev/null then echo "$arg0: width or height of $file screwed up: $x" 1>&2 return 1 fi # calculate the adjustment for width and height as a per thousand. adjwidth=9999 adjheight=9999 [ "$destwidth" != "-" ] && let adjwidth="(destwidth * 1000) / $x" [ "$destheight" != "-" ] && let adjheight="(destheight * 1000) / $y" typeset adjust=$adjwidth [ $adjheight -lt $adjwidth ] && let adjust=$adjheight let newwidth="(x * adjust) / 1000" let newheight="(y * adjust) / 1000" if $single then echo "_IMAGE(\`\`$thumbfile'', \`\`$comments'')" | sed 's/"/\"/g' else alternate="" if [ "$captions" != "" ] then alternate=$(grep "^$file" "$captions" | cut -f2- | head -1) fi if [ "$alternate" = "" ] && ! expr "$file" : "\(.*/\)\{0,\}[A-Z0-9]\{0,3\}[0-9][0-9]*\.[a-z]*\$" >/dev/null then alternate=$(echo "$file" | sed -e 's/[0-9]*\.[a-z][a-z]*$//g' \ -e 's&/&: &' -e 's/[^:a-zA-Z0-9]/ /'g) fi [ "$alternate" = "" ] && alternate="Thumbnail." [ $count -eq 0 ] && echo "" let "count=count+1" echo "_IMAGE(\`\`$thumbfile'', \`\`ALT=\"$alternate\" TITLE=\"$alternate\"'')" [ $count -eq $imagecount ] && echo "" && count=0 fi return 0 } ##### End of function resize_this ##### ###################################################################### # Function: resize_jpeg # Purpose: Resize a jpeg (making a thumbnail) and write out the new file. # Arguments: $1 - the file to resize. # Returns: 0 on success, non-0 on error # Author: Perette Barella #--------------------------------------------------------------------- function resize_jpeg { typeset file="$1" SIZE x y z thumbfile thumb_x thumb_y dirname exif dirname=$(dirname "$file") [ ! -d "$dirname/Thumbnails" ] && mkdir "$dirname/Thumbnails" thumbfile=$dirname/Thumbnails/$(basename "$file") set $(identify -format "%w %h %[EXIF:Orientation] 1" "$file") || exit 1 x="$1" y="$2" exif="$3" [ "$exif" = "unknown" ] && exif=1 # EXIF orientation values: # 1: natural orientation - N # 2: Flip Horizontal - N # 3: Rotate 180 deg clockwise = Flip V+H - N # 4: Flip vertical = rotate 180 + flip horizontal - N # 5: Rotate 90 deg clockwise + flip horizontal - X # 6: Rotate 90 deg clockwise - X # 7: Rotate 270 deg clockwise + flip horizontal - X # 8: Rotate 270 deg clockwise - X # Identify returns the size of the image as encoded. # If the image is rotated via the EXIF data, we need to # swap the X and Y coordinates to reflect this presentation. swap=false if [ $exif -ge 5 ] then z="$x" ; x="$y"; y="$z" fi resize_this "$x" "$y" "$file" "$thumbfile" || return $? if [ -f "$thumbfile" -a "$thumbfile" -nt "$file" ] && set $(identify -format "%w %h" "$thumbfile") then thumb_x="$1" thumb_y="$2" # The size may be off by +1. This seems to be # the convert utility trying to maintain proportions. margin=2 [ $thumb_x -ge $((newwidth - margin)) -a \ $thumb_x -le $((newwidth + margin)) -a \ $thumb_y -ge $((newheight - margin)) -a \ $thumb_y -le $((newheight + margin)) ] && echo "Using existing $thumbfile" 1>&2 && return 0 fi echo "Creating $thumbfile" 1>&2 && if [ "$exif" -ge 5 ] then z="$newwidth" newwidth="$newheight" newheight="$z" fi convert -quality $quality -geometry ${newwidth}x${newheight} "$file" "$thumbfile" return $? } ##### End of function resize_jpeg ##### ##### Start of main ##### arg0=$(basename $0) parse_arguments "$@" shift $? if [ \( "$single" = "false" -a $# -lt 3 \) -o \ \( "$single" = "true" -a $# -lt 2 \) ] then echo "$arg0: Too few parameters." usage fi imagecount="$1" $single || shift destwidth="$1" destheight="$2" shift 2 if $single then imagecount=2 if qualitystr=$(expr "$comments" : '.*QUALITY=\([0-9]\{1,2\}\)') then quality="$qualitystr" comments=$(echo "$comments" | sed 's/QUALITY=[0-9]* *//') fi elif $ordered then set $(cut -s -f1 "$captions" | egrep -v '^[ ]*$|^[ ]*#') if [ $# -eq 0 ] then echo "$captions: No images specified in file." 1>&2 exit 3 fi fi status=0 count=0 for file in "$@" do # if it's already a thumbnail, skip it. if [ ! -e "$file" ] then echo "$arg0: $file does not exist" 1>&2 status=1 continue fi case "$file" in */Thumbnails/*|Thumbnails/*) # Silently skip things that are already thumbnails. : ;; *) # ImageMagick handles most formats -- just pass # everyting off to it. resize_jpeg $file status=$? ;; esac done [ $count -ne 0 ] && echo "" exit $status ##### End of main #####