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