#!/bin/bash # # This script scans the given JPEG files (whose names # must end in .jpg), generates a thumbnail and a reduced # version in JPEG of each, and generates an HTML page with all the # thumbnails and links to the reduced version and the original. # # If the image contains PhotoRDF (wrapped in Adobe's XMP), it is used # to generate a description. # # The HTML page with thumbnails is written to the first argument: # # thumbnails index.html *.jpg # # Options: # # -t title # Use title as the title of the thumbnails page (default: # "Thumbnails") # -l language # Add lang=language to the generated HTML pages and translate the # generated canned phrases to that language. Currently supported # languages: "en" (=English, default), "nl" (=Dutch) and "fr" # (=French) # -n name # The name to insert in the copyright message at the bottom # (default: "Bert Bos") # -c percent # Try to make thumbnails better by showing only the center of the # image. 100 means the whole image is used (default), 80 means the # image's four edges are cut off such that only 80% of its original # width and height remain # -p file # Insert the contents of file into the index file, before the # thumbnails. # -w number # Width or height (whichever is larger) of thumbnails, in pixels # (default: 100) # -s stylesheet # URI reference of an external style sheet. By default, the script # will insert a " else echo "" fi echo "" echo echo "" echo "

$title

" if [ -f "$preamble" ]; then echo "
" cat "$preamble" echo "
" fi } # output_footer -- output copyright message, etc. at the end function output_footer { echo "" echo "" echo "" } # ask_pagetitle -- put up a dialog with an input box for the page title function ask_pagetitle { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." dialog --backtitle "$d_backtitle"\ --inputbox "Title for thumbnails page" 10 60 "$pagetitle" 2>$TMP case $? in 0) pagetitle="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac } # ask_owner -- put up a dialog with an input box for the copyright owner function ask_owner { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." dialog --backtitle "$d_backtitle"\ --inputbox "Copyright owner" 10 60 "$owner" 2>$TMP case $? in 0) owner="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac } # ask_images -- Ask for the names of all the JPEG images to process function ask_images { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." dialog --backtitle "$d_backtitle"\ --inputbox "The JPEG images (e.g., \"*.jpg\")" 10 70 "$images" 2>$TMP case $? in 0) images="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac } # ask_output -- put up a dialog for the name of the generated thumbnails page function ask_output { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." local again=true while [ $again = true ]; do dialog --backtitle "$d_backtitle"\ --inputbox "Output file name (\"-\" for standard out)" 10 60 "$output" 2>$TMP case $? in 0) output="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac if [ -z "$output" ]; then dialog --backtitle "$d_backtitle"\ --msgbox "The file name cannot be empty. If you want output\ to be printed to standard output, use a single dash (\"-\")"\ 12 60 again=true else again=false fi done } # ask_language -- present the choice of output languages function ask_language { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." local en=off fr=off nl=off case "$language" in en) en=on;; fr) fr=on;; nl) nl=on;; esac dialog --backtitle "$d_backtitle"\ --radiolist "Language for HTML pages" 12 40 3\ en "English" $en\ fr "French" $fr\ nl "Dutch" $nl 2>$TMP case $? in 0) language="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac } # ask_preamble -- ask for the name of a file to insert function ask_preamble { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." dialog --backtitle "$d_backtitle"\ --inputbox "Optional file with text to insert" 10 60 "$preamble" 2>$TMP case $? in 0) preamble="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac } # ask_percentage -- put up a dialog for the percentage crop of thumbnails function ask_percentage { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." local again=true while [ $again = true ]; do dialog --backtitle "$d_backtitle"\ --max-input 3 --trim\ --inputbox "Percentage of photo shown in thumbnail (100 = everything)" 10 60 "$crop" 2>$TMP case $? in 0) crop="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac case "$crop" in [1-9] | [1-9][0-9] | 100) again=false;; *) dialog --backtitle "$d_backtitle"\ --msgbox "The percentage must be between 1 and 100. Values smaller\ than 100 cause the thumbnail to show only the center part\ of the photo."\ 12 60 again=true;; esac done } # ask_thumbnail_size -- put up a dialog for the size of thumbnails function ask_thumbnail_size { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." local again=true while [ $again = true ]; do dialog --backtitle "$d_backtitle"\ --max-input 3 --trim\ --inputbox "Size of thumbnails (in pixels)" 10 60 "$w1" 2>$TMP case $? in 0) w1="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac case "$w1" in [1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]) again=false;; *) dialog --backtitle "$d_backtitle"\ --msgbox "The size must be between 1 and 9999."\ 12 60 again=true;; esac done } # ask_grouping -- ask if the thumbnails should be grouped function ask_grouping { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." local none=off series=off year=off case "$group" in series) series=on;; year) year=on;; *) none=on;; esac dialog --backtitle "$d_backtitle"\ --radiolist "Group thumbnails?" 10 60 3\ "" "Don't group" $none\ "series" "By series" $series\ "year" "By year" $year 2>$TMP case $? in 0) group=$(<$TMP);; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac } # ask_style -- ask for the URL of an ecternal style sheet function ask_style { local TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." dialog --backtitle "$d_backtitle"\ --inputbox "Optional external style sheet" 10 60 "$style" 2>$TMP case $? in 0) style="$(<$TMP)";; # OK 1|255) exit;; # Cancel|ESC *) die "Bug! Cannot happen!";; esac } # Parse options while getopts "hgyit:l:n:m:c:w:p:s:" flag; do case $flag in "i") interactive=true;; "t") pagetitle="$OPTARG";; "l") language="$OPTARG";; "n") owner="$OPTARG";; "m") email="$OPTARG";; "c") crop="$OPTARG";; "w") w1="$OPTARG";; "p") preamble="$OPTARG";; "s") style="$OPTARG";; "g") group=series;; "y") group=year;; "h") help;; "?") usage;; esac done # Parse the name of the HTML file to output to $interactive || [[ "${!OPTIND}" != "" ]] || usage output="${!OPTIND}" shift $OPTIND images="$*" # Check if the dialog program is present. # DIALOG=`type -p dialog 2>/dev/null` # If interactive, prompt for all parameters. Loop until user is # satisfied. # while $interactive; do if [ -x "$DIALOG" ]; then ask_pagetitle ask_language ask_owner ask_output ask_images ask_percentage ask_thumbnail_size ask_preamble ask_style ask_grouping if dialog --backtitle "$d_backtitle" --yesno\ "Are these correct?\n\ Title = \"$pagetitle\"\n\ Language = \"$language\"\n\ Owner = \"$owner\"\n\ Preamble = \"$preamble\"\n\ Style sheet = \"$style\"\n\ Output = \"$output\"\n\ Group by = ${group:-(none)}" 15 72; then interactive=false fi else # No dialog, use read instead read -e -p "Page title? [$pagetitle] " [[ -z "$REPLY" ]] || pagetitle="$REPLY" read -e -p "Language? [$language] " [[ -z "$REPLY" ]] || language="$REPLY" read -e -p "Owner? [$owner] " [[ -z "$REPLY" ]] || owner="$REPLY" read -e -p "Preamble? [$preamble] " [[ -z "$REPLY" ]] || preamble="$REPLY" read -e -p "Style URL? [$style] " [[ -z "$REPLY" ]] || style="$REPLY" read -e -p "Output file? ${output:+[$output]} " [[ -z "$REPLY" ]] || output="$REPLY" read -e -p "Images? [$images] " [[ -z "$REPLY" ]] || images="$REPLY" if [ -z "$output" ]; then echo echo "** Sorry, the output file must be specified." echo "** Use \"-\" if you want to print to standard output." echo else echo echo "Page title : $pagetitle" echo "Language : $language" echo "Owner : $owner" echo "Output : $output" echo "Images : $images" echo read -e -p "Is this OK? [Y] " if [ "$REPLY" = "y" -o "$REPLY" = "Y" -o "$REPLY" = "" ];then interactive=false fi fi fi done # Sizes that depend on the thumbnail size w2=`expr $w1 + 50` h1=$w1 h2=`expr \( $h1 + 102 \) + \( 2 \* $border \)` # Redirect generated HTML output to file, unless it is "-" (stdout) [[ "$output" = "-" ]] || exec >"$output" # Create a temporary file to hold the text for the copyright TMP=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." echo "Copyright © "`date +%Y`" $owner <$email>" >$TMP RDFFILE=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." TMP2=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." TMP3=`mktemp -q -p $TEMPDIR` || die "Cannot create temporary file." # Translate name of the language into an index into language array typeset -i lang ((lang = ${#languages[*]} - 1)) while [ "${languages[$lang]}" != "$language" -a $lang -gt 0 ]; do ((lang = $lang - 1)) done # Create the directories for the thumbnails and the reduced JPEGs [[ -d $thdir ]] || mkdir $thdir [[ -d $smdir ]] || mkdir $smdir # Write the header of the HTML file. output_header "$pagetitle" "$preamble" # Sort by series and by date if [ "$group" ]; then set -- $images echo -e "Sorting\c" >&2 for f; do echo -e ".\c" >&2 if rdjpgxmp "$f" >$RDFFILE; then case "$group" in series) echo -e `extract "$dcRelation" $RDFFILE\ | tr -s '\r\n\t' ' '`"\t$f" >>$TMP2;; year) echo -e `extract "$dcDate" $RDFFILE\ | tr -s '\r\n\t' ' '\ | sed -e 's/.*\([0-9][0-9][0-9][0-9]\).*/\1/'`"\t$f" >>$TMP2;; *) die "Bug! Cannot happen!";; esac else echo -e "@@@\t$f" >>$TMP2 fi done # New list of images, sorted by group images=`sort -b -d -f $TMP2 | cut -f2` # Make a menu of groups echo "" echo >&2 fi # Loop over all arguments unset mainpage typeset -i groupcount=1 prevgroup=" " set -- $images while [ $# -gt 0 ]; do prev="$mainpage" # For "prev" link f="$1" # Image to process if [ -z "$2" ]; then unset next; else next=`basename "$2" .jpg`.html; fi mainpage=`basename "$f" .jpg`.html # HTML page for small image shift echo -e "Processing $f \c" >&2 h=`basename "$f" .jpg` # Basename of original image g="$thdir/${h}" # Basename of thumbnail j="${g}.jpg" # Full name of thumbnail smallbase="$smdir/${h}" # Basename of 640x480 version smallname="$smallbase.jpg" # Full name of 640x480 version typeset -i size=`getsize "$f"` echo -e "(${size} KB), \c" >&2 # Check for PhotoRDF unset description title date place series number camera lens film develdate\ creator if rdjpgxmp "$f" >$RDFFILE; then description=`extract "$dcDescription" $RDFFILE` title=`extract "$dcTitle" $RDFFILE` date=`extract "$dcDate" $RDFFILE` place=`extract "$dcCoverage" $RDFFILE` series=`extract "$dcRelation" $RDFFILE` number=`extract "$dcIdentifier" $RDFFILE` creator=`extract "$dcCreator" $RDFFILE` camera=`extract "$tcCamera" $RDFFILE` lens=`extract "$tcLens" $RDFFILE` film=`extract "$tcFilm" $RDFFILE` develdate=`extract "$tcDevelDate" $RDFFILE` fi [[ -z "$description" ]] && description=`basename $f` # Generate small version, unless an up-to-date version already exists # Copy the PhotoRDF if it exists, or add a standard copyright echo -e "small \c" >&2 if [ -z "$title" ]; then cp $TMP $TMP3 else echo -e "http://ns.adobe.com/xap/1.0/\000\c" >$TMP3 cat $RDFFILE >>$TMP3 fi if [[ ! -f "$smallname" || "$f" -nt "$smallname" ]]; then scale $smallwd $smallht <"$f" | wrjpgapp -cfile $TMP3 >"$smallname" fi typeset -i smallsize=`getsize "$smallname"` echo -e "(${smallsize} KB), \c" >&2 # Generate thumbnail unless an up-to-date version already exists echo "thumbnail" >&2 if [[ ! -f "$j" || "$f" -nt "$j" ]]; then crop_and_scale $crop $w1 $h1 $smallname >$j fi fileinfo=`get_dimension <"$j"` thumbwd=`echo $fileinfo | cut -d' ' -f1` thumbht=`echo $fileinfo | cut -d' ' -f2` # Find out if $smallname is indeed smaller than $f. Store the name # and size of the smaller of the two in $mainname and $mainsize, and # compute the name of an HTML file $mainpage # if [ $smallsize -lt $size ]; then mainname="$smallname" mainsize=$smallsize else mainname="$f" mainsize=$size fi # Write an HTML page for the small version, with links to prev, next # and thumbnails and to the large image ( echo "" echo echo "" echo "" # Header echo -e "\c" if [ -z "$title" ]; then echo -e "$description\c"; else echo -e "$title\c"; fi echo "" [[ -z "$prev" ]] || echo "" [[ -z "$next" ]] || echo "" echo "" [[ -z "$title" ]] || echo "" if [ -z "$style" ]; then echo "" else echo "" fi echo # Body echo "" if [ -z "$prev" ]; then echo "" else echo "" fi echo "" if [ -z "$next" ]; then echo "" else echo "" fi if [ ! -z "$title" ]; then echo "" fi echo echo -e "

\c" if [ -z "$title" ]; then echo -e "$descriptionf\c"; else echo -e "$title\c"; fi echo "

" echo echo "

\"${Image[$lang]}\""" echo echo "

$description" echo echo "" [[ -z "$date" ]] || echo "
${Date[$lang]}$date" [[ -z "$place" ]] || echo "
${Place[$lang]}$place" [[ -z "$series" ]] || echo "
${Series[$lang]}$series" [[ -z "$number" ]] || echo "
${Number[$lang]}$number" [[ -z "$creator" ]] || echo "
${Creator[$lang]}$creator" [[ -z "$camera" ]] || echo "
${Camera[$lang]}$camera" [[ -z "$lens" ]] || echo "
${Lens[$lang]}$lens" [[ -z "$film" ]] || echo "
${Film[$lang]}$film" [[ -z "$develdate" ]] || echo "
${DevelDate[$lang]}$develdate" echo "
${Size[$lang]}$size KB" echo "
" ) > "$mainpage" # If images are grouped, insert a group title, if needed case "$group" in series) h="$series";; year) h=`echo \"$date\"|sed -e 's/.*\([0-9][0-9][0-9][0-9]\).*/\1/'`;; *) h="$prevgroup";; esac if [ "$h" != "$prevgroup" ]; then [[ "$prevgroup" == " " ]] || echo "" echo echo "

" echo "

$h

" ((groupcount++)) prevgroup="$h" fi # Output the HTML code for the thumbnail. # Link it to page with the small image echo echo "
" echo "
" echo "

" echo "

" [[ -z "$title" ]] || echo "

$title

" echo "

${size} KB -" # Don't link to the small version if the small version is actually larger if [ $smallsize -lt $size ]; then echo " ${smallsize} KB -" else rm "$smallname" fi # ToDo: if the description (or any other field) is a URL, make a link echo " $description" # Add the number and the date (will only be visible when printed) [[ -z "$number" ]] || echo " ($number)" [[ -z "$date" ]] || echo " $date" [[ -z "$place" ]] || echo " $place" # If the PhotoRDF exists, make a URL that can retrieve it (Jigsaw only) [[ -z "$title" ]] || echo "RDF" echo "

" done [[ "$group" ]] && echo "
" output_footer # Local Variables: # mode: ksh # End: