3 # bpgallery.sh - builds a simple 'gallery' from a collection of images
4 # Copyright (C) 2004-2008 Brett Parker <iDunno@sommitrealweird.co.uk>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along
17 # with this program; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 function bpgallery_default_head() {
27 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd">
28 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
30 <title>${TITLE}</title>
31 <link rel="stylesheet" href="${BASEURL}style.css" type="text/css" />
37 declare -rf bpgallery_default_head
39 function bpgallery_default_description() {
46 declare -rf bpgallery_default_description
48 function bpgallery_default_thumbsline() {
49 if [[ -z $caption ]]; then
55 <div class="thumbnail"><a href="$link"><img src="${ICONSDIRECTORY}/$filename" alt="$caption_alt" /></a><div class="caption">$caption</div></div>
59 declare -rf bpgallery_default_thumbsline
61 function bpgallery_default_tail() {
68 declare -rf bpgallery_default_tail
70 function bpgallery_default_stylesheet() {
75 font-family: sans-serif;
84 height: ${MAXHEIGHT}px;
105 div.navigation ul li {
120 declare -rf bpgallery_default_stylesheet
122 function bpgallery_default_page() {
123 $BPGALLERY_HEAD_FUNCTION
128 if [[ ! -z $linklocation ]]; then
129 linkstart="<a href='$linklocation'>"
135 <div class="navigation">
137 <li><a href='${BASEURL}${INDEXDOCUMENT}'>Thumbnails</a></li>
139 if [[ ! -z $previouspage ]]; then
140 $ECHOCOMMAND "<li><a href='${previouspage}'>Previous</a></li>"
142 $ECHOCOMMAND "<li>Previous</li>"
145 if [[ ! -z $nextpage ]]; then
146 $ECHOCOMMAND "<li><a href='${nextpage}'>Next</a></li>"
148 $ECHOCOMMAND "<li>Next</li>"
153 <div class="mainimage">
154 ${linkstart}<img src="${filename}" alt="${caption}" />${linkend}
157 $BPGALLERY_TAIL_FUNCTION
160 declare -rf bpgallery_default_page
162 function bpgallery_escape_url() {
180 function bpgallery_cleanup_directory_name() {
198 declare -rf bpgallery_escape_url
200 if [[ ! -z ${BPGALLERY_THEME} ]] ; then
201 declare -r BPGALLERY_THEME
204 if [[ ! -z ${TITLE} ]] ; then
208 if [[ -e /usr/local/etc/bpgallery/config ]] ; then
209 . /usr/local/etc/bpgallery/config 2>/dev/null
212 if [[ -e /etc/bpgallery/config ]] ; then
213 . /etc/bpgallery/config 2>/dev/null
216 if [[ -e $HOME/.bpgallery.rc ]]; then
217 . $HOME/.bpgallery.rc 2>/dev/null
220 if [[ -e $1 && -d $1 && -e $1/.bpgallery.rc ]]; then
221 . $1/.bpgallery.rc 2>/dev/null
224 if [[ -z ${BPGALLERY_THEME} ]]; then
225 BPGALLERY_THEME=default
228 if [[ ! -z ${BPGALLERY_THEME_DIR} ]] && \
229 [[ -e ${BPGALLERY_THEME_DIR}/${BPGALLERY_THEME} ]]; then
230 . ${BPGALLERY_THEME_DIR}/${BPGALLERY_THEME} 2>/dev/null
231 elif [[ -e $HOME/.bpgallery.themes/${BPGALLERY_THEME} ]]; then
232 . $HOME/.bpgallery.themes/${BPGALLERY_THEME} 2>/dev/null
233 elif [[ -e /usr/local/etc/bpgallery/themes/${BPGALLERY_THEME} ]]; then
234 . /usr/local/etc/bpgallery/themes/${BPGALLERY_THEME} 2>/dev/null
235 elif [[ -e /etc/bpgallery/themes/${BPGALLERY_THEME} ]]; then
236 . /etc/bpgallery/themes/${BPGALLERY_THEME} 2>/dev/null
239 if [[ -z $TITLE ]]; then
240 TITLE="Photo Gallery"
243 if [[ -z $CONVERTTOOL ]]; then
245 if [[ $? != 0 ]]; then
246 echo "Can't find convert, exiting"
249 CONVERTTOOL=$(hash -t convert)
251 if [[ ! -x $CONVERTTOOL ]]; then
252 echo "Can't find convert at location $CONVERTTOOL, exiting"
257 if [[ -z $FINDCOMMAND ]]; then
259 if [[ $? != 0 ]]; then
260 echo "Can't find find, exiting"
263 FINDCOMMAND=$(hash -t find)
265 if [[ ! -x $FINDCOMMAND ]]; then
266 echo "Can't find find at $FINDCOMMAND, exiting"
271 if [[ -z $XARGSCOMMAND ]]; then
273 if [[ $? != 0 ]]; then
274 echo "Can't find xargs, exiting"
277 XARGSCOMMAND=$(hash -t xargs)
279 if [[ ! -x $XARGSCOMMAND ]]; then
280 echo "Can't find xargs at $XARGSCOMMAND, exiting"
285 if [[ -z $ECHOCOMMAND ]]; then
288 if [[ ! -x $ECHOCOMMAND ]]; then
289 echo "Can't find echo at $ECHOCOMMAND, exiting"
294 if [[ -z $SORTCOMMAND ]]; then
296 if [[ $? != 0 ]]; then
297 echo "Can't find sort, exiting"
300 SORTCOMMAND=$(hash -t sort)
302 if [[ ! -x $SORTCOMMAND ]]; then
303 echo "Can't find sort, exiting"
308 if [[ -z $IDENTIFYCOMMAND ]]; then
310 if [[ $? != 0 ]]; then
311 echo "Can't find indentify, exiting"
314 IDENTIFYCOMMAND=$(hash -t identify)
316 if [[ ! -x $IDENTIFYCOMMAND ]]; then
317 echo "Can't find identify at $IDENTIFYCOMMAND, exiting"
322 if [[ -z $HEADCOMMAND ]]; then
324 if [[ $? != 0 ]]; then
325 echo "Can't find head, exiting"
328 HEADCOMMAND=$(hash -t head)
330 if [[ ! -x $HEADCOMMAND ]]; then
331 echo "Can't find head at $HEADCOMMAND, exiting"
336 if [[ -z $GREPCOMMAND ]]; then
338 if [[ $? != 0 ]]; then
339 echo "Can't find grep, exiting"
342 GREPCOMMAND=$(hash -t grep)
344 if [[ ! -x $GREPCOMMAND ]]; then
345 echo "Can't find grep at $GREPCOMMAND, exiting"
350 if [[ -z $SEDCOMMAND ]]; then
352 if [[ $? != 0 ]]; then
353 echo "Can't find sed, exiting"
356 SEDCOMMAND=$(hash -t sed)
358 if [[ ! -x $SEDCOMMAND ]]; then
359 echo "Can't find sed at $SEDCOMMAND, exiting"
364 if [[ -z $WCCOMMAND ]]; then
366 if [[ $? != 0 ]]; then
367 echo "Can't find wc, exiting"
370 WCCOMMAND=$(hash -t wc)
371 WCCOMMAND="$WCCOMMAND -l"
373 if [[ ! -x $WCCOMMAND ]]; then
374 echo "Can't find wc at $WCCOMMAND, exiting"
377 WCCOMMAND="$WCCOMMAND -l"
380 if [[ -z $MAXTHREADS ]]; then
381 # if there's more than 2G of memory, then do 4 threads, otherwise, just 1
382 __total_memory=$(free -t -g | sed -ne '2 { s#Mem:[[:space:]]*\([0-9]*\)[[:space:]]*.*$#\1#; p; }')
383 if [[ $__total_memory -ge 2 ]]; then
390 if [[ -z $WIDTH ]]; then
394 if [[ -z $IMAGEEXTENSIONS ]]; then
395 IMAGEEXTENSIONS="jpeg jpg gif png";
398 if [[ -z $CAPTIONHEIGHT ]]; then
402 if [[ -z $OUTPUTHTML ]]; then
406 if [[ -z $GENERATEPAGESFORFULLSIZE ]]; then
407 GENERATEPAGESFORFULLSIZE=0
410 if [[ -z $GENERATEPAGESFORMEDIUMSIZE ]]; then
411 GENERATEPAGESFORMEDIUMSIZE=1
414 if [[ -z $PAGESDIRECTORY ]]; then
417 removetrailingslashes=${PAGESDIRECTORY%/}
418 temp=$removetrailingslashes
419 while [[ $removetrailingslashes != $temp ]]; do
420 temp=$removetrailingslashes
421 removetrailingslashes=${temp%/}
423 PAGESDIRECTORY=$(bpgallery_escape_url "${PAGESDIRECTORY}")
426 if [[ -z $MEDIUMWIDTH ]]; then
430 if [[ -z $INDEXDOCUMENT ]]; then
431 INDEXDOCUMENT=index.html
434 if [[ -z $MEDIUMDIRECTORY ]]; then
435 MEDIUMDIRECTORY=medium
437 # Strip out anything that might be broken
438 MEDIUMDIRECTORY=$(bpgallery_cleanup_directory_name "$MEDIUMDIRECTORY")
441 if [[ -z $ICONSDIRECTORY ]]; then
444 # Strip out anything that might be broken
445 ICONSDIRECTORY=$(bpgallery_cleanup_directory_name "$ICONSDIRECTORY")
448 if declare -F "bpgallery_${BPGALLERY_THEME}_page" > /dev/null ; then
449 BPGALLERY_PAGE_FUNCTION="bpgallery_${BPGALLERY_THEME}_page"
451 BPGALLERY_PAGE_FUNCTION="bpgallery_default_page"
454 if declare -F "bpgallery_${BPGALLERY_THEME}_head" > /dev/null ; then
455 BPGALLERY_HEAD_FUNCTION="bpgallery_${BPGALLERY_THEME}_head"
457 BPGALLERY_HEAD_FUNCTION="bpgallery_default_head"
460 if declare -F "bpgallery_${BPGALLERY_THEME}_description" > /dev/null ; then
461 BPGALLERY_DESCRIPTION_FUNCTION="bpgallery_${BPGALLERY_THEME}_description"
463 BPGALLERY_DESCRIPTION_FUNCTION="bpgallery_default_description"
466 if declare -F "bpgallery_${BPGALLERY_THEME}_thumbsline" > /dev/null ; then
467 BPGALLERY_THUMBSLINE_FUNCTION="bpgallery_${BPGALLERY_THEME}_thumbsline"
469 BPGALLERY_THUMBSLINE_FUNCTION="bpgallery_default_thumbsline"
472 if declare -F "bpgallery_${BPGALLERY_THEME}_tail" > /dev/null ; then
473 BPGALLERY_TAIL_FUNCTION="bpgallery_${BPGALLERY_THEME}_tail"
475 BPGALLERY_TAIL_FUNCTION="bpgallery_default_tail"
478 if declare -F "bpgallery_${BPGALLERY_THEME}_stylesheet" > /dev/null ; then
479 BPGALLERY_STYLESHEET_FUNCTION="bpgallery_${BPGALLERY_THEME}_stylesheet"
481 BPGALLERY_STYLESHEET_FUNCTION="bpgallery_default_stylesheet"
486 for imageext in $IMAGEEXTENSIONS; do
487 FINDIMAGESOPTIONS=$FINDIMAGESOPTIONS' -o -type f -iname '*.$imageext' -print0'
490 FINDIMAGESOPTIONS=${FINDIMAGESOPTIONS## -o }
491 FINDIMAGESOPTIONS='-maxdepth 1 '${FINDIMAGESOPTIONS}
496 $0 [--help|--version|<path to images>]
499 displays this help screen
501 displays the version and exits
503 This can also takes some environment variables, these will use defaults if not
507 the title of the gallery
510 the width to make the icons
513 the height to make the icons (sets up a bounding box with WIDTH)
516 set the width of images in the medium size pages
519 the height to make images in the medium size pages (sets up a
520 bounding box with MEDIUMWIDTH)
523 set the theme to use (described below)
526 set an extra location to look for themes
529 sets the script output to be wrapped in a <pre> block
531 GENERATEPAGESFORMEDIUMSIZE
532 generate medium sized images and pages
534 GENERATEPAGESFORFULLSIZE
535 decide wether to generate pages for the full size images or not
538 name of the index page (e.g. index.html)
541 TITLE="My Funky Gallery" WIDTH=200 INDEXDOCUMENT="welcome.html" GENERATEPAGESFORFULLSIZE=1 GENERATEPAGESFORMEDIUMSIZE=1 MEDIUMWIDTH=400 $0 /path/to/image/folder
551 function check_dimensions() {
556 if [ ! -e "$dir/$filename" ]; then
560 iconwidth=$($IDENTIFYCOMMAND -format "%wx%h" "$dir/$filename")
561 iconheight=${iconwidth//*x}
562 iconwidth=${iconwidth//x*}
563 # are the dimensions correctish?
565 if [ ! -z $wantedheight ]; then
566 if [ $wantedwidth -ne $iconwidth ] && [ $wantedheight -ne $iconheight ]; then
569 # make sure that both of the dimensions are smaller than they
571 if [ $iconwidth -gt $wantedwidth ] || [ $iconheight -gt $wantedheight ]; then
576 if [ $wantedwidth -ne $iconwidth ]; then
583 function generate_resized_images() {
584 $ECHOCOMMAND "Generating $2"
587 if [ $width != $height ]; then
593 totalimages=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | $WCCOMMAND);
594 imagestoupdate=$($FINDCOMMAND . $FINDIMAGESOPTIONS |
595 $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} |
596 while read filename; do
597 filename=${filename//\"/\\\"}
598 imagesizeright=$(check_dimensions "$width" "$height" "$2" "$filename")
599 if [ ! -r "$2/$filename" ] ||
600 [ "$filename" -nt "$2/$filename" ] ||
601 [ $imagesizeright -ne 1 ]; then
602 $ECHOCOMMAND $filename
607 if [ $totalimages -eq 0 ]; then
608 # might as well exit at this point - there are no pictures
609 $ECHOCOMMAND "No images for the gallery - exiting."
612 # check if the directory exists and create it other wise
618 $ECHOCOMMAND "Can't write to $2 directory, exiting"
623 if [ $totalimages -eq $imagestoupdate ]; then
624 $ECHOCOMMAND "Regenerating all $2"
625 elif [ $imagestoupdate -eq 0 ]; then
626 $ECHOCOMMAND "No Updated $2, not regenerating"
629 $ECHOCOMMAND "Generating $imagestoupdate of $totalimages $2"
632 $FINDCOMMAND . $FINDIMAGESOPTIONS | \
633 $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | \
634 while read filename; do
635 tempfilename=${filename//\"/\\\"/};
636 imagesizeright=$(check_dimensions "$width" "$height" "$2" "$filename")
637 if [ ! -r "$2/$tempfilename" ] \
638 || [ "$tempfilename" -nt "$2/$tempfilename" ] \
639 || [ $imagesizeright -ne 1 ]; then
640 $ECHOCOMMAND -n $filename
641 $ECHOCOMMAND -n -e "\000"
644 $XARGSCOMMAND -0 --verbose --max-procs=$MAXTHREADS -I {} $CONVERTTOOL -resize $1 '{}' $2/'{}' 2>&1 | \
645 while read throwout; do
646 $ECHOCOMMAND done: $currentimage/$imagestoupdate images
647 currentimage=$((currentimage+1))
649 $ECHOCOMMAND done: $imagestoupdate/$imagestoupdate images
650 $ECHOCOMMAND "Completed generating $2 for $totalimages images"
653 function generate_thumbs() {
654 if [ ! -z $HEIGHT ]; then
655 generate_resized_images "${WIDTH}x${HEIGHT}" $ICONSDIRECTORY
657 generate_resized_images $WIDTH $ICONSDIRECTORY
661 function generate_medium() {
662 if [ ! -z $MEDIUMHEIGHT ]; then
663 generate_resized_images "${MEDIUMWIDTH}x${MEDIUMHEIGHT}" $MEDIUMDIRECTORY
665 generate_resized_images $MEDIUMWIDTH $MEDIUMDIRECTORY
669 function generate_pages() {
670 $ECHOCOMMAND "Generating Pages"
690 if [ -z $2 ] && [[ $GENERATEPAGESFORMEDIUMSIZE != 0 ]]; then
694 $FINDCOMMAND . $FINDIMAGESOPTIONS | \
695 $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | \
697 while read imagefilename; do
698 previousimage=$currentimage
699 currentimage=$nextimage
700 nextimage=${imagefilename#./}
703 if [[ $GENERATEPAGESFORFULLSIZE != 0 ]]; then
704 if [[ $addlinks == 1 ]]; then
705 addlink=${currentimage}.html
707 addlink=${currentimage}${extra}.html
710 addlink=${currentimage}
713 previouspage=$currentpage
714 currentpage=$nextpage
715 if [[ $addlinks == 1 ]]; then
716 nextpage=${nextimage}${extra}.html
718 nextpage=${nextimage}.html
721 if [[ "x$PAGESDIRECTORY" != "x" ]]; then
722 filename=../${extradir}${currentimage}
724 filename=${extradir}${currentimage}
726 if [ "x$currentpage" != "x" ]; then
727 generate_general_page "$previouspage" "$currentpage" "$nextpage" $addlink
729 $ECHOCOMMAND $nextimage
735 if [[ $GENERATEPAGESFORFULLSIZE != 0 ]]; then
736 if [[ $addlinks == 1 ]]; then
737 addlink=${currentpage}.html
739 addlink=${currentpage}${extra}.html
742 addlink=${currentpage}
745 if [[ "x$PAGESDIRECTORY" != "x" ]]; then
746 filename=../${extradir}${currentpage}
748 filename=${extradir}${currentpage}
750 if [[ $addlinks == 1 ]]; then
751 currentpage=${currentpage}${extra}.html
752 previouspage=${previouspage}${extra}.html
754 currentpage=${currentpage}.html
755 previouspage=${previouspage}.html
758 generate_general_page "$previouspage" "$currentpage" "" $addlink
762 function generate_medium_pages() {
763 generate_pages __${MEDIUMDIRECTORY} ${MEDIUMDIRECTORY}
766 function generate_general_page() {
781 if [[ ! -z $4 ]]; then
785 if [ -r captions.txt ]; then
786 imagefilename=${filename##*/}
787 caption=$($GREPCOMMAND -E "^${imagefilename} " captions.txt); caption=${caption#* }
792 $BPGALLERY_PAGE_FUNCTION > "${UNIXPAGESDIRECTORY}$currentpage"
795 if [[ $OUTPUTHTML != 0 ]]; then
800 $ECHOCOMMAND "No path given"
805 if [[ "$1" == "--help" || "$1" == "-h" ]]; then
810 if [[ "$1" == "--version" || "$1" == "-v" ]]; then
815 if [[ ! -d $1 ]]; then
816 $ECHOCOMMAND "$1 is not a directory"
823 if ( ! $FINDCOMMAND . $FINDIMAGESOPTIONS > /dev/null 2>/dev/null ); then
824 $ECHOCOMMAND "$1 does not contain any images. Quitting."
829 $ECHOCOMMAND "Can't write to images directory, exiting"
833 if [ -e ${INDEXDOCUMENT} ] && [ ! -w ${INDEXDOCUMENT} ]; then
834 $ECHOCOMMAND "Can't write ${INDEXDOCUMENT}, exiting"
838 if [ -e style.css ] && [ ! -w style.css ]; then
839 $ECHOCOMMAND "Can't write style.css, exiting"
845 if [[ "x$PAGESDIRECTORY" != "x" ]]; then
846 if [ ! -d $PAGESDIRECTORY ]; then
847 mkdir -p $PAGESDIRECTORY
850 if [ ! -w $PAGESDIRECTORY ]; then
851 $ECHOCOMMAND "Can't write to $PAGESDIRECTORY directory, exiting"
854 UNIXPAGESDIRECTORY=$PAGESDIRECTORY/
855 PAGESDIRECTORY=$(bpgallery_escape_url $PAGESDIRECTORY)/
860 UNIXPAGESDIRECTORY=""
863 if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
865 generate_medium_pages
868 if [ $GENERATEPAGESFORFULLSIZE != 0 ]; then
869 if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
870 generate_pages __${MEDIUMDIRECTORY}
876 if [ -r description.txt ] ; then
877 DESCRIPTION=$($SEDCOMMAND -e '1 { s/^/<p>/; }; /^$/ { s,$,</p><p>,; }; $ { s,$,</p>, };' description.txt)
884 $ECHOCOMMAND "Starting to generate page"
886 $BPGALLERY_HEAD_FUNCTION > ${INDEXDOCUMENT}
887 $BPGALLERY_DESCRIPTION_FUNCTION >> ${INDEXDOCUMENT}
889 $ECHOCOMMAND "Adding Captions"
892 if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
893 extra=__${MEDIUMDIRECTORY}
896 $FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | $SORTCOMMAND -g | while read filename; do filename=${filename#./}; if [ -r captions.txt ]; then caption=$($GREPCOMMAND -E "^$filename " captions.txt); caption=${caption#* }; else caption=""; fi; if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then link=${PAGESDIRECTORY}$(bpgallery_escape_url "${filename}${extra}.html"); elif [ $GENERATEPAGESFORFULLSIZE != 0 ]; then link=${PAGESDIRECTORY}$(bpgallery_escape_url "${filename}.html"); else link=$(bpgallery_escape_url "$filename"); fi; filename=$(bpgallery_escape_url "$filename"); $BPGALLERY_THUMBSLINE_FUNCTION; done >> ${INDEXDOCUMENT}
898 $BPGALLERY_TAIL_FUNCTION >> ${INDEXDOCUMENT}
900 $ECHOCOMMAND "Finished generating the page"
901 $ECHOCOMMAND "Generating stylesheet"
904 MAXHEIGHT=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 $IDENTIFYCOMMAND -format "%h\n" | $GREPCOMMAND -v "^$" | $SORTCOMMAND -g -r | $HEADCOMMAND -n 1)
905 MAXWIDTH=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 $IDENTIFYCOMMAND -format "%w\n" | $GREPCOMMAND -v "^$" | $SORTCOMMAND -g -r | $HEADCOMMAND -n 1)
909 # add a bit to the maxheight for the size of the caption
910 MAXHEIGHT=$((MAXHEIGHT+$CAPTIONHEIGHT))
912 $BPGALLERY_STYLESHEET_FUNCTION > style.css
914 $ECHOCOMMAND "All done"
916 if [[ $OUTPUTHTML != 0 ]]; then
917 $ECHOCOMMAND "</pre>"