Up version for release
[bpgallery.git] / bpgallery.sh
1 #!/usr/bin/env bash
2
3 # bpgallery.sh - builds a simple 'gallery' from a collection of images
4 # Copyright (C) 2004 Brett Parker <iDunno@sommitrealweird.co.uk>
5 #
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.
10
11 # This program is distributed in the hope that it will be useful,
12 # but 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.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 set -f
21
22 VERSION="1.1.1"
23
24 function bpgallery_default_head() {
25 cat <<END
26 <?xml version="1.0"?>
27 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd">
28 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
29 <head>
30         <title>${TITLE}</title>
31         <link rel="stylesheet" href="style.css" type="text/css" />
32 </head>
33 <body>
34 END
35 }
36
37 declare -rf bpgallery_default_head
38
39 function bpgallery_default_description() {
40 cat <<END
41         <h1>${TITLE}</h1>
42         ${DESCRIPTION}
43 END
44 }
45
46 declare -rf bpgallery_default_description
47
48 function bpgallery_default_thumbsline() {
49 if [[ -z $caption ]]; then
50         caption_alt=Unknown
51 else
52         caption_alt=$caption
53 fi
54 cat << END
55 <div class="thumbnail"><a href="$link"><img src="icons/$filename" alt="$caption_alt" /></a><div class="caption">$caption</div></div>
56 END
57 }
58
59 declare -rf bpgallery_default_thumbsline
60
61 function bpgallery_default_tail() {
62 cat << END
63 </body>
64 </html>
65 END
66 }
67
68 declare -rf bpgallery_default_tail
69
70 function bpgallery_default_stylesheet() {
71 cat <<END
72 body {
73         background: white;
74         color: black;
75         font-family: sans-serif;
76         font-size: 10pt;
77 }
78
79 div.thumbnail {
80         float: left;
81         padding: 20px;
82         border: 0px;
83         width: ${WIDTH}px;
84         height: ${MAXHEIGHT}px;
85 }
86
87 div.caption {
88         width: 100%;
89         text-align: center;
90         font-weight: bold;
91 }
92
93 div.navigation {
94         margin: 0;
95 }
96
97 div.navigation ul {
98         display: inline;
99         margin: 0;
100         padding: 0;
101         text-align: center;
102 }
103
104 div.navigation ul li {
105         display: inline;
106         margin: 2em;
107 }
108
109 a {
110         border: 0px;
111 }
112
113 img {
114         border: 0px;
115 }
116 END
117 }
118
119 declare -rf bpgallery_default_stylesheet
120
121 function bpgallery_default_page() {
122         $BPGALLERY_HEAD_FUNCTION
123
124         linkstart=""
125         linkend=""
126
127         if [[ ! -z $linklocation ]]; then
128                 linkstart="<a href='$linklocation'>"
129                 linkend="</a>"
130         fi
131         
132         cat <<END
133 <h1>${caption}</h1>
134 <div class="navigation">
135         <ul>
136                 <li><a href='${INDEXDOCUMENT}'>Thumbnails</a></li>
137 END
138         if [[ ! -z $previouspage ]]; then
139                 $ECHOCOMMAND "<li><a href='${previouspage}'>Previous</a></li>"
140         else
141                 $ECHOCOMMAND "<li>Previous</li>"
142         fi
143
144         if [[ ! -z $nextpage ]]; then
145                 $ECHOCOMMAND "<li><a href='${nextpage}'>Next</a></li>"
146         else
147                 $ECHOCOMMAND "<li>Next</li>"
148         fi
149 cat <<END
150         </ul>
151 </div>
152 <div class="mainimage">
153         ${linkstart}<img src="${filename}" alt="${caption}" />${linkend}
154 </div>
155 END
156         $BPGALLERY_TAIL_FUNCTION
157 }
158
159 declare -rf bpgallery_default_page
160
161 function bpgallery_escape_url() {
162         temp=$1
163         temp=${temp//\%/%25}
164         temp=${temp//:/%3A}
165         temp=${temp//;/%3B}
166         temp=${temp// /%20}
167         temp=${temp//$/%24}
168         temp=${temp//&/%26}
169         temp=${temp//+/%2B}
170         temp=${temp//,/%2C}
171         temp=${temp//\//%2F}
172         temp=${temp//=/%3D}
173         temp=${temp//\?/%3F}
174         temp=${temp//@/%40}
175         temp=${temp//\"/%22}
176         $ECHOCOMMAND $temp
177 }
178
179 declare -rf bpgallery_escape_url
180
181 if [[ ! -z ${BPGALLERY_THEME} ]] ; then
182         declare -r BPGALLERY_THEME
183 fi
184
185 if [[ ! -z ${TITLE} ]] ; then
186         declare -r TITLE
187 fi
188
189 if [[ -e /usr/local/etc/bpgallery/config ]] ; then
190         . /usr/local/etc/bpgallery/config 2>/dev/null
191 fi
192
193 if [[ -e /etc/bpgallery/config ]] ; then
194         . /etc/bpgallery/config 2>/dev/null
195 fi
196
197 if [[ -e $HOME/.bpgallery.rc ]]; then
198         . $HOME/.bpgallery.rc 2>/dev/null
199 fi
200
201 if [[ -e $1 && -d $1 && -e $1/.bpgallery.rc ]]; then
202         . $1/.bpgallery.rc 2>/dev/null
203 fi
204
205 if [[ -z ${BPGALLERY_THEME} ]]; then
206         BPGALLERY_THEME=default
207 fi
208
209 if [[ ! -z ${BPGALLERY_THEME_DIR} ]] && \
210         [[ -e ${BPGALLERY_THEME_DIR}/${BPGALLERY_THEME} ]]; then
211         . ${BPGALLERY_THEME_DIR}/${BPGALLERY_THEME} 2>/dev/null
212 elif [[ -e $HOME/.bpgallery.themes/${BPGALLERY_THEME} ]]; then
213         . $HOME/.bpgallery.themes/${BPGALLERY_THEME} 2>/dev/null
214 elif [[ -e /usr/local/etc/bpgallery/themes/${BPGALLERY_THEME} ]]; then
215         . /usr/local/etc/bpgallery/themes/${BPGALLERY_THEME} 2>/dev/null
216 elif [[ -e /etc/bpgallery/themes/${BPGALLERY_THEME} ]]; then
217         . /etc/bpgallery/themes/${BPGALLERY_THEME} 2>/dev/null
218 fi
219
220 if [[ -z $TITLE ]]; then 
221         TITLE="Photo Gallery"
222 fi
223
224 if [[ -z $CONVERTTOOL ]]; then
225         CONVERTTOOL=convert
226 fi
227
228 if [[ -z $FINDCOMMAND ]]; then
229         FINDCOMMAND=find
230 fi
231
232 if [[ -z $XARGSCOMMAND ]]; then
233         XARGSCOMMAND=xargs
234 fi
235
236 if [[ -z $ECHOCOMMAND ]]; then
237         ECHOCOMMAND=echo
238 fi
239
240 if [[ -z $SORTCOMMAND ]]; then
241         SORTCOMMAND=sort
242 fi
243
244 if [[ -z $IDENTIFYCOMMAND ]]; then
245         IDENTIFYCOMMAND=identify
246 fi
247
248 if [[ -z $HEADCOMMAND ]]; then
249         HEADCOMMAND=head
250 fi
251
252 if [[ -z $GREPCOMMAND ]]; then
253         GREPCOMMAND=grep
254 fi
255
256 if [[ -z $SEDCOMMAND ]]; then
257         SEDCOMMAND=sed
258 fi
259
260 if [[ -z $WIDTH ]]; then
261         WIDTH=100
262 fi
263
264 if [[ -z $IMAGEEXTENSIONS ]]; then
265         IMAGEEXTENSIONS="jpeg jpg gif png";
266 fi
267
268 if [[ -z $WCCOMMAND ]]; then
269         WCCOMMAND="wc -l"
270 fi
271
272 if [[ -z $CAPTIONHEIGHT ]]; then
273         CAPTIONHEIGHT=75
274 fi
275
276 if [[ -z $OUTPUTHTML ]]; then
277         OUTPUTHTML=0
278 fi
279
280 if [[ -z $GENERATEPAGESFORFULLSIZE ]]; then
281         GENERATEPAGESFORFULLSIZE=0
282 fi
283
284 if [[ -z $GENERATEPAGESFORMEDIUMSIZE ]]; then
285         GENERATEPAGESFORMEDIUMSIZE=1
286 fi
287
288 if [[ -z $MEDIUMWIDTH ]]; then
289         MEDIUMWIDTH=400
290 fi
291
292 if [[ -z $INDEXDOCUMENT ]]; then
293         INDEXDOCUMENT=index.html
294 fi
295
296 if declare -F "bpgallery_${BPGALLERY_THEME}_page" > /dev/null ; then
297         BPGALLERY_PAGE_FUNCTION="bpgallery_${BPGALLERY_THEME}_page"
298 else
299         BPGALLERY_PAGE_FUNCTION="bpgallery_default_page"
300 fi
301
302 if declare -F "bpgallery_${BPGALLERY_THEME}_head" > /dev/null ; then
303         BPGALLERY_HEAD_FUNCTION="bpgallery_${BPGALLERY_THEME}_head"
304 else
305         BPGALLERY_HEAD_FUNCTION="bpgallery_default_head"
306 fi
307
308 if declare -F "bpgallery_${BPGALLERY_THEME}_description" > /dev/null ; then
309         BPGALLERY_DESCRIPTION_FUNCTION="bpgallery_${BPGALLERY_THEME}_description"
310 else
311         BPGALLERY_DESCRIPTION_FUNCTION="bpgallery_default_description"
312 fi
313
314 if declare -F "bpgallery_${BPGALLERY_THEME}_thumbsline" > /dev/null ; then
315         BPGALLERY_THUMBSLINE_FUNCTION="bpgallery_${BPGALLERY_THEME}_thumbsline"
316 else
317         BPGALLERY_THUMBSLINE_FUNCTION="bpgallery_default_thumbsline"
318 fi
319
320 if declare -F "bpgallery_${BPGALLERY_THEME}_tail" > /dev/null ; then
321         BPGALLERY_TAIL_FUNCTION="bpgallery_${BPGALLERY_THEME}_tail"
322 else
323         BPGALLERY_TAIL_FUNCTION="bpgallery_default_tail"
324 fi
325
326 if declare -F "bpgallery_${BPGALLERY_THEME}_stylesheet" > /dev/null ; then
327         BPGALLERY_STYLESHEET_FUNCTION="bpgallery_${BPGALLERY_THEME}_stylesheet"
328 else
329         BPGALLERY_STYLESHEET_FUNCTION="bpgallery_default_stylesheet"
330 fi
331
332 FINDIMAGESOPTIONS=""
333
334 for imageext in $IMAGEEXTENSIONS; do
335         FINDIMAGESOPTIONS=$FINDIMAGESOPTIONS' -o -type f -iname '*.$imageext' -print0'
336 done
337
338 FINDIMAGESOPTIONS=${FINDIMAGESOPTIONS## -o }
339 FINDIMAGESOPTIONS='-maxdepth 1 '${FINDIMAGESOPTIONS}
340
341 function usage() {
342 cat <<END
343 Usage:
344   $0 [--help|--version|<path to images>]
345
346     --help
347         displays this help screen
348     --version
349         displays the version and exits
350
351 This can also takes some environment variables, these will use defaults if not
352 set.
353
354         TITLE
355             the title of the gallery
356
357         WIDTH
358             the width to make the icons
359
360         MEDIUMWIDTH
361             set the width of images in the medium size pages
362
363         BPGALLERY_THEME
364             set the theme to use (described below)
365
366         BPGALLERY_THEME_DIR
367             set an extra location to look for themes
368
369         OUTPUTHTML
370             sets the script output to be wrapped in a <pre> block
371
372         GENERATEPAGESFORMEDIUMSIZE
373             generate medium sized images and pages
374
375         GENERATEPAGESFORFULLSIZE
376             decide wether to generate pages for the full size images or not
377
378         INDEXDOCUMENT
379             name of the index page (e.g. index.html)
380
381 Example:
382         TITLE="My Funky Gallery" WIDTH=200 INDEXDOCUMENT="welcome.html" GENERATEPAGESFORFULLSIZE=1 GENERATEPAGESFORMEDIUMSIZE=1 MEDIUMWIDTH=400 $0 /path/to/image/folder
383 END
384 }
385
386 function version() {
387 cat <<END
388 Version: $VERSION
389 END
390 }
391
392 function generate_resized_images() {
393         $ECHOCOMMAND "Generating $2"
394         currentimage=0
395         totalimages=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | $WCCOMMAND);
396         imagestoupdate=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | while read filename; do filename=${filename//\"/\\\"}; if [ ! -r "$2/$filename" ] || [ "$filename" -nt "$2/$filename" ] || [ $($IDENTIFYCOMMAND -format "%w" "$2/$filename") -ne $1 ]; then $ECHOCOMMAND $filename; fi; done | $WCCOMMAND)
397         
398         if [ $totalimages -eq 0 ]; then
399                 # might as well exit at this point - there are no pictures
400                 $ECHOCOMMAND "No images for the gallery - exiting."
401                 exit 64
402         else
403                 # check if the directory exists and create it other wise
404                 if [ ! -d $2 ]; then
405                         mkdir $2
406                 fi
407
408                 if [ ! -w $2 ]; then
409                         $ECHOCOMMAND "Can't write to $2 directory, exiting"
410                         exit 16
411                 fi
412         fi
413
414         if [ $totalimages -eq $imagestoupdate ]; then
415                 $ECHOCOMMAND "Regenerating all $2"
416         elif [ $imagestoupdate -eq 0 ]; then
417                 $ECHOCOMMAND "No Updated $2, not regenerating"
418                 return
419         else
420                 $ECHOCOMMAND "Generating $imagestoupdate of $totalimages $2"
421         fi
422         
423         $FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | while read filename; do tempfilename=${filename//\"/\\\"/}; if [ ! -r "$2/$tempfilename" ] || [ "$tempfilename" -nt "$2/$tempfilename" ] || [ $($IDENTIFYCOMMAND -format "%w" "$2/$filename") -ne $1 ]; then $ECHOCOMMAND -n $filename; $ECHOCOMMAND -n -e "\000"; fi; done | $XARGSCOMMAND -0 --verbose --max-procs=4 -I {} $CONVERTTOOL -resize $1 '{}' $2/'{}' 2>&1 | while read throwout; do $ECHOCOMMAND done: $currentimage/$imagestoupdate images; currentimage=$((currentimage+1)); done
424         $ECHOCOMMAND done: $imagestoupdate/$imagestoupdate images
425         $ECHOCOMMAND "Completed generating $2 for $totalimages images"
426 }
427
428 function generate_thumbs() {
429         generate_resized_images $WIDTH icons
430 }
431
432 function generate_medium() {
433         generate_resized_images $MEDIUMWIDTH medium
434 }
435
436 function generate_pages() {
437         $ECHOCOMMAND "Generating Pages"
438         previouspage=""
439         currentpage=""
440         nextpage=""
441         previousimage=""
442         currentimage=""
443         nextimage=""
444         extra=""
445         extradir=""
446         addlinks=0
447         
448         if [ ! -z $1 ]; then
449                 extra=$1
450         fi
451
452         if [ ! -z $2 ]; then
453                 extradir=$2/
454                 addlinks=1
455         fi
456
457         if [ -z $2 ] && [[ $GENERATEPAGESFORMEDIUMSIZE != 0 ]]; then
458                 addlinks=2
459         fi
460         
461         $FINDCOMMAND . $FINDIMAGESOPTIONS | \
462         $XARGSCOMMAND -0 -I {} $ECHOCOMMAND {} | \
463         $SORTCOMMAND -g | \
464         while read imagefilename; do
465                 previousimage=$currentimage
466                 currentimage=$nextimage
467                 nextimage=${imagefilename#./}
468                 addlink=""
469                 
470                 if [[ $GENERATEPAGESFORFULLSIZE != 0 ]]; then
471                         if [[ $addlinks == 1 ]]; then
472                                 addlink=${currentimage}.html
473                         else
474                                 addlink=${currentimage}${extra}.html
475                         fi
476                 else
477                         addlink=${currentimage}
478                 fi
479
480                 previouspage=$currentpage
481                 currentpage=$nextpage
482                 if [[ $addlinks == 1 ]]; then
483                         nextpage=${nextimage}${extra}.html
484                 else
485                         nextpage=${nextimage}.html
486                 fi
487                 filename=${extradir}${currentimage}
488                 if [ "x$currentpage" != "x" ]; then
489                         generate_general_page "$previouspage" "$currentpage" "$nextpage" $addlink
490                 fi
491                 $ECHOCOMMAND $nextimage
492         done | tail -n 2 | (
493                 read previouspage
494                 read currentpage
495                 addlink=""
496
497                 if [[ $GENERATEPAGESFORFULLSIZE != 0 ]]; then
498                         if [[ $addlinks == 1 ]]; then
499                                 addlink=${currentpage}.html
500                         else
501                                 addlink=${currentpage}${extra}.html
502                         fi
503                 else
504                         addlink=${currentpage}
505                 fi
506
507                 filename=${extradir}${currentpage}
508                 if [[ $addlinks == 1 ]]; then
509                         currentpage=${currentpage}${extra}.html
510                         previouspage=${previouspage}${extra}.html
511                 else
512                         currentpage=${currentpage}.html
513                         previouspage=${previouspage}.html
514                 fi
515                 nextpage=""
516                 generate_general_page "$previouspage" "$currentpage" "" $addlink
517         )
518 }
519
520 function generate_medium_pages() {
521         generate_pages __medium medium
522 }
523
524 function generate_general_page() {
525
526         if [[ -z $1 ]]; then
527                 previouspage=""
528         fi
529
530         if [[ -z $2 ]]; then
531                 currentpage=""
532                 return
533         fi
534
535         if [[ -z $3 ]]; then
536                 nextpage=""
537         fi
538
539         if [[ ! -z $4 ]]; then
540                 linklocation=$4
541         fi
542
543         if [ -r captions.txt ]; then
544                 imagefilename=${filename##*/}
545                 caption=$($GREPCOMMAND -E "^${imagefilename}    " captions.txt); caption=${caption#*    }
546         else
547                 caption=""
548         fi
549         
550         $BPGALLERY_PAGE_FUNCTION > "$currentpage"
551 }
552
553 if [[ $OUTPUTHTML != 0 ]]; then
554         $ECHOCOMMAND "<pre>"
555 fi
556
557 if [[ -z $1 ]]; then
558         $ECHOCOMMAND "No path given"
559         usage
560         exit 1
561 fi
562
563 if [[ "$1" == "--help" || "$1" == "-h" ]]; then
564         usage
565         exit 0
566 fi
567
568 if [[ "$1" == "--version" || "$1" == "-v" ]]; then
569         version
570         exit 0
571 fi
572
573 if [[ ! -d $1 ]]; then
574         $ECHOCOMMAND "$1 is not a directory"
575         usage
576         exit 2
577 fi
578
579 cd "$1"
580
581 if ( ! $FINDCOMMAND . $FINDIMAGESOPTIONS > /dev/null 2>/dev/null ); then
582         $ECHOCOMMAND "$1 does not contain any images. Quitting."
583         exit 4
584 fi
585
586 if [ ! -w . ]; then
587         $ECHOCOMMAND "Can't write to images directory, exiting"
588         exit 8
589 fi
590
591 if [ -e ${INDEXDOCUMENT} ] && [ ! -w ${INDEXDOCUMENT} ]; then
592         $ECHOCOMMAND "Can't write ${INDEXDOCUMENT}, exiting"
593         exit 8
594 fi
595
596 if [ -e style.css ] && [ ! -w style.css ]; then
597         $ECHOCOMMAND "Can't write style.css, exiting"
598         exit 8
599 fi
600
601 generate_thumbs
602
603 if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
604         generate_medium
605         generate_medium_pages
606 fi
607
608 if [ $GENERATEPAGESFORFULLSIZE != 0 ]; then
609         if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
610                 generate_pages __medium
611         else
612                 generate_pages
613         fi
614 fi
615
616 if [ -r description.txt ] ; then
617         DESCRIPTION=$($SEDCOMMAND -e '1 { s/^/<p>/; }; /^$/ { s,$,</p><p>,; }; $ { s,$,</p>, };' description.txt)
618 else
619         DESCRIPTION=""
620 fi
621
622
623 $ECHOCOMMAND "Starting to generate page"
624
625 $BPGALLERY_HEAD_FUNCTION > ${INDEXDOCUMENT}
626 $BPGALLERY_DESCRIPTION_FUNCTION >> ${INDEXDOCUMENT}
627
628 $ECHOCOMMAND "Adding Captions"
629
630 extra=""
631 if [ $GENERATEPAGESFORMEDIUMSIZE != 0 ]; then
632         extra=__medium
633 fi
634
635 $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=$(bpgallery_escape_url "${filename}${extra}.html"); elif [ $GENERATEPAGESFORFULLSIZE != 0 ]; then link=$(bpgallery_escape_url "${filename}.html"); else link=$(bpgallery_escape_url "$filename"); fi; filename=$(bpgallery_escape_url "$filename"); $BPGALLERY_THUMBSLINE_FUNCTION; done >> ${INDEXDOCUMENT}
636
637 $BPGALLERY_TAIL_FUNCTION >> ${INDEXDOCUMENT}
638
639 $ECHOCOMMAND "Finished generating the page"
640 $ECHOCOMMAND "Generating stylesheet"
641 cd icons
642
643 MAXHEIGHT=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 $IDENTIFYCOMMAND -format "%h\n" | $GREPCOMMAND -v "^$" | $SORTCOMMAND -g -r | $HEADCOMMAND -n 1)
644 MAXWIDTH=$($FINDCOMMAND . $FINDIMAGESOPTIONS | $XARGSCOMMAND -0 $IDENTIFYCOMMAND -format "%w\n" | $GREPCOMMAND -v "^$" | $SORTCOMMAND -g -r | $HEADCOMMAND -n 1)
645
646 cd ..
647
648 # add a bit to the maxheight for the size of the caption
649 MAXHEIGHT=$((MAXHEIGHT+$CAPTIONHEIGHT))
650
651 $BPGALLERY_STYLESHEET_FUNCTION > style.css
652
653 $ECHOCOMMAND "All done"
654
655 if [[ $OUTPUTHTML != 0 ]]; then
656         $ECHOCOMMAND "</pre>"
657 fi