#! /bin/sh
# This script creates tumbnails, reduced versions of large images, and an
# index.html file pointing to all of it.
GLOBAL_rcsid='$Id: makethumbs.sh,v 1.194 2002/02/12 10:17:54 molenda Exp $'
GLOBAL_rcsrev='$Revision: 1.194 $'
# Design goals are
# (1) exist in a single script that can be mailed around easily, etc.
# (2) generate clean, simple, portable HTML
# (3) no databases required
# (4) portable portable portable
# There are many other programs that compromise some or all of these goals.
# They are real neat, they make great web pages, they organize your life.
# They don't fit in a single ugly Bourne shell script whose only point in
# life is to take pictures off your digital camera and make them basically
# presentable to your friends.
# This script is in the public domain, share and enjoy.
# The latest version is always at http://www.molenda.com/makethumbs/
# Written by Jason Molenda, 1998-09-13; rewritten less lamely 2001-10-26.
## Notes to people reading this script.
##
## Start at main() and trace the function calls from there.
## As much as I like Bourne shell, I should have just done this in
## perl or python. On the down side, whichever of those I pick, I'll
## hear constant whining from about half of my friends. No one likes
## Bourne shell, so it's the safest language choice. And to be honest,
## I sometimes think it's too easy when you have all those fancy high
## level data types, scoping, abstractions, and regular expression at your
## finger tips -- it's a little more fun when you need to work hard to
## make things work cleanly without a lot of help from the language.
## Return values from functions are prefixed with "RETURN_".
## Command line options are prefixed with "ARGV_".
## Defaults are prefixed with "DEFAULT_"
## Settings from the .makethumbsrc are prefixed with "DOTRC_"
## Globals variables are prefixed with "GLOBAL_".
## GLOBAL_ will hold all the settings that we should act on. These came
## either from a DEFAULT_, ARGV_, or DOTRC_ if the user overrode the DEFAULT_.
main ()
{
enable_atexit_trap_handler
find_optional
find_necessary
init_defaults
read_dotrc_file
make_dir_transversible "."
parse_args $*
get_image_list
create_descriptions_file
create_dates_file
analyze_filenames_and_dates
reorder_image_list
create_generated_files
create_index_pages
[ $GLOBAL_create_slideshow -eq 1 ] && create_slideshow
exit 0
}
# DEFAULT_ values are treated as const and are not normally referenced
# by functions in this script. Functions should refer to the GLOBAL_
# version -- it will either be set to the DEFAULT_ or to the ARGV_ value
# if the user overrides it on the cmd line.
init_defaults ()
{
TMPDIR=${TMPDIR-/tmp}
DEFAULT_columns=3
DEFAULT_max_thumb_size=150
DEFAULT_use_two_windows=0
DEFAULT_reduce_big_pics=1
DEFAULT_reduce_trigger_height=768
DEFAULT_reduce_trigger_width=1024
DEFAULT_reduce_height=480
DEFAULT_reduce_width=640
DEFAULT_large_trigger_height=1300
DEFAULT_large_trigger_width=1700
DEFAULT_large_height=1024
DEFAULT_large_width=1280
DEFAULT_create_large_images=1
DEFAULT_remove_originals=0
DEFAULT_rotation_filename="rot-state.txt"
DEFAULT_dates_filename="dates.txt"
DEFAULT_descriptions_filename="descriptions.txt"
DEFAULT_show_progress=1
DEFAULT_show_timings=0
DEFAULT_body_tag="
"
DEFAULT_meta_tag="undef"
DEFAULT_html_charset="undef"
DEFAULT_index_base_name="index"
DEFAULT_html_file_suffix="html"
DEFAULT_index_filename="${DEFAULT_index_base_name}.$DEFAULT_html_file_suffix"
DEFAULT_print_captions=1
DEFAULT_print_img_size_on_index=0
DEFAULT_print_title_on_index=1
DEFAULT_compact_index_page=0
DEFAULT_compression_level="75"
DEFAULT_image_imprinting_text="undef"
DEFAULT_boilerplate_footer="undef"
DEFAULT_boilerplate_index_head_stuff="undef"
DEFAULT_boilerplate_index_before_title="undef"
DEFAULT_boilerplate_index_after_title="undef"
DEFAULT_boilerplate_index_end_of_page="undef"
DEFAULT_single_index_page=0
DEFAULT_rows_per_index_page=10
DEFAULT_usa_specific_date_format_checks=1
DEFAULT_heuristic_filenames_are_digicam_boring=0
DEFAULT_heuristic_days_are_identical=0
DEFAULT_heuristic_times_are_absent=0
DEFAULT_heuristic_filename_pattern=undef
DEFAULT_total_image_count=0
DEFAULT_link_to_original_img_on_index=0
DEFAULT_show_image_info=0
DEFAULT_dont_change_file_permissions=0
DEFAULT_file_readable_permissions="a+r,a-x"
DEFAULT_dir_transversible_permissions="a+x"
DEFAULT_create_slideshow=1
DEFAULT_print_img_size_on_slideshow=1
DEFAULT_slideshow_img_size_across_two_lines=1
DEFAULT_slideshow_images_are_clickable=0
DEFAULT_slideshow_print_javascript_navigation=1
DEFAULT_slideshow_previous_pre_link="["
DEFAULT_slideshow_previous="previous"
DEFAULT_slideshow_previous_post_link="]
"
DEFAULT_slideshow_next_pre_link="["
DEFAULT_slideshow_next="next"
DEFAULT_slideshow_next_post_link="]
"
DEFAULT_slideshow_ret_to_index_pre_link="["
DEFAULT_slideshow_ret_to_index="index"
DEFAULT_slideshow_ret_to_index_post_link="]
"
DEFAULT_monthname_01="January"
DEFAULT_monthname_02="February"
DEFAULT_monthname_03="March"
DEFAULT_monthname_04="April"
DEFAULT_monthname_05="May"
DEFAULT_monthname_06="June"
DEFAULT_monthname_07="July"
DEFAULT_monthname_08="August"
DEFAULT_monthname_09="September"
DEFAULT_monthname_10="October"
DEFAULT_monthname_11="November"
DEFAULT_monthname_12="December"
GLOBAL_columns=$DEFAULT_columns
GLOBAL_max_thumb_size=$DEFAULT_max_thumb_size
GLOBAL_use_two_windows=$DEFAULT_use_two_windows
GLOBAL_reduce_big_pics=$DEFAULT_reduce_big_pics
GLOBAL_reduce_trigger_height=$DEFAULT_reduce_trigger_height
GLOBAL_reduce_trigger_width=$DEFAULT_reduce_trigger_width
GLOBAL_reduce_height=$DEFAULT_reduce_height
GLOBAL_reduce_width=$DEFAULT_reduce_width
GLOBAL_create_large_images=$DEFAULT_create_large_images
GLOBAL_large_trigger_height=$DEFAULT_large_trigger_height
GLOBAL_large_trigger_width=$DEFAULT_large_trigger_width
GLOBAL_large_height=$DEFAULT_large_height
GLOBAL_large_width=$DEFAULT_large_width
GLOBAL_rotation_filename=$DEFAULT_rotation_filename
GLOBAL_dates_filename=$DEFAULT_dates_filename
GLOBAL_descriptions_filename=$DEFAULT_descriptions_filename
GLOBAL_show_progress=$DEFAULT_show_progress
GLOBAL_show_timings=$DEFAULT_show_timings
GLOBAL_remove_originals=$DEFAULT_remove_originals
GLOBAL_body_tag=$DEFAULT_body_tag
GLOBAL_meta_tag=$DEFAULT_meta_tag
GLOBAL_html_charset=$DEFAULT_html_charset
GLOBAL_index_filename=$DEFAULT_index_filename
GLOBAL_index_base_name=$DEFAULT_index_base_name
GLOBAL_html_file_suffix=$DEFAULT_html_file_suffix
GLOBAL_print_captions=$DEFAULT_print_captions
GLOBAL_print_img_size_on_index=$DEFAULT_print_img_size_on_index
GLOBAL_print_title_on_index=$DEFAULT_print_title_on_index
GLOBAL_compact_index_page=$DEFAULT_compact_index_page
GLOBAL_compression_level=$DEFAULT_compression_level
GLOBAL_image_imprinting_text=$DEFAULT_image_imprinting_text
GLOBAL_boilerplate_footer=$DEFAULT_boilerplate_footer
GLOBAL_boilerplate_index_head_stuff=$DEFAULT_boilerplate_index_head_stuff
GLOBAL_boilerplate_index_before_title=$DEFAULT_boilerplate_index_before_title
GLOBAL_boilerplate_index_after_title=$DEFAULT_boilerplate_index_after_title
GLOBAL_boilerplate_index_end_of_page=$DEFAULT_boilerplate_index_end_of_page
GLOBAL_single_index_page=$DEFAULT_single_index_page
GLOBAL_rows_per_index_page=$DEFAULT_rows_per_index_page
GLOBAL_usa_specific_date_format_checks=$DEFAULT_usa_specific_date_format_checks
GLOBAL_total_image_count=$DEFAULT_total_image_count
GLOBAL_heuristic_filenames_are_digicam_boring=$DEFAULT_heuristic_filenames_are_digicam_boring
GLOBAL_heuristic_days_are_identical=$DEFAULT_heuristic_days_are_identical
GLOBAL_heuristic_times_are_absent=$DEFAULT_heuristic_times_are_absent
GLOBAL_heuristic_filename_pattern=$GLOBAL_heuristic_filename_pattern
GLOBAL_link_to_original_img_on_index=$DEFAULT_link_to_original_img_on_index
GLOBAL_show_image_info=$DEFAULT_show_image_info
GLOBAL_dont_change_file_permissions=$DEFAULT_dont_change_file_permissions
GLOBAL_file_readable_permissions=$DEFAULT_file_readable_permissions
GLOBAL_dir_transversible_permissions=$DEFAULT_dir_transversible_permissions
GLOBAL_create_slideshow=$DEFAULT_create_slideshow
GLOBAL_print_img_size_on_slideshow=$DEFAULT_print_img_size_on_slideshow
GLOBAL_slideshow_img_size_across_two_lines=$DEFAULT_slideshow_img_size_across_two_lines
GLOBAL_slideshow_images_are_clickable=$DEFAULT_slideshow_images_are_clickable
GLOBAL_slideshow_print_javascript_navigation=$DEFAULT_slideshow_print_javascript_navigation
GLOBAL_slideshow_previous_pre_link=$DEFAULT_slideshow_previous_pre_link
GLOBAL_slideshow_previous=$DEFAULT_slideshow_previous
GLOBAL_slideshow_previous_post_link=$DEFAULT_slideshow_previous_post_link
GLOBAL_slideshow_next_pre_link=$DEFAULT_slideshow_next_pre_link
GLOBAL_slideshow_next=$DEFAULT_slideshow_next
GLOBAL_slideshow_next_post_link=$DEFAULT_slideshow_next_post_link
GLOBAL_slideshow_ret_to_index_pre_link=$DEFAULT_slideshow_ret_to_index_pre_link
GLOBAL_slideshow_ret_to_index=$DEFAULT_slideshow_ret_to_index
GLOBAL_slideshow_ret_to_index_post_link=$DEFAULT_slideshow_ret_to_index_post_link
GLOBAL_monthname_01=$DEFAULT_monthname_01
GLOBAL_monthname_02=$DEFAULT_monthname_02
GLOBAL_monthname_03=$DEFAULT_monthname_03
GLOBAL_monthname_04=$DEFAULT_monthname_04
GLOBAL_monthname_05=$DEFAULT_monthname_05
GLOBAL_monthname_06=$DEFAULT_monthname_06
GLOBAL_monthname_07=$DEFAULT_monthname_07
GLOBAL_monthname_08=$DEFAULT_monthname_08
GLOBAL_monthname_09=$DEFAULT_monthname_09
GLOBAL_monthname_10=$DEFAULT_monthname_10
GLOBAL_monthname_11=$DEFAULT_monthname_11
GLOBAL_monthname_12=$DEFAULT_monthname_12
GLOBAL_descriptions_file_validated=0
GLOBAL_descriptions_file_is_invalid=0
GLOBAL_already_failed_guessing_date_from_dir=0
GLOBAL_makethumbs_version=`echo "$GLOBAL_rcsrev" | sed 's,[^0-9.],,g'`
GLOBAL_rcsid=`echo "$GLOBAL_rcsid" | sed -e 's,\$Id: ,,' -e 's,molenda Exp.*,,'`
}
parse_args ()
{
local optname optarg
while [ $# -gt 0 ]
do
optname="`echo $1 | sed 's,=.*,,'`"
optarg="`echo $1 | sed 's,^[^=]*=,,'`"
case "$1" in
--maxthumbsize=* | --max-thumb-size=*)
optarg=`echo $optarg | sed 's,[^0-9],,g'`
exit_if_empty "$optname" "$optarg"
ARGV_max_thumb_size=$optarg
GLOBAL_max_thumb_size=$ARGV_max_thumb_size
;;
--columns=* | --cols=*)
optarg=`echo $optarg | sed 's,[^0-9],,g'`
exit_if_empty "$optname" "$optarg"
ARGV_columns=$optarg
GLOBAL_columns=$optarg
;;
--one-index-page* | --one-index*)
ARGV_single_index_page=1
GLOBAL_single_index_page=$ARGV_single_index_page
;;
--use-two-windows*|--enable-two-windows|--with-two-windows)
ARGV_use_two_windows=1
GLOBAL_use_two_windows=$ARGV_use_two_windows
;;
--remove-orig*)
ARGV_remove_originals=1
GLOBAL_remove_originals=$ARGV_remove_originals
;;
--progress)
ARGV_show_progress=1
GLOBAL_show_progress=$ARGV_show_progress
;;
--quiet | -q)
ARGV_show_progress=0
GLOBAL_show_progress=$ARGV_show_progress
;;
--disable-reduce|--without-reduce)
ARGV_reduce_big_pics=0
GLOBAL_reduce_big_pics=$ARGV_reduce_big_pics
;;
--disable-slideshow|--without-slideshow)
ARGV_create_slideshow=0
GLOBAL_create_slideshow=$ARGV_create_slideshow
;;
--enable-reduce|--with-reduce)
ARGV_reduce_big_pics=1
GLOBAL_reduce_big_pics=$ARGV_reduce_big_pics
;;
--compact-index|--compact)
ARGV_compact_index_page=1
GLOBAL_compact_index_page=$ARGV_compact_index_page
;;
--reduce-height=*)
optarg=`echo $optarg | sed 's,[^0-9],,g'`
exit_if_empty "$optname" "$optarg"
ARGV_reduce_height=$optarg
GLOBAL_reduce_height=$ARGV_reduce_height
;;
--reduce-width=*)
optarg=`echo $optarg | sed 's,[^0-9],,g'`
exit_if_empty "$optname" "$optarg"
ARGV_reduce_width=$optarg
GLOBAL_reduce_width=$ARGV_reduce_width
;;
--reduce-trigger-height=*)
optarg=`echo $optarg | sed 's,[^0-9],,g'`
exit_if_empty "$optname" "$optarg"
ARGV_reduce_trigger_height=$optarg
GLOBAL_reduce_trigger_height=$ARGV_reduce_trigger_height
;;
--reduce-trigger-width=*)
optarg=`echo $optarg | sed 's,[^0-9],,g'`
exit_if_empty "$optname" "$optarg"
ARGV_reduce_trigger_width=$optarg
GLOBAL_reduce_trigger_width=$ARGV_reduce_trigger_width
;;
--compression-level=*|--compression=*)
optarg=`echo $optarg | sed 's,[^0-9],,g'`
exit_if_empty "$optname" "$optarg"
ARGV_compression_level=$optarg
GLOBAL_compression_level=$ARGV_compression_level
;;
--clean | --cleanup)
do_cleanup
exit 0
;;
-h | --help | -v | --version | -V)
help
exit 1
;;
-*)
echo "`basename $0`: ERROR: Unrecognized option \"$1\"" >&2
;;
*)
ARGV_image_list="$ARGV_image_list $1"
;;
esac
shift
done
if [ -n "$ARGV_compact_index_page" ]
then
enable_compact_index_mode
fi
}
help ()
{
# The following exec goop so I don't have to manually redirect every
# message to stderr in this function.
exec 4>&1 # save stdout fd to fd #4
exec 1>&2 # redirect stdout to stderr
cat <<__EOM__
Usage: `basename $0` [options]
--compact-index Create a compact index page to pack in lots of thumbnails
--maxthumbsize=n Maximum size of thumbnails, in pixels, default $DEFAULT_max_thumb_size
--columns=n Number of thumbnails per line, default $DEFAULT_columns
--disable-reduce Don't create a reduced image if the picture is large
--disable-slideshow Don't create slideshow files
--clean Remove all makethumbs-generated files
--compression=n Set JPEG compression percentage to n for generated images.
Default is 75. Things usually look OK down to the 40-50's.
--one-index-page Only create a single index page. Default is to put 10 rows
on each index page, creating as many pages as necessary.
--use-two-windows Bring up a new window to see images, default is `[ $DEFAULT_use_two_windows -eq 1 ] && echo enabled || echo disabled`
__EOM__
if [ $DEFAULT_show_progress -eq 1 ]
then
echo '--quiet Avoid unnecessary output while running'
else
echo '--progress Show progress updates as the script runs'
fi
cat <<__EOM__
--remove-originals Remove original images if we make reduced versions.
Useful when disk space is limited; default is `[ $DEFAULT_remove_originals -eq 1 ] && echo enabled || echo disabled`
WARNING!!! This option *will* remove your original images
if reduced images are available!
Run this script in a directory of JPEG files to create thumbnail images and
HTML pages. Makethumbs will not overwrite any files you've created by hand.
Makethumbs will not modify your original images. Makethumbs will not
corrupt your precious bodily fluids.
You can permanently override options by creating a ~/.makethumbsrc file.
Many more features can be tweaked via the .makethumbsrc file. See the
documentation on the makethumbs home page for more information. You should
not need to modify makethumbs or the HTML it generates.
This script written by Jason Molenda, makethumbs(AT)molenda.com.
This is version ${GLOBAL_makethumbs_version}.
The latest version of this script is always available at
http://www.molenda.com/makethumbs/
__EOM__
exec 1>&4 # Copy stdout fd back from temporary save fd, #4
}
# RETURN_found is 1 if found, 0 if not found. If found, $RETURN_fullname
# contains the path + filename.
find_in_path ()
{
local OFS i target dir
target="$*"
RETURN_fullname=""
RETURN_found=0
OFS="$IFS"
IFS=:
for i in $PATH
do
[ -z "$i" ] && i="."
if [ -f "$i/$target" ]
then
RETURN_fullname="$i/$target"
RETURN_found=1
break
fi
done
IFS="$OFS"
}
# Compact Index Mode is a special case because the setting of this
# one mode involves setting several other variables, unless the
# user has explicitly overridden them elsewhere.
enable_compact_index_mode ()
{
[ $GLOBAL_compact_index_page -eq 0 ] && return
if [ -z "$ARGV_max_thumb_size" -a -z "$DOTRC_max_thumb_size" ]
then
GLOBAL_max_thumb_size=75
fi
if [ -z "$ARGV_print_captions" -a -z "$DOTRC_print_captions" ]
then
GLOBAL_print_captions=0
fi
if [ -z "$ARGV_columns" -a -z "$DOTRC_columns" ]
then
GLOBAL_columns=6
fi
}
# Parse a user's $HOME/.makethumbsrc. The code here is kind of
# funky because I didn't want to just bourne-shell source the file
# (". $HOME/.makethumbsrc"); any syntax error in that startup file
# would have caused makethumbs to fail in weird ways and users could have
# trouble debugging it. It's a huge amount of work to get all the parsing
# correct so spaces, quote marks, apostrophies, etc., are all carried over
# accurately. The sed expression where $value gets set is not something
# I'm too proud of - this is always the sort of thing that is tricky in
# Bourne shell.
read_dotrc_file ()
{
local this_dotrc tmpf varname varname_is_valid line value curval
for this_dotrc in $HOME/.makethumbsrc $HOME/.makethumbs $HOME/makethumbsrc \
../../.makethumbsrc ../../.makethumbs ../../makethumbsrc \
../.makethumbsrc ../.makethumbs ../makethumbsrc \
.makethumbsrc .makethumbs makethumbsrc
do
[ ! -f "$this_dotrc" ] && continue
make_tmpfile dotrc
tmpf=$RETURN_tmpfile
cat "$this_dotrc" | grep -v '^[ ]*#' | grep = > $tmpf
[ ! -s $tmpf ] && continue
while read line
do
varname_is_valid=0
varname=`echo "$line" | sed -e 's,=.*,,' -e 's,[^A-Za-z_0-9],,g' \
-e 's,^ARGV_,,' -e 's,^GLOBAL_,,' \
-e 's,^DEFAULT_,,' -e 's,^DOTRC_,,'`
# Eliminate whitespace, quotes around the value
value=`echo "$line" | sed -e 's,^[^=]*=,,' -e 's,^[ ]*,,' \
-e 's,[ ]*$,,' \
-e s,^\[\"\'\]\[\ \ \]\*,, \
-e s,\[\ \ \]\*\[\"\'\]\$,,`
if echo "$varname" | grep -i '_FILE$' >/dev/null 2>&1
then
read_in_file_contents "$value"
if [ $RETURN_file_found -eq 1 ]
then
value=`echo "$RETURN_file_contents" | grep -v '^[ ]*$'`
else
echo WARNING: Unable to read in file "$value" for variable "$varname" 2>&1
continue
fi
varname=`echo "$varname" | sed 's,_[Ff][Ii][Ll][Ee]$,,'`
fi
eval [ -n \"\$GLOBAL_$varname\" ] && varname_is_valid=1
if [ $varname_is_valid -eq 0 ]
then
echo ERROR: "$this_dotrc" has unrecognized variable name, \"$varname\"!>&2
continue
fi
# Try to do a little verification if the current value is numeric. I could
# probably add some extra checks if the current val is 0 or 1, making an
# assumption that it's a boolean value. (someone might try to use "yes"
# instead of '1', for instance)
curval=`eval echo \\$GLOBAL_$varname`
if echo "$curval" | grep '^[0-9]*$' >/dev/null 2>&1
then
if [ -z "$value" ]
then
echo WARNING: Variable $varname currently has a numeric value of $curval >&2
echo WARNING: but you\'re setting it to an empty value. >&2
else
if echo "$value" | grep '^[0-9]*$' >/dev/null 2>&1
then
:
else
echo WARNING: Variable $varname currently has a numeric value of $curval >&2
echo WARNING: but you\'re setting it to \"$value\". >&2
fi
fi
fi
eval DOTRC_$varname='$value'
eval GLOBAL_$varname=\$DOTRC_$varname
done < $tmpf
done
# If a user sets some variables, others should be set as well.
if [ -n "$DOTRC_compact_index_page" ]
then
enable_compact_index_mode
fi
}
# A variable might be a filename instead of a value. This function
# checks to see if such a file exists and returns the fully qualified
# pathname if it does.
read_in_file_contents ()
{
local fn i
RETURN_file_found=0
RETURN_file_contents=""
fn="$*"
# Try to expand these via eval
if echo "$fn" | egrep '^(~|[$]HOME)' >/dev/null 2>&1
then
fn=`eval echo "$fn"`
fi
# Not all Bourne shells will expand tilde.
if echo "$fn" | egrep '^~/' >/dev/null 2>&1
then
fn=`echo "$fn" | sed 's,~/,,'`
fi
if [ -f "$fn" ]
then
RETURN_file_found=1
RETURN_file_contents=`cat "$fn"`
return
fi
for i in . $HOME ..
do
if [ -f "$i/$fn" ]
then
RETURN_file_found=1
RETURN_file_contents=`cat "$i/$fn"`
return
fi
done
}
# Returns a temp file in $RETURN_tmpfile.
# Takes an optional description name argument.
make_tmpfile ()
{
local base_tmpfile n
if [ $GLOBAL_mktemp_is_present -eq 1 ]
then
RETURN_tmpfile=`mktemp -q "$TMPDIR/makethumbs-$1.XXXXXXX"`
if [ $? -eq 0 ]
then
make_file_owner_read_writable "$RETURN_tmpfile"
add_cleanup "$RETURN_tmpfile"
return 0
fi
fi
base_tmpfile="$TMPDIR/makethumbs-$1.$$"
RETURN_tmpfile="$base_tmpfile"
n=0
while [ -f "$RETURN_tmpfile" ]
do
n=`expr $n + 1`
RETURN_tmpfile="${base_tmpfile}-$n"
done
make_file_owner_read_writable "$RETURN_tmpfile"
add_cleanup "$RETURN_tmpfile"
return 0
}
# Ends program execution if a necessary program is missing.
find_necessary ()
{
local missed_something progname
missed_something=0
# For now, pull these two checks because we can usually get by without them
# and older netpbm's don't have them.
# $GLOBAL_tifftopnm_is_present -eq 1 -a \
# $GLOBAL_pngtopnm_is_present -eq 1 -a \
if [ $GLOBAL_pnmfile_is_present -eq 1 -a \
$GLOBAL_giftopnm_is_present -eq 1 -a \
$GLOBAL_pnmscale_is_present -eq 1 -a \
$GLOBAL_pnmrotate_is_present -eq 1 ]
then
GLOBAL_netpbm_is_available=1
else
GLOBAL_netpbm_is_available=0
fi
if [ $GLOBAL_mogrify_is_present -eq 1 -a \
$GLOBAL_convert_is_present -eq 1 -a \
$GLOBAL_identify_is_present -eq 1 ]
then
GLOBAL_imagemagick_is_available=1
else
GLOBAL_imagemagick_is_available=0
fi
if [ $GLOBAL_cjpeg_is_present -eq 1 -a \
$GLOBAL_djpeg_is_present -eq 1 ]
then
GLOBAL_jpegsrc_is_available=1
else
GLOBAL_jpegsrc_is_available=0
fi
if [ $GLOBAL_imagemagick_is_available -eq 0 ]
then
if [ $GLOBAL_jpegsrc_is_available -eq 0 ]
then
echo ERROR: You may be able to find a copy of this at ftp://ftp.uu.net/graphics/jpeg >&2
missed_something=1
fi
if [ $GLOBAL_netpbm_is_available -eq 0 ]
then
echo ERROR: You need to install the \"netpbm\" utilities. >&2
echo ERROR: You can find this at http://netpbm.sourceforge.net/ >&2
missed_something=1
fi
fi
if [ $missed_something -eq 1 ]
then
echo "" >&2
echo ERROR: You will find all the necessary utilities pre-installed >&2
echo ERROR: on most Linux systems. >&2
exit 1
fi
}
# Detect some optional helper programs and remember their presence.
find_optional ()
{
local prog varname
for prog in metacam jhead dphotox dump-exif \
mktemp \
cjpeg djpeg rdjpgcom \
pnmfile giftopnm tifftopnm pngtopnm pnmscale pnmrotate jpegtopnm \
mogrify identify convert
do
varname=`echo $prog | tr -d '-'`
find_in_path $prog
if [ $RETURN_found -eq 1 ]
then
eval GLOBAL_${varname}_is_present=1
else
eval GLOBAL_${varname}_is_present=0
fi
done
}
enable_atexit_trap_handler ()
{
trap "atexit 0" 0
trap "atexit 1" 1
trap "atexit 2" 2
trap "atexit 15" 15
}
add_cleanup ()
{
GLOBAL_cleanuplist="$GLOBAL_cleanuplist $*"
}
remove_cleanup ()
{
local fn
fn="$*"
GLOBAL_cleanuplist=`echo $GLOBAL_cleanuplist | sed "s|${fn}||"`
}
atexit ()
{
trap "" 0 1 2 15
rm -f $GLOBAL_cleanuplist
[ -n "$1" ] && exit $1
exit 1
}
# Unnecessary paranoia - makethumbs can successfully operate even
# if you have a umask of 777 thanks to this function. What the heck.
make_file_owner_read_writable ()
{
[ -f "$*" ] && chmod u+rw "$*"
}
# Only accepts *one* argument, which may contain space chars.
make_file_world_readable ()
{
make_file_owner_read_writable "$*"
[ $GLOBAL_dont_change_file_permissions -eq 1 ] && return
if [ -f "$*" -a -n "$GLOBAL_file_readable_permissions" ]
then
chmod "$GLOBAL_file_readable_permissions" "$*"
fi
}
# Only accepts *one* argument, which may contain space chars.
make_dir_transversible ()
{
[ $GLOBAL_dont_change_file_permissions -eq 1 ] && return
if [ -d "$*" -a -n "$GLOBAL_dir_transversible_permissions" ]
then
chmod "$GLOBAL_dir_transversible_permissions" "$*"
fi
}
exit_if_empty ()
{
local desc val
desc="$1"
shift
val="$*"
if [ -z "$val" ]
then
echo ERROR: No argument given with \"$desc\" command line argument! >&2
exit 1
fi
}
do_cleanup ()
{
local fn indexes
get_image_list
move_to_backup_file "$GLOBAL_descriptions_filename"
move_to_backup_file "$GLOBAL_dates_filename"
indexes=`ls ${GLOBAL_index_base_name}.${GLOBAL_html_file_suffix} \
${GLOBAL_index_base_name}-all.${GLOBAL_html_file_suffix} \
${GLOBAL_index_base_name}-[0-9].${GLOBAL_html_file_suffix} \
${GLOBAL_index_base_name}-[0-9][0-9].${GLOBAL_html_file_suffix} \
${GLOBAL_index_base_name}-[0-9][0-9][0-9].${GLOBAL_html_file_suffix} \
2>/dev/null`
if [ -n "$indexes" ]
then
for fn in $indexes
do
remove_or_move_file_aside "$fn"
done
fi
remove_existing_slideshow_html_files
while read fn
do
source_name_to_large_name "$fn"
[ "$fn" != "$RETURN_large_name" ] && rm -f "$RETURN_large_name"
source_name_to_reduced_name "$fn"
[ "$fn" != "$RETURN_reduced_name" ] && rm -f "$RETURN_reduced_name"
source_name_to_thumb_name "$fn"
[ "$fn" != "$RETURN_thumb_name" ] && rm -f "$RETURN_thumb_name"
done < $GLOBAL_image_list_tmpfile
}
remove_or_move_file_aside ()
{
local fn
fn="$*"
[ ! -f "$fn" ] && return
remove_file_if_unmodified "$fn"
[ ! -f "$fn" ] && return
move_to_backup_file "$fn"
}
move_to_backup_file ()
{
local fn i most_recent_backup
fn="$*"
[ ! -f "${fn}" ] && return
if [ ! -f "${fn}~" ]
then
mv "$fn" "${fn}~"
return
fi
most_recent_backup=`ls -1t "${fn}~" ${fn}~* 2>/dev/null | head -1`
if cmp "${fn}" "$most_recent_backup" >/dev/null 2>&1
then
rm -f "${fn}"
touch "$most_recent_backup"
return
fi
i=1
while [ -f "${fn}~${i}~" -a $i -le 50 ]
do
i=`expr $i + 1`
done
if [ ! -f "${fn}~${i}~" ]
then
mv "$fn" "${fn}~${i}~"
return
fi
}
#########################################################
#### Start of real makethumbs image stuff functions
#########################################################
# Sets file at $GLOBAL_image_list_tmpfile with images to process.
# Tries to normalize filename extensions.
get_image_list ()
{
local prelim_image_tmpfile i normalized_filename filename
make_tmpfile first-image-list
prelim_image_tmpfile="$RETURN_tmpfile"
make_tmpfile image-list
GLOBAL_image_list_tmpfile="$RETURN_tmpfile"
if [ -n "$ARGV_image_list" ]
then
for i in $ARGV_image_list
do
echo $ARGV_image_list >> $prelim_image_tmpfile
done
else
ls -1 | egrep -i '\.jpg$|\.jpeg$|\.png$|\.gif$' > $prelim_image_tmpfile
fi
cat $prelim_image_tmpfile | while read filename
do
[ -s "$filename" ] || continue
if echo "$filename" | egrep -- '-[trl].[jpgpnggif]{3}$' >/dev/null 2>&1
then
continue
fi
normalized_filename=`echo "$filename" |
sed -e 's,.JPG$,.jpg,' -e 's,.jpeg$,.jpg,' -e 's,.JPEG$,.jpg,' \
-e 's,.PNG$,.png,' -e 's,.GIF$,.gif,'`
if [ ! -f "$normalized_filename" -a -n "$normalized_filename" ]
then
if mv "$filename" "$normalized_filename"
then
filename="$normalized_filename"
fi
fi
#FIXME: This will probably fail on a MacOS HFS+ type system where testing
# for "foo.JPG" and "foo.jpg" may both return true if one of the names
# is present... Maybe check inode #s or something to be sure.
if [ "$filename" != "$normalized_filename" -a \
-f "$filename" -a -f "$normalized_filename" ]
then
echo "WARNING: Both $filename and $normalized_filename exist, and this script does" 1>&2
echo " odd things when this happens!" 1>&2
fi
make_file_world_readable "$filename"
echo "$filename" >> $GLOBAL_image_list_tmpfile
done
if [ ! -s "$GLOBAL_image_list_tmpfile" ]
then
echo ERROR: No images found! >&2
exit 1
fi
}
# Use the order of filenames in the descriptions.txt [captions] section
# to determine the order that they'll be presented on the web page.
reorder_image_list ()
{
local newlist fn newsize oldsize
get_caption_filenames_from_descriptions_file
[ -z "$RETURN_captions_tmpfile" ] && return
[ ! -s "$RETURN_captions_tmpfile" ] && return
make_tmpfile newlist
newlist="$RETURN_tmpfile"
while read fn
do
quote_egrep_chars "$fn"
if egrep "^${RETURN_egrep}\$" $newlist >/dev/null 2>&1
then
continue
fi
if egrep "^${RETURN_egrep}\$" $GLOBAL_image_list_tmpfile >/dev/null 2>&1
then
echo "$fn" >> $newlist
fi
done < $RETURN_captions_tmpfile
while read fn
do
quote_egrep_chars "$fn"
if egrep "^${RETURN_egrep}\$" $newlist >/dev/null 2>&1
then
:
else
echo "$fn" >> $newlist
fi
done < $GLOBAL_image_list_tmpfile
newsize=`ls -l $newlist | awk '{print $5}'`
oldsize=`ls -l $GLOBAL_image_list_tmpfile | awk '{print $5}'`
# I don't know... is there a case where the new one could be smaller?
# Maybe a duplicate could be in the original list, and that'd be eliminated
# by the reordering. I'll skip the obvious check for now.
if [ -n "$newsize" -a -n "$oldsize" -a $newsize -gt 0 ]
then
cat $newlist > $GLOBAL_image_list_tmpfile
fi
}
iterate_over_image_list ()
{
local col first_row fn filelist indexno
indexno="$1"
col=0
first_row=1
GLOBAL_last_row_was_closed=0
make_tmpfile thislist-$indexno
filelist="$RETURN_tmpfile"
if [ "$indexno" = "allinone" ]
then
cat $GLOBAL_image_list_tmpfile > $filelist
else
grep "^$indexno " $GLOBAL_image_indexpages | sed 's,^[0-9]* ,,' > $filelist
fi
while read fn
do
if [ $col -eq 0 ]
then
print_html_row_start
GLOBAL_last_row_was_closed=0
fi
print_html_column_start
print_image_entry "$fn"
print_html_column_end
col=`expr $col + 1`
if [ $col -eq $GLOBAL_columns ]
then
print_html_row_end
col=0
GLOBAL_last_row_was_closed=1
fi
done < $filelist
}
print_image_entry ()
{
local fn thumb_width thumb_height was_reduced
fn="$*"
source_name_to_thumb_name "$fn"
get_dimensions "$RETURN_thumb_name"
thumb_width=$RETURN_width
thumb_height=$RETURN_height
reduced_file_exists "$fn"
was_reduced=$RETURN_reduced_exists
print_image_link $thumb_width $thumb_height $was_reduced "$fn"
print_image_size "$fn"
}
# Only remove JPG images. Removing GIF/PNG images is a little tricky -
# see the RCS comment on rev 1.60 for more details on why this is tricky.
# FIXME: This function is incorrect given 'large' images - they should
# become the plain files if they exist, not the reduced ones.
maybe_remove_original ()
{
local name reduced_name large_name old_name
name="$*"
RETURN_original_removed=0
[ $GLOBAL_remove_originals -eq 0 ] && return
[ ! -f "$name" ] && return
if echo "$name" | grep -v '\.jpg$' > /dev/null 2>&1
then
return
fi
source_name_to_reduced_name "$name"
reduced_name="$RETURN_reduced_name"
source_name_to_large_name "$name"
large_name="$RETURN_large_name"
if [ -f "$large_name" -a -s "$large_name" ]
then
mv "$name" "${name}.bak"
mv "$large_name" "$name"
old_name="$large_name"
elif [ -f "$reduced_name" -a -s "$reduced_name" ]
then
mv "$name" "${name}.bak"
mv "$reduced_name" "$name"
old_name="$reduced_name"
fi
if [ ! -f "$old_name" -a -f "$name" -a -s "$name" ]
then
rm -f "${name}.bak"
RETURN_original_removed=1
else
echo ERROR: I got confused while trying to remove original file >&2
echo ERROR: \"$name\"! Aborting... >&2
exit 1
fi
}
# A little complicated - parameters are
# THUMBNAIL-WIDTH THUMBNAIL-HEIGHT REDUCED-IMG-MADE? FILENAME
# $thumb_width $thumb_height $was_reduced "$fn"
print_image_link ()
{
local twidth theight reduced fn caption thumb_name
local slideshow_name reduced_slideshow_name
local image_name reduced_name main_link_href secondary_link_href
twidth=$1; shift
theight=$1; shift
reduced=$1; shift
fn="$*"
get_image_caption_for_main_index "$fn"
caption="$RETURN_caption"
source_name_to_thumb_name "$fn"
thumb_name="$RETURN_thumb_name"
if [ $GLOBAL_create_slideshow -eq 1 ]
then
image_name_to_html_name "$fn"
slideshow_name="$RETURN_html_name"
source_name_to_reduced_html_name "$fn"
reduced_slideshow_name="$RETURN_reduced_html_name"
fi
image_name="$fn"
source_name_to_reduced_name "$image_name"
reduced_name="$RETURN_reduced_name"
# The logic ahead is complicated. We change our behavior depending
# on whether (a) this image has a reduced version ($reduced), whether
# (b) we are making slideshows ($GLOBAL_create_slideshow), and whether
# (c) there are any reduced images present.
# One odd case is if we are making a slideshow, and we are making reduced
# versions of images, but _this_ particular image didn't have a reduced
# version. In this one case, the _main_ link we emit is to the reduced
# HTML slideshow page. That way when people do Next/Previous, they'll
# proceed to the Reduced version (the one they most likely want).
if [ $reduced -eq 1 ]
then
if [ $GLOBAL_create_slideshow -eq 1 ]
then
main_link_href="$reduced_slideshow_name"
secondary_link_href="$slideshow_name"
else
main_link_href="$reduced_name"
secondary_link_href="$image_name"
fi
else
if [ $GLOBAL_create_slideshow -eq 1 ]
then
if [ $GLOBAL_reduce_big_pics -eq 1 -a \
$GLOBAL_there_is_at_least_one_reduced_img -eq 1 ]
then
main_link_href="$reduced_slideshow_name"
else
main_link_href="$slideshow_name"
fi
else
main_link_href="$image_name"
fi
fi
echo -n '
"
if [ $GLOBAL_print_captions -eq 1 ]
then
echo -n "
$caption"
if [ $reduced -eq 1 -a \
$GLOBAL_create_slideshow -eq 1 -a \
$GLOBAL_link_to_original_img_on_index -eq 1 ]
then
quote_url_chars "$secondary_link_href"
echo -n "
[Original img]"
fi
fi
echo ""
}
print_image_size ()
{
if [ $GLOBAL_print_captions -eq 1 -a \
$GLOBAL_print_img_size_on_index -eq 1 ]
then
return_image_size "$*"
echo " (${RETURN_image_size_str})"
fi
}
return_image_size ()
{
local bytes kbytes fn
RETURN_image_size_str=""
fn="$*"
bytes=`ls -l "$fn" | awk '{print $5}'`
kbytes=`expr $bytes / 1000`
RETURN_image_size_str="${kbytes}k"
}
foo_to_pnm ()
{
case "$*" in
*.jpg)
RETURN_foo_to_pnm="djpeg -ppm";;
*.gif)
RETURN_foo_to_pnm="giftopnm";;
*.tif)
RETURN_foo_to_pnm="tifftopnm";;
*.png)
RETURN_foo_to_pnm="pngtopnm";;
*)
echo ERROR: Unable to proceed with file "$*"! >&2
exit 1;;
esac
}
#########################################################
#### Index pages functions
#########################################################
create_index_pages ()
{
local t index_pages thumbnails_per_page
if [ $GLOBAL_single_index_page -eq 1 ]
then
thumbnails_per_page="$GLOBAL_total_image_count"
else
thumbnails_per_page=`expr $GLOBAL_rows_per_index_page \* $GLOBAL_columns`
fi
compute_number_of_indexes
index_pages="$RETURN_number_of_index_pages"
make_tmpfile indexpages
GLOBAL_image_indexpages="$RETURN_tmpfile"
set_up_indexpages_tmpfile $index_pages $thumbnails_per_page
t=1
while [ $t -le $index_pages ]
do
create_an_index_page $t $index_pages
t=`expr $t + 1`
done
if [ $GLOBAL_single_index_page -eq 0 -a $index_pages -gt 1 ]
then
create_an_index_page "allinone" $index_pages
fi
}
compute_number_of_indexes ()
{
local thumbnails_per_page index_pages
RETURN_number_of_index_pages=""
if [ $GLOBAL_single_index_page -eq 1 ]
then
RETURN_number_of_index_pages=1
return
fi
thumbnails_per_page=`expr $GLOBAL_rows_per_index_page \* $GLOBAL_columns`
index_pages=`expr $GLOBAL_total_image_count / $thumbnails_per_page + 1`
if [ `expr $GLOBAL_total_image_count % $thumbnails_per_page` -le \
`expr $GLOBAL_columns \* 1` -a $index_pages -gt 1 ]
then
RETURN_number_of_index_pages=`expr $index_pages - 1`
else
RETURN_number_of_index_pages="$index_pages"
fi
}
set_up_indexpages_tmpfile ()
{
local index_pages thumbnails_per_page
local i cur_page fn
index_pages="$1"
thumbnails_per_page="$2"
cur_page=1
i=1
while read fn
do
[ $cur_page -gt $index_pages ] && cur_page=$index_pages
echo "$cur_page" "$fn" >> $GLOBAL_image_indexpages
if [ `expr $i % $thumbnails_per_page` -eq 0 ]
then
i=1
cur_page=`expr $cur_page + 1`
else
i=`expr $i + 1`
fi
done < $GLOBAL_image_list_tmpfile
}
create_an_index_page ()
{
local indexno page_name index_pages
indexno="$1"
index_pages="$2"
if [ -z "$indexno" -o -z "$index_pages" ]
then
echo ERROR: Unable to understand index page number because it\'s empty 1>&2
exit 1
fi
if [ "$indexno" = 1 -o $GLOBAL_single_index_page -eq 1 ]
then
page_name="${GLOBAL_index_base_name}.${GLOBAL_html_file_suffix}"
elif [ "$indexno" = "allinone" ]
then
page_name="${GLOBAL_index_base_name}-all.${GLOBAL_html_file_suffix}"
else
page_name="${GLOBAL_index_base_name}-${indexno}.${GLOBAL_html_file_suffix}"
fi
remove_or_move_file_aside "$page_name"
progress_update_start_creating_index_html "$page_name"
point_stdout_to_an_index_file "$page_name"
print_html_header
print_index_list "$indexno" $index_pages
print_html_table_start
iterate_over_image_list "$indexno"
print_html_table_end
print_html_footer "$page_name"
progress_update_done_creating_index_html
}
print_index_list ()
{
local indexno index_pages i page
local pad_for_one_digit pad_for_two_digits padding
indexno="$1"
index_pages="$2"
[ "$indexno" = 1 -a $index_pages -eq 1 ] && return
[ $GLOBAL_single_index_page -eq 1 ] && return
case $index_pages in
[0-9][0-9][0-9])
pad_for_one_digit=" "
pad_for_two_digits=" "
;;
[0-9][0-9])
pad_for_one_digit=" "
pad_for_two_digits=""
;;
[0-9])
pad_for_one_digit=""
pad_for_two_digits=""
;;
*)
pad_for_one_digit=""
pad_for_two_digits=""
;;
esac
echo ''
echo -n ' '
i=1
while [ $i -le $index_pages ]
do
case $i in
[0-9]) padding="$pad_for_one_digit" ;;
[0-9][0-9]) padding="$padding_for_two_digits";;
[0-9][0-9][0-9]) padding="";;
*) padding="";;
esac
if [ $i -eq 1 ]
then
page="${GLOBAL_index_base_name}.${GLOBAL_html_file_suffix}"
else
page="${GLOBAL_index_base_name}-${i}.${GLOBAL_html_file_suffix}"
fi
[ $i != "$indexno" ] && echo -n ""
echo -n "[Image set ${padding}${i}]"
[ $i != "$indexno" ] && echo -n ""
echo -n " "
i=`expr $i + 1`
done
if [ $indexno != "allinone" ]
then
echo -n ""
fi
echo -n "[All in one]"
if [ $indexno != "allinone" ]
then
echo ''
else
echo ""
fi
echo '
'
echo ""
}
point_stdout_to_an_index_file ()
{
local fn
fn="$*"
if [ -f "$fn" ]
then
echo ERROR: I was unable to remove an index page somehow! Exiting. 1>&2
exit 1
fi
GLOBAL_print_html_header_footer=1
exec > "$fn"
add_cleanup "$fn"
make_file_world_readable "$fn"
}
# Given an image name, return the name of the index.html page with that
# image on it.
map_image_to_index ()
{
local fn i page_name
fn="$*"
RETURN_index_name=""
generated_name_to_source_name "$fn"
quote_egrep_chars "$RETURN_source_name"
indexno=`egrep "^[0-9]* ${RETURN_egrep}\$" $GLOBAL_image_indexpages |
head -1 | sed 's, .*,,' | sed 's,[^0-9],,g'`
if [ -z "$indexno" ]
then
echo ERROR: Unable to figure index page for image \"$fn\"! 1>&2
exit 1
fi
if [ $indexno -eq 1 ]
then
page_name="${GLOBAL_index_base_name}.${GLOBAL_html_file_suffix}"
else
page_name="${GLOBAL_index_base_name}-${indexno}.${GLOBAL_html_file_suffix}"
fi
RETURN_index_name="$page_name"
}
#########################################################
#### Image filename conversion/test functions
#########################################################
source_name_to_thumb_name ()
{
source_name_to_generated_file_name thumb t "$*"
RETURN_thumb_name="$RETURN_generated_name"
}
source_name_to_reduced_name ()
{
source_name_to_generated_file_name reduced r "$*"
RETURN_reduced_name="$RETURN_generated_name"
}
source_name_to_large_name ()
{
source_name_to_generated_file_name large l "$*"
RETURN_large_name="$RETURN_generated_name"
}
# Call it like
# source_name_to_generated_name large l foo.jpg
# to get back "foo-l.jpg"
source_name_to_generated_file_name ()
{
local type ext fn
RETURN_generated_name=""
type="$1"; shift
ext="$1"; shift
fn="$*"
RETURN_generated_name=`echo "$*" | sed "s,\.[^.]*\$,-${ext}.jpg,"`
if [ "$fn" = "$RETURN_generated_name" ]
then
echo ERROR: I couldn\'t create a $type name for "\"${fn}\""! >&2
exit 1
fi
if echo "$RETURN_generated_name" | egrep -- "-${ext}-${ext}\." >/dev/null 2>&1
then
echo ERROR: I couldn\'t create a $type name for "\"${fn}\""! >&2
exit 1
fi
}
is_reduced_name ()
{
RETURN_is_reduced_name=0
if echo "$*" | egrep -- '-r\.[jpgpnggif]{3}$' >/dev/null 2>&1
then
RETURN_is_reduced_name=1
fi
}
is_large_name ()
{
RETURN_is_large_name=0
if echo "$*" | egrep -- '-l\.[jpgpnggif]{3}$' >/dev/null 2>&1
then
RETURN_is_large_name=1
fi
}
is_generated_name ()
{
RETURN_is_generated_name=0
if echo "$*" | egrep -- '-[trl]\.[jpgpnggif]{3}$' >/dev/null 2>&1
then
RETURN_is_generated_name=1
fi
}
source_name_to_source_html_name ()
{
RETURN_source_html_name=`echo "$*" | sed 's,\.[^.]*$,.html,'`
if [ "$*" = "$RETURN_source_html_name" ]
then
echo ERROR: I couldn\'t create an HTML name for "\"$*\""! >&2
exit 1
fi
}
image_name_to_html_name ()
{
RETURN_html_name=`echo "$*" | sed 's,\.[^.]*$,.html,'`
if [ "$*" = "$RETURN_html_name" ]
then
echo ERROR: I couldn\'t create an HTML name for "\"$*\""! >&2
exit 1
fi
}
html_name_to_image_name ()
{
local fn basename imgname
fn="$*"
basename=`echo "$fn" | sed -e 's,-[rtl].html$,,' -e 's,.html$,,'`
quote_egrep_chars "$basename"
imgname=`egrep "^${RETURN_egrep}.[jpgpnggif]{3}\$" $GLOBAL_image_list_tmpfile | head -1`
RETURN_image_name="$imgname"
if [ ! -f "$RETURN_image_name" ]
then
echo ERROR: I couldn\'t guess the image name for HTML file "\"$*\""! >&2
exit 1
fi
}
# We may have a reduced image, or we may not. If the reduced image
# is present, we return the source image HTML name (so
# source_name_to_source_html_name is equivalent to this function),
# otherwise we return the reduced image HTML name.
source_name_to_reduced_html_name ()
{
local reduced_name
source_name_to_reduced_name "$*"
reduced_name="$RETURN_reduced_name"
RETURN_reduced_html_name=`echo "$reduced_name" | sed 's,\.[jpgpnggif]*$,.html,'`
if [ "$reduced_name" = "$RETURN_reduced_html_name" ]
then
echo ERROR: I couldn\'t create an HTML name for "\"$reduced_name\""! >&2
exit 1
fi
}
source_name_to_large_html_name ()
{
local large_name
source_name_to_large_name "$*"
large_name="$RETURN_large_name"
RETURN_large_html_name=`echo "$large_name" | sed 's,\.[jpgpnggif]*$,.html,'`
if [ "$large_name" = "$RETURN_large_html_name" ]
then
echo ERROR: I couldn\'t create an HTML name for "\"$large_name\""! >&2
exit 1
fi
}
generated_name_to_source_name ()
{
local is_generated_file nameroot source
is_generated_name "$*"
if [ $RETURN_is_generated_name -eq 1 ]
then
is_generated_file=1
nameroot=`echo "$*" | sed 's,-[trl]\.[jpgpnggif]*$,,'`
else
is_generated_file=0
nameroot=`echo "$*" | sed 's,\.[jpgpnggif]*$,,'`
fi
quote_egrep_chars "$nameroot"
source=`egrep "^${RETURN_egrep}\.[jpgpnggif]{3}\$" $GLOBAL_image_list_tmpfile`
if [ -z "$source" -o ! -f "$source" -o ! -s "$source" ]
then
echo ERROR: I couldn\'t find the source name from \"$*\"! >&2
exit 1
fi
if [ "$*" = "$source" -a $is_generated_file -eq 1 ]
then
echo ERROR: I couldn\'t find convert source name with \"$*\"! >&2
exit 1
fi
RETURN_source_name="$source"
}
quote_egrep_chars ()
{
RETURN_egrep=`echo "$*" | sed -e 's,(,\\\\(,g' -e 's,),\\\\),g'`
}
quote_url_chars ()
{
RETURN_url=`echo "$*" | sed -e 's, ,%20,g' -e 's,",%22,g'`
}
quote_html_chars ()
{
RETURN_html=`echo "$*" | sed -e 's,&,\&,g' \
-e 's,<,\<,g' \
-e 's,>,\>,g'`
}
#########################################################
#### Image creation functions
#########################################################
create_generated_files ()
{
local fn
local height width
GLOBAL_there_is_at_least_one_reduced_img=0
GLOBAL_there_is_at_least_one_large_img=0
progress_update_start_creating_reduced_images
while read fn
do
create_thumbnail "$fn"
get_dimensions "$fn"
width="$RETURN_width";
height="$RETURN_height"
create_reduced "$height" "$width" "$fn"
[ $RETURN_was_reduced -eq 1 ] && GLOBAL_there_is_at_least_one_reduced_img=1
create_large "$height" "$width" "$fn"
[ $RETURN_was_larged -eq 1 ] && GLOBAL_there_is_at_least_one_large_img=1
maybe_remove_original "$fn"
done < $GLOBAL_image_list_tmpfile
progress_update_done_creating_reduced_images
}
create_thumbnail ()
{
local source_fn thumb_fn
source_fn="$*"
source_name_to_thumb_name "$source_fn"
thumb_fn="$RETURN_thumb_name"
general_image_reducer \
0 0 \
0 0 \
$GLOBAL_max_thumb_size $GLOBAL_max_thumb_size \
1 \
"$source_fn" "$thumb_fn"
if [ $RETURN_reduced_exists -eq 1 -a $RETURN_reduced_already_existed -eq 0 ]
then
progress_update_created_thumbnail_image
fi
}
create_reduced ()
{
local source_fn reduced_fn start_conv
local source_height source_width
source_height="$1"
source_width="$2"
shift; shift
source_fn="$*"
RETURN_was_reduced=0
[ $GLOBAL_reduce_big_pics -eq 0 ] && return
source_name_to_reduced_name "$source_fn"
reduced_fn="$RETURN_reduced_name"
general_image_reducer \
$source_height $source_width \
$GLOBAL_reduce_trigger_height $GLOBAL_reduce_trigger_width \
$GLOBAL_reduce_height $GLOBAL_reduce_width \
0 \
"$source_fn" "$reduced_fn"
if [ $RETURN_reduced_exists -eq 1 ]
then
RETURN_was_reduced=1
if [ $RETURN_reduced_already_existed -eq 0 ]
then
progress_update_created_reduced_image
fi
fi
}
create_large ()
{
local source_fn large_fn
local source_height source_width
source_height="$1"
source_width="$2"
shift; shift
source_fn="$*"
RETURN_was_larged=0
[ $GLOBAL_create_large_images -eq 0 ] && return
source_name_to_large_name "$source_fn"
large_fn="$RETURN_large_name"
general_image_reducer \
$source_height $source_width \
$GLOBAL_large_trigger_height $GLOBAL_large_trigger_width \
$GLOBAL_large_height $GLOBAL_large_width \
0 \
"$source_fn" "$large_fn"
if [ $RETURN_reduced_exists -eq 1 ]
then
RETURN_was_larged=1
if [ $RETURN_reduced_already_existed -eq 0 ]
then
progress_update_created_large_image
fi
fi
}
general_image_reducer ()
{
local source_height source_width
local trigger_height trigger_width
local dest_height dest_width
local creating_a_thumbnail
local source_name
local target_name
local start_conv
local t
local converted_with
source_height="$1"
source_width="$2"
trigger_height="$3"
trigger_width="$4"
dest_height="$5"
dest_width="$6"
creating_a_thumbnail="$7"
source_name="$8"
target_name="$9"
RETURN_reduced_exists=0
RETURN_reduced_already_existed=0
if [ -f "$target_name" -a -s "$target_name" ]
then
[ $creating_a_thumbnail -eq 1 ] && get_dimensions "$target_name"
if [ $creating_a_thumbnail -eq 1 -a \
$RETURN_width -ne $dest_width -a $RETURN_height -ne $dest_height ]
then
rm -f "$target_name"
else
make_file_world_readable "$target_name"
RETURN_reduced_exists=1
RETURN_reduced_already_existed=1
return
fi
fi
# If this is a portrait image, we need to swap the trigger/reduction dimensions.
# FIXME This is controversial in my mind. The question is what a height/width
# constraint means. Does it mean that's how much screen real estate you want
# to use, or does it mean how many pixels you want in an image? If it's
# referring to the screen real estate, then we want to reduce to height/width
# regardless of whether the image is in portait or landscape orientation.
# If it's referring to the # of pixels, then we want to swap height/width
# when we're looking at a portrait photo vs a landscape photo.
# The vast majority of programs on the net do the screen real estate path
# because it's the obvious one. The following code errs on the side of pixel
# count. I haven't made up my mind yet.
if [ $source_height -gt $source_width ]
then
t=$trigger_height
trigger_height=$trigger_width
trigger_width=$t
# t=$dest_height
# dest_height=$dest_width
# dest_width=$t
fi
if [ $creating_a_thumbnail -eq 1 -o \
$source_width -ge $trigger_width -o \
$source_height -ge $trigger_height ]
then
foo_to_pnm "$source_name"
start_conv="$RETURN_foo_to_pnm"
add_cleanup "$target_name"
check_for_rotation "$source_name"
if [ $GLOBAL_imagemagick_is_available -eq 1 ]
then
[ -z "$RETURN_rotation_angle" ] && RETURN_rotation_angle="0"
convert -quality $GLOBAL_compression_level \
-rotate $RETURN_rotation_angle \
-geometry ${dest_width}x${dest_height} \
"$source_name" JPEG:- > "$target_name"
converted_with="imagemagick"
elif [ $GLOBAL_netpbm_is_available -eq 1 ]
then
[ "$RETURN_rotation_angle" = "0" ] && RETURN_rotation_angle=""
$start_conv "$source_name" |
$RETURN_rotation_cmd $RETURN_rotation_angle |
pnmscale -xysize $dest_width \
$dest_height 2>/dev/null |
cjpeg -optimize -quality $GLOBAL_compression_level > "$target_name"
converted_with="netpbm"
fi
if [ $GLOBAL_jhead_is_present -eq 1 -a $creating_a_thumbnail -eq 0 ]
then
if [ "x$converted_with" != ximagemagick ]
then
jhead -te "$source_name" "$target_name" >/dev/null 2>&1
fi
jhead -dt "$target_name" >/dev/null 2>&1
fi
make_file_world_readable "$target_name"
remove_cleanup "$target_name"
tag_image_with_text "$target_name"
RETURN_reduced_exists=1
fi
if [ $RETURN_reduced_exists -eq 1 -a ! -s "$target_name" ]
then
echo "ERROR: Unable to reduce \"$source_name\"! Exiting." >&2
exit 1
fi
}
reduced_file_exists ()
{
local fn
fn="$*"
RETURN_reduced_exists=0
[ $GLOBAL_reduce_big_pics -eq 0 ] && return
source_name_to_reduced_name="$fn"
if [ -f "$RETURN_reduced_name" ]
then
RETURN_reduced_exists=1
fi
}
get_dimensions ()
{
local fn conv dimens
fn="$*"
if [ $GLOBAL_imagemagick_is_available -eq 1 ]
then
dimens=`identify -ping -format "%w %h" "$fn" 2>/dev/null`
elif [ $GLOBAL_netpbm_is_available -eq 1 ]
then
foo_to_pnm "$fn"
conv="$RETURN_foo_to_pnm"
dimens=`$conv "$fn" | pnmfile | awk '{print $4 " " $6}'`
fi
RETURN_width=`echo $dimens | cut -d ' ' -f1`
RETURN_height=`echo $dimens | cut -d ' ' -f2`
if [ -z "$RETURN_width" -o -z "$RETURN_height" ]
then
echo ERROR: Internal error in get_dimensions, for some reason I couldn\'t get >&2
echo ERROR: the dimensions of \"$fn\". Exiting. >&2
exit 1
fi
}
check_for_rotation ()
{
local fn rot_cmd
fn="$*"
RETURN_do_rotation=0
RETURN_rotation_cmd=cat
RETURN_rotation_angle="0"
[ ! -f $GLOBAL_rotation_filename ] && return
if grep -i "^[a-z-]* ${fn}" $GLOBAL_rotation_filename >/dev/null 2>&1
then
:
else
return
fi
rot_cmd=`grep -i "^[a-z-]* ${fn}" $GLOBAL_rotation_filename | sed "s/ ${fn}//"`
if [ -z "$rot_cmd" ]
then
echo WARNING: Unrecognized rotation for "$fn"! Ignoring rotate. >&2
return
fi
if [ "$rot_cmd" != "clockwise" -a "$rot_cmd" != "counter-clockwise" ]
then
echo WARNING: Unrecognized rotation for "$fn"! Ignoring rotate. >&2
return
fi
RETURN_do_rotation=1
RETURN_rotation_cmd=pnmrotate
if [ "$rot_cmd" = "clockwise" ]
then
RETURN_rotation_angle=-90
else
RETURN_rotation_angle=90
fi
}
get_image_number ()
{
local fn num total
generated_name_to_source_name "$*"
fn="$RETURN_source_name"
num=`cat -n $GLOBAL_image_list_tmpfile |
grep "^[ ]*[0-9]*[ ]*${fn}\$" |
cut -f1 | sed 's,[^0-9],,g'`
if [ -z "$num" ]
then
echo WARNING: Could not get image number for file \"$fn\"! 1>&2
fi
RETURN_image_number="$num"
total="$GLOBAL_total_image_count"
if [ -z "$total" ]
then
echo WARNING: Could not determine number of image files! 1>&2
fi
RETURN_number_of_images="$total"
}
tag_image_with_text ()
{
local fn font_size font xoffset yoffset text
fn="$*"
[ -n "$GLOBAL_image_imprinting_text" ] || return
[ "$GLOBAL_image_imprinting_text" = "undef" ] && return
[ $GLOBAL_mogrify_is_present -eq 0 ] && return
font_size=12
font="-*-helvetica-bold-r-*-*-${font_size}-*-*-*-*-*-iso8859-*"
compute_subtitle_pixelwidth "$font_size"
get_dimensions "$fn"
xoffset=`expr $RETURN_width - $GLOBAL_image_subtitle_pixelwidth`
[ $xoffset -le 0 ] && xoffset=0
yoffset=`expr $RETURN_height - $font_size`
add_cleanup "$fn"
text=`echo "$GLOBAL_image_imprinting_text" | sed "s,\",',g"`
mogrify -fill yellow -font "$font" \
-draw "text ${xoffset},${yoffset} \"$text\"" "$fn"
remove_cleanup "$fn"
}
# This function tries to determine the pixel width of a text string given
# the string and given the font size that it'll be rendered in. I wish we
# could just get the number directly from the imaging program that does it,
# but I don't think I can. I need this information so I can justify the
# text right-flush at the bottom of the image.
#
# The font is proportional, so these are just estimations. In short,
#
# upper-case char pixel width = font-size / 1.45 (8.27 pixels/char @ 12pts)
# lower-case char pixel width = font-size / 2.20 (5.45 pixels/char @ 12pts)
# space char pixel width = font-size / 2.22 (5.45 pixels/char @ 12pts)
# all other chars pixel width = font-size / 1.60 (7.50 pixels/char @ 12pts)
compute_subtitle_pixelwidth ()
{
local font_size len len_padded lowcase upcase space otherchars pixellen
font_size="$*"
[ -n "$GLOBAL_image_subtitle_pixelwidth" ] && return
len=`echo "$GLOBAL_image_imprinting_text" | wc -c |
sed -e 's,^[ ]*,,' -e 's,[ ]*$,,'`
len_padded=`expr $len \* $font_size \* 10`
lowcase=`echo "$GLOBAL_image_imprinting_text" | tr -cd '[a-z]' |
wc -c | sed -e 's,^[ ]*,,' -e 's,[ ]*$,,'`
upcase=`echo "$GLOBAL_image_imprinting_text" | tr -cd '[A-Z0-9]' |
wc -c | sed -e 's,^[ ]*,,' -e 's,[ ]*$,,'`
space=`echo "$GLOBAL_image_imprinting_text" | tr -cd '[ ]' |
wc -c | sed -e 's,^[ ]*,,' -e 's,[ ]*$,,'`
otherchars=`expr $len - $upcase - $lowcase - $space`
pixellen=`expr $lowcase \* $font_size \* 100 / 220`
pixellen=`expr $pixellen + $upcase \* $font_size \* 100 / 145`
pixellen=`expr $pixellen + $space \* $font_size \* 100 / 220`
pixellen=`expr $pixellen + $otherchars \* $font_size \* 100 / 160`
pixellen=`expr $pixellen + 2`
GLOBAL_image_subtitle_pixelwidth="$pixellen"
}
#########################################################
#### HTML printing functions
#########################################################
print_html_header ()
{
get_directory_title
echo ''
echo ''
echo '
'
echo " $RETURN_directory_title_inline"
[ -n "$GLOBAL_meta_tag" -a "$GLOBAL_meta_tag" != undef ] && echo " $GLOBAL_meta_tag"
if [ "$GLOBAL_html_charset" != "undef" ]
then
echo " "
fi
echo " "
if [ -n "$GLOBAL_boilerplate_index_head_stuff" -a \
"$GLOBAL_boilerplate_index_head_stuff" != undef ]
then
echo "$GLOBAL_boilerplate_index_head_stuff"
fi
echo ''
echo "$GLOBAL_body_tag"
echo ""
if [ -n "$GLOBAL_boilerplate_index_before_title" -a \
"$GLOBAL_boilerplate_index_before_title" != undef ]
then
echo "$GLOBAL_boilerplate_index_before_title"
echo ""
fi
if [ $GLOBAL_print_title_on_index -eq 1 ]
then
echo "$RETURN_directory_title
"
fi
echo ""
if [ -n "$GLOBAL_boilerplate_index_after_title" -a \
"$GLOBAL_boilerplate_index_after_title" != undef ]
then
echo "$GLOBAL_boilerplate_index_after_title"
echo ""
fi
get_directory_description
if [ -n "$RETURN_directory_description" ]
then
echo "$RETURN_directory_description"
echo "
"
echo ""
fi
}
print_html_table_start ()
{
if [ $GLOBAL_compact_index_page -eq 1 ]
then
echo '
'
else
echo ''
fi
}
print_html_table_end ()
{
if [ $GLOBAL_last_row_was_closed -eq 0 ]
then
echo ""
fi
echo ""
echo '
'
}
print_html_row_start ()
{
echo ""
echo ''
}
print_html_row_end ()
{
echo '
'
echo ""
if [ $GLOBAL_compact_index_page -eq 0 ]
then
#
echo "| |
"
fi
}
print_html_column_start ()
{
echo ' '
}
print_html_column_end ()
{
echo ' | '
}
# FIXME: I can't decide if the user's footer text should come
# before the "This page created" text or after that text. If they're
# putting a
tag, it would probably look better to put the
# This Page text after the user's footer text.
print_html_footer ()
{
local fn
fn="$*"
echo ""
echo "This page created on `date '+%Y-%m-%d'`."
if [ -n "$GLOBAL_boilerplate_footer" -a "$GLOBAL_boilerplate_footer" != undef ]
then
echo ""
echo "$GLOBAL_boilerplate_footer"
echo ""
fi
cat << __EOM__
__EOM__
if [ -n "$GLOBAL_boilerplate_index_end_of_page" -a \
"$GLOBAL_boilerplate_index_end_of_page" != undef ]
then
echo ""
echo "$GLOBAL_boilerplate_index_end_of_page"
echo ""
fi
echo ''
echo ''
add_checksum_to_file "$fn"
remove_cleanup "$fn"
}
#########################################################
#### slideshow functions
#########################################################
create_slideshow ()
{
local fileset prev cur next
[ $GLOBAL_create_slideshow -eq 0 ] && return
progress_update_start_creating_slideshow_pages
remove_existing_slideshow_html_files
create_slideshow_image_list
while read fileset
do
prev=`echo "$fileset" | cut -d\| -f1`
cur=`echo "$fileset" | cut -d\| -f2`
next=`echo "$fileset" | cut -d\| -f3`
create_slideshow_source_file "$prev" "$cur" "$next"
if [ $GLOBAL_reduce_big_pics -eq 1 -a \
$GLOBAL_there_is_at_least_one_reduced_img -eq 1 ]
then
create_slideshow_reduced_file "$prev" "$cur" "$next"
fi
if [ $GLOBAL_create_large_images -eq 1 -a \
$GLOBAL_there_is_at_least_one_large_img -eq 1 ]
then
create_slideshow_large_file "$prev" "$cur" "$next"
fi
progress_update_created_slideshow_page
done < $GLOBAL_slideshow_image_list
progress_update_done_creating_slideshow_pages
}
create_slideshow_source_file ()
{
local prev_image cur_image next_image html_file
prev_image="$1"
cur_image="$2"
next_image="$3"
image_name_to_html_name "$cur_image"
html_file="$RETURN_html_name"
add_cleanup "$html_file"
print_slideshow_file_header "$prev_image" "$cur_image" "$next_image" \
"$html_file"
print_slideshow_top_navlinks "$prev_image" "$cur_image" "$next_image" \
"$html_file"
print_slideshow_image "$cur_image" "$html_file" "source"
print_slideshow_size_links "source" "$cur_image" "$html_file"
print_slideshow_image_description "$html_file"
print_image_exif_info "$cur_image"
print_slideshow_file_footer "$html_file"
remove_cleanup "$html_file"
}
create_slideshow_reduced_file ()
{
local prev_image cur_image next_image
local cur_source_image cur_reduced_image html_file
prev_image="$1"
cur_image="$2"
next_image="$3"
cur_source_image="$cur_image"
cur_reduced_image="$cur_image"
if [ "$prev_image" != NULL ]
then
source_name_to_reduced_name "$prev_image"
prev_image="$RETURN_reduced_name"
fi
source_name_to_reduced_name "$cur_image"
cur_reduced_image="$RETURN_reduced_name"
if [ -f "$RETURN_reduced_name" ]
then
cur_image="$RETURN_reduced_name"
else
source_name_to_large_name "$cur_image"
if [ -f "$RETURN_large_name" ]
then
cur_image="$RETURN_large_name"
fi
fi
if [ "$next_image" != NULL ]
then
source_name_to_reduced_name "$next_image"
next_image="$RETURN_reduced_name"
fi
image_name_to_html_name "$cur_reduced_image"
html_file="$RETURN_html_name"
add_cleanup "$html_file"
print_slideshow_file_header "$prev_image" "$cur_image" "$next_image" \
"$html_file"
print_slideshow_top_navlinks "$prev_image" "$cur_image" "$next_image" \
"$html_file"
print_slideshow_image "$cur_image" "$html_file" "reduced"
print_slideshow_size_links "reduced" "$cur_image" "$html_file"
print_slideshow_image_description "$html_file"
print_image_exif_info "$cur_reduced_image"
print_slideshow_file_footer "$html_file"
remove_cleanup "$html_file"
}
create_slideshow_large_file ()
{
local prev_image cur_image next_image
local cur_source_image cur_large_image html_file
prev_image="$1"
cur_image="$2"
next_image="$3"
cur_source_image="$cur_image"
cur_large_image="$cur_image"
if [ "$prev_image" != NULL ]
then
source_name_to_large_name "$prev_image"
prev_image="$RETURN_large_name"
fi
source_name_to_large_name "$cur_image"
cur_large_image="$RETURN_large_name"
if [ -f "$RETURN_large_name" ]
then
cur_image="$RETURN_large_name"
else
source_name_to_reduced_name "$cur_image"
if [ -f "$RETURN_reduced_name" ]
then
cur_image="$RETURN_reduced_name"
fi
fi
if [ "$next_image" != NULL ]
then
source_name_to_large_name "$next_image"
next_image="$RETURN_large_name"
fi
image_name_to_html_name "$cur_large_image"
html_file="$RETURN_html_name"
add_cleanup "$html_file"
print_slideshow_file_header "$prev_image" "$cur_image" "$next_image" \
"$html_file"
print_slideshow_top_navlinks "$prev_image" "$cur_image" "$next_image" \
"$html_file"
print_slideshow_image "$cur_image" "$html_file" "large"
print_slideshow_size_links "large" "$cur_image" "$html_file"
print_slideshow_image_description "$html_file"
print_image_exif_info "$cur_large_image"
print_slideshow_file_footer "$html_file"
remove_cleanup "$html_file"
}
javascript_navigate=''
javascript_next_img='if (keyval == key_n || keyval == key_k) { location = "@NEXT@"; return true; }'
javascript_previous_img='if (keyval == key_p || keyval == key_j) { location = "@PREVIOUS@"; return true; }'
print_slideshow_file_header ()
{
local source_image prev_image next_image html_file
local t t_prev t_next
prev_image="$1"
source_image="$2"
next_image="$3"
html_file="$4"
get_image_caption "$source_image"
is_this_a_boring_filename "$source_image"
if [ $GLOBAL_slideshow_print_javascript_navigation -eq 1 ]
then
if [ "$prev_image" != NULL -a "$prev_image" ]
then
image_name_to_html_name "$prev_image"
quote_url_chars "$RETURN_html_name"
t_prev=`echo "$javascript_previous_img" |
sed "s/@PREVIOUS@/${RETURN_url}/g"`
fi
if [ "$next_image" != NULL -a "$next_image" ]
then
image_name_to_html_name "$next_image"
quote_url_chars "$RETURN_html_name"
t_next=`echo "$javascript_next_img" |
sed "s/@NEXT@/${RETURN_url}/g"`
fi
t=`echo "$javascript_navigate" |
sed -e "s/@JAVASCRIPT_PREVIOUS@/${t_prev}/g" |
sed -e "s/@JAVASCRIPT_NEXT@/${t_next}/g"`
fi
# The following exec goop so I don't have to manually redirect every
# message to stderr in this function.
exec 4>&1 # save stdout fd to fd #4
exec > "$html_file" # redirect stdout to stderr
echo ''
echo ''
echo '
'
echo " $RETURN_caption_inline"
[ -n "$GLOBAL_meta_tag" -a "$GLOBAL_meta_tag" != undef ] && echo " $GLOBAL_meta_tag"
if [ "$GLOBAL_html_charset" != "undef" ]
then
echo " "
fi
echo " "
echo ' '
[ $GLOBAL_slideshow_print_javascript_navigation -eq 1 ] && echo "$t"
echo ''
echo "$GLOBAL_body_tag"
echo ""
get_directory_title
if [ -n "$RETURN_directory_title_inline" ]
then
if [ $RETURN_directory_title_is_from_user -eq 1 ]
then
echo -n "$RETURN_directory_title_inline"
if [ $GLOBAL_heuristic_filenames_are_digicam_boring -eq 0 -o \
$RETURN_caption_was_from = "descriptions-file" -o \
$RETURN_is_boring -eq 0 ]
then
echo " / $RETURN_caption_inline
"
else
echo ""
fi
elif [ $RETURN_caption_was_from = "descriptions-file" -o \
$RETURN_is_boring -eq 0 ]
then
echo "$RETURN_caption_inline
"
fi
fi
exec 1>&4 # Copy stdout fd back from temporary save fd, #4
make_file_world_readable "$html_file"
}
print_slideshow_size_links ()
{
local current_image current_image_type html_file
local reduced_image large_image orig_image
local reduced_link_text large_link_text orig_link_text
local size
local spacer
current_image_type="$1"
current_image="$2"
html_file="$3"
if [ $GLOBAL_slideshow_img_size_across_two_lines -eq 1 ]
then
spacer="
"
else
spacer=" "
fi
generated_name_to_source_name "$current_image"
orig_image="$RETURN_source_name"
source_name_to_reduced_name "$orig_image"
reduced_image="$RETURN_reduced_name"
source_name_to_large_name "$orig_image"
large_image="$RETURN_large_name"
if [ -f "$reduced_image" ]
then
if [ $GLOBAL_print_img_size_on_slideshow -eq 1 ]
then
return_image_size "$reduced_image"
size="${spacer}(${RETURN_image_size_str})"
fi
if [ "$current_image_type" != "reduced" ]
then
image_name_to_html_name "$reduced_image"
quote_url_chars "$RETURN_html_name"
reduced_link_text="[reduced]$size"
else
reduced_link_text="[reduced]$size"
fi
fi
if [ -f "$large_image" ]
then
if [ $GLOBAL_print_img_size_on_slideshow -eq 1 ]
then
return_image_size "$large_image"
size="${spacer}(${RETURN_image_size_str})"
fi
if [ "$current_image_type" != "large" ]
then
image_name_to_html_name "$large_image"
quote_url_chars "$RETURN_html_name"
large_link_text="[large]$size"
else
large_link_text="[large]$size"
fi
fi
if [ -f "$orig_image" ]
then
if [ $GLOBAL_print_img_size_on_slideshow -eq 1 ]
then
return_image_size "$orig_image"
size="${spacer}(${RETURN_image_size_str})"
fi
if [ "$current_image_type" != "source" ]
then
image_name_to_html_name "$orig_image"
quote_url_chars "$RETURN_html_name"
orig_link_text="[original]$size"
else
orig_link_text="[original]$size"
fi
fi
[ -z "$reduced_link_text" -a -z "$large_link_text" ] && return
echo '' >> "$html_file"
echo '
' >> "$html_file"
echo " | $reduced_link_text | " >> "$html_file"
echo " | " >> "$html_file"
echo " $large_link_text | " >> "$html_file"
echo " | " >> "$html_file"
echo " $orig_link_text | " >> "$html_file"
echo '
' >> "$html_file"
}
print_slideshow_image_description ()
{
local html_file
html_file="$*"
html_name_to_image_name "$html_file"
get_image_description "$RETURN_image_name"
if [ -n "$RETURN_image_description" ]
then
echo "$RETURN_image_description
" >> "$html_file"
fi
}
print_slideshow_file_footer ()
{
local html_file
html_file="$*"
html_name_to_image_name "$html_file"
if [ -n "$GLOBAL_boilerplate_footer" -a "$GLOBAL_boilerplate_footer" != undef ]
then
echo "" >> "$html_file"
echo "$GLOBAL_boilerplate_footer" >> "$html_file"
echo "" >> "$html_file"
fi
echo "" >> "$html_file"
echo "