1: magical incantation finds Perl as long as it's in the user's path 2eval 'exec perl -wS $0 ${1+"$@"}' 3 if 0; 4 5############################################################################ 6# Please change this accordingly if you change the DESTDIR in the tarball 7# distribution Makefile or the --prefix of the RPM installation 8$LIBDIR = "/usr/local/lib/igal2"; 9# for example if you make DESTDIR=/usr then $LIBDIR="/usr/lib/igal2" 10############################################################################ 11# 12# A short note from Eric Pop the developer of the "old" igal version: 13# Note to do-it-yourselvers and Computer Science types: the IGAL code is 14# UGLY. I'm am amateur programmer, not a CS type. If my scrappy code runs 15# and gives the right results, I'm happy. If others find it useful, that's 16# wonderful. I hope my comments can help decipher the mess below a bit. I 17# wrote IGAL partly because I wanted another excuse to learn Perl (it's 18# useful for my research too) and because other image gallery generators 19# had hairy dependencies and didn't do what I needed. So... my apologies 20# if the spaghetti below makes you cringe. It works for me, so I don't 21# really have plans (or time) to clean it up. 22# 23############################################################################ 24# If you KNOW you have the ImageMagick package installed (e.g commands like 25# identify and convert) then setting this equal to 1 may speed up the code a 26# bit (igal will stop checking for these commands every time it runs) 27# 28$HAVEIM = 0; 29############################################################################ 30# If you KNOW you have the libjpeg stuff installed (e.g commands like cjpeg, 31# djpeg and pnmscale) then setting this equal to 1 may speed up the code a 32# bit (igal will stop checking for these commands every time it runs) 33# 34$HAVELJ = 0; 35############################################################################ 36 37# This is IGAL version 2.2, an online Image GALlery generator. 38# Copyright (C) 2000 Eric Pop, 2003 Wolfgang Trexler 39# This version was enhanced by Wolfgang Trexler (wt) Apr. 2003 - May 2016 40# 41# This program is free software; you can redistribute it and/or modify 42# it under the terms of the GNU General Public License as published by 43# the Free Software Foundation; either version 2 of the License, or 44# (at your option) any later version. 45# 46# This program is distributed in the hope that it will be useful, 47# but WITHOUT ANY WARRANTY; without even the implied warranty of 48# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 49# GNU General Public License for more details. 50# 51# You should have received a copy of the GNU General Public License 52# along with this program; if not, write to the Free Software 53# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 54# 55# Author: Eric Pop, Dept. of Electrical Engineering, Stanford University 56# Email: epop@stanford.edu 57# Enhancements were done by: Wolfgang Trexler, Alexander Zangerl 58# EMail: wt-igal@trexler.at 59 60use FileHandle; 61use Getopt::Long; 62use POSIX qw(ceil floor); 63# Check if EXIF Tool library is installed 64$ExifTool = eval "use Image::ExifTool; 1" ? 1 : 0; 65 66 67# some constants 68$VERSION = "2.2"; 69$Getopt::Long::ignorecase = 0; 70$itile = "tile.png"; 71$slidetemplate = "slidetemplate2.html"; 72$indextemplate = "indextemplate2.html"; 73$csstemplate = "igal2.css"; 74$directorylinefile = "directoryline2.html"; 75$captionfile = ".captions"; 76$userigaldir = "$ENV{'HOME'}/.igal2"; 77$thumbprefix = ".thumb_"; 78$slideprefix = ".slide_"; 79$destback = ""; 80STDOUT->autoflush("1"); 81 82# default command-line argument values 83$opt_a = "0"; # to write image size under thumbnails in index page 84$opt_c = "0"; # -c to use user-supplied captions 85$opt_C = "0"; # same as -c, but preserve image names as captions 86$opt_d = "."; # look in current directory "." 87$opt_e = "0"; # write EXIF information under image 88$opt_f = "0"; # -f to force thumbnail regeneration 89$opt_h = "0"; 90$opt_i = "index.html"; # name of the main thumbnail index file 91$opt_k = "0"; # -k for the captions to also be used as slide titles 92$opt_m = ""; # -m Apply a watermark to each image 93$opt_n = "0"; # -n to use image file names for the .html files 94$opt_o = ""; # -o dir specifies alternate prefix for target links 95$opt_p = "3"; # cellpadding value for the thumbnail index tables 96$opt_r = "0"; # -r to omit the film reel effect altogether 97$opt_s = "0"; # -s to make no slides, just thumbnail links to images 98$opt_t = "21"; # height of the .tile.png tiled image 99$opt_u = "0"; # write captions under thumbnails on index page 100$opt_w = "5"; # index rows are 5 images wide by default 101$opt_x = "0"; # -x to omit the image count from the caption 102$opt_y = "0"; # max height of a thumbnail (defaults to 75 below) 103$opt_ad = "0"; # write out only dimensions 104$opt_as = "0"; # write out only file size 105$opt_bigy = "0"; # max height of the slides. use if images are huge. 106$opt_con = ""; # options to be passed to convert or cjpeg 107$opt_help = "0"; # displays brief usage message; same as -h 108$opt_www = "0"; # makes everything world-readable 109$opt_xy = "0"; # scale thumbs to n pixels in their longer dimension 110$opt_dest = ""; # Destination directory of helper files 111$opt_AddSubdir = "0"; # Add subdirectories to index.html file 112$opt_pagination = "0"; # maximum number of images on one page, zero means no pagination 113 114$usage = <<"END_OF_USAGE"; 115This is iGal2 $VERSION an HTML image slide show generator. 116Syntax: igal [-option -option ...] 117Options: -a write image sizes under thumbnails on index page 118 -c first generate and then use captions 119 -C like -c, but preserve file names as captions 120 -d <dir> operate on files in directory <dir> (.) 121 -e write EXIF information under image (needs Image::ExifTool) 122 -f force thumbnail regeneration 123 -h displays this brief help; same as --help 124 -i <file> name of the main thumbnail index file (index.html) 125 -k use the image captions for the HTML slide titles 126 -m <file> Automatically add watermark to each image 127 -n use image file names for the HTML slide files 128 -p <n> cellpadding value of thumbnail index tables (3) 129 -r omit the film reel effect altogether 130 -s make no HTML slides, link thumbnails to images 131 -t <n> height of the film reel tiled image (21) 132 -u write captions under thumbnails on index page 133 -w <n> rows in thumbnail index are <n> images wide (5) 134 -x omit the image count from the captions 135 -y <n> scale all thumbnails to the same height <n> (75) 136 --ad like -a, but write only the image dimensions 137 --as like -a, but write only the file size (in kbytes) 138 --bigy <n> like -y, use it if you have very large image files 139 --con <> options to pass to convert or cjpeg (e.g. -quality N) 140 --help displays this brief help; same as -h 141 --www make all iGal files world-readable 142 --xy <n> scale thumbs to <n> pixels in their longer dimension 143 ------------- N E W F U N C T I O N S -------------------------- 144 --dest <dir> Destination directory for the helper files 145 (thumbnails, slides, etc.) igal generates. This is 146 relative to the operative directory -d and has to be 147 one level below (.) 148 --AddSubdir If igal finds further directories beneath your image 149 directory -d, it will generate HTML Links in the 150 index file (index.html) to this directories. 151 Default is (off). Directories given with --dest or 152 starting with a "." will be ignored. 153 Note: igal will not work recursively, it just adds 154 HTML links to the directories below. 155 -m <file> Automatically add watermark to each image - this 156 works well with a transparent .gif, but anything 157 can be used - edit the "composite" line later on 158 to adjust visibility/position of mark if required 159 Originals will be left with a .unmarked extension 160 -o <dir> Root URL of alternate location for the links to full 161 size images. Use this if your indexes will be in 162 a different location/server from the back end images 163 --pagination <n> Maximum number of images on one page. 164 If the given number of images is reached a new page 165 is started. Pagination number <n> should be a multiple 166 of parameter -w (default 5). 167 Default 0 - means no pagination at all. 168Note: default values are given in parentheses (where applicable). 169Authors: Wolfgang Trexler <wt-igal\@trexler.at> 170 Eric Pop <epop\@stanford.edu> (original igal) 171 contributions: 172 Stewart Addison <contactsxa\@gmail.com>, Riku Kalinen, 173 Alexander Zangerl 174URL: http://igal.trexler.at/ 175END_OF_USAGE 176 177# store command-line options upfront to write in the index <HEAD> 178@igal_options = @ARGV; 179 180# process command-line arguments (overriding defaults above) 181GetOptions('a','c','C','d=s','e','f','h','i=s','k','m=s','n','o=s', 182 'p=i','r','s','t=i','u','w=i','x','y=i','ad','as', 183 'bigy=i', 'con=s','help','im','www','xy=i', 'dest=s', 184 'AddSubdir', 'pagination=s') or die "$usage"; 185 186die $usage if ($opt_help or $opt_h); 187# deal with the competing -y and --xy options 188if (($opt_y == 0) and ($opt_xy == 0)) { 189 $opt_y = 75; # default, if neither -y nor --xy is specified 190} else { 191 $opt_f = "1"; # if either is specified, force thumbnail regeneration 192} 193die "Please only specify one of the -y and --xy options\n" if ($opt_y and $opt_xy); 194# other error (sanity) checks 195die "Please enter nonnegative thumbnail dimensions\n" if (($opt_y < 0) or ($opt_xy < 0)); 196die "Please enter a nonnegative cellpadding value\n" if ($opt_p < 0); 197die "Please choose at least one image per index row\n" if ($opt_w <= 0); 198die "Please enter a nonnegative tiled image height\n" if ($opt_t < 0); 199die "Please enter a nonnegative pagination value\n" if ($opt_pagination < 0); 200$opt_o = "$opt_o/" if ( $opt_o ); 201 202die "Critical failure: Lib Image::ExifTool not install but EXIF Tags (option -e) requested\n" if (($ExifTool == 0) and ($opt_e)); 203 204# strip any unnecessary slashes from the end of the given $opt_d directory 205$opt_d =~ s/\/$//; 206 207# let users store their templates in a $HOME/.igal directory, if it exists, 208# instead of the site-wide /usr/local/lib/igal (from line 8 up top) 209$LIBDIR = $userigaldir if ((-r $userigaldir) && (-d $userigaldir)); 210 211# load up image files from $opt_d into array @imgfiles 212opendir DIR, $opt_d or die "Can't open directory $opt_d\n"; 213 214# find and read all jp(e)g, gif and png files 215@jpgfiles = grep((!/^\./ and /\.jpe?g$/i), readdir DIR); 216rewinddir DIR; # this is CRUCIAL here!!! 217@giffiles = grep((!/^\./ and /\.gif$/i), readdir DIR); 218rewinddir DIR; # this is CRUCIAL here!!! 219@pngfiles = grep((!/^\./ and /\.png$/i), readdir DIR); 220@imgfiles = @jpgfiles; 221push(@imgfiles, @giffiles); 222push(@imgfiles, @pngfiles); 223 224@imgfiles = sort @imgfiles; # sort alphabetically, by file name 225$njpg = @jpgfiles; 226$nfiles = @imgfiles; # how many total image files i've loaded 227 228die "Can't find any image files in directory $opt_d\n" if ($nfiles == 0); 229 230# find and read all directories (except beginning with . and igal destination) for later use 231if ($opt_AddSubdir) { 232 rewinddir DIR; 233 foreach $file (readdir DIR) { 234 if (-d "$opt_d/$file" && !($file =~ /^\./) && !($file =~ /$opt_dest/)) { 235 push(@directories, $file); 236 } 237 } 238 if (@directories) { 239 @directories = sort @directories; # sort alphabetically, by name 240 } else { 241 print "Information: Option --AddSubdir is set, but can't find any matching subdiretories!\n"; 242 } 243 244 245} 246 247closedir DIR; 248 249# Store image extensions 250@imgext = (); @captions = (); 251 252foreach $file (@imgfiles) { 253 # store image captions & extensions in separate arrays along the way 254 $file =~ m/(^.*)\.(\w{3,4})$/; 255 push(@captions, $1); 256 push(@imgext, $2); 257} 258 259 260# wt 08.04.03: check for destination directory of igal files, and create it if necessary 261$opt_dest =~ s/\/$//; # strip any unnecessary slashes from the end of the given $opt_dest directory 262if (length $opt_dest > 0) { 263 if ($opt_dest =~ m/(\/|\\|\#|<|>|%|\"|\s)/) { 264 die "\nYour destination directory ($opt_dest) contains a character ($1) which\nis not allowed inside an URL. URIs may not contain delimiters such as \\, <, >, #, %, \" or \nwhite space.\n\n"; 265 } 266 if (! -d "$opt_d/$opt_dest") { 267 mkdir "$opt_d/$opt_dest" or die "Can't create directory for igal files ($opt_d/$opt_dest) [$!]"; 268 } 269 print "Using directory $opt_d/$opt_dest for igal files (except for index.html)\n"; 270 $opt_dest = "$opt_dest/"; # Append / to directory for further use 271 $destback = "../"; # will be used in html later on to find the directory where images reside 272} 273 274 275# if the -c (or -C) option was supplied let user specify captions, else see below 276if ($opt_c or $opt_C) { 277 if (! -r "$opt_d/$opt_dest$captionfile") { 278 # create $captionfile file if it doesn't exist 279 print "Found $nfiles image files in directory $opt_d\n"; 280# die "Please select more files for your slide show!\n" if ($nfiles <= 1); 281 open(CAP,">$opt_d/$opt_dest$captionfile") or die "Can't create $opt_d/$opt_dest$captionfile file\n"; 282 print "Creating the $opt_dest$captionfile file...\n"; 283 print CAP "# This is igal's $captionfile file, first generated ", scalar localtime, ".\n"; 284 print CAP "# To the left of the separator are the image file names. Enter your captions\n# on the right side, one per line. The captions may include HTML tags.\n# To add any comments to this file or to exclude any images from the slide \n# show, add a # sign at the beginning of their respective lines. You may\n# also change the order of images in your slide show at this time.\n\n"; 285 for ($i = 0; $i < $nfiles; $i++) { 286 print CAP "$imgfiles[$i] ---- "; 287 print CAP "$captions[$i]" if $opt_C; 288 print CAP "\n"; 289 } 290 close(CAP); 291 die "Now edit the $opt_dest$captionfile file to your liking and rerun igal -c\n"; 292 } else { 293 # read in files specified in the .captions file 294 open(CAP,"$opt_d/$opt_dest$captionfile") or die "Can't open $opt_d/$opt_dest$captionfile file\n"; 295 @imgfiles = (); # reset arrays b/c we're rereading them 296 @captions = (); @imgext = (); $njpg = 0; 297 print "Reading the $captionfile file ... "; 298 while (defined($line = <CAP>)) { 299 chomp($line); $line =~ s/^\s*//; $line =~ s/\s*$//; 300 # only read lines with the ---- delimiter that don't start with # 301 if (($line =~ m/\w\s*----\s*/) && !($line =~ m/^\#/)) { 302 @arr = split(/\s*----\s*/,$line); 303 # first check image extensions 304 $temp = $arr[0]; $temp =~ s/^.*\.//; 305 push(@imgfiles,$arr[0]); 306 push(@imgext, $temp); 307 push(@arr,"") if (scalar @arr == 1); 308 push(@captions,$arr[1]); 309 $njpg++ if ($arr[0] =~ m/jpe?g/i); 310 } 311 } 312 close(CAP); 313 $nfiles = @imgfiles; 314 print "found $nfiles image files.\n"; 315 die "Please select more files for your slide show!\n" if ($nfiles < 1); 316 } 317} else { 318 print "Found $nfiles image files in directory $opt_d\n"; 319} 320 321# find out if the imagemagick commands exist 322$HAVEIM = (&exist("identify") and &exist("convert")) unless ($HAVEIM); 323print "\nWARNING: commands identify/convert missing!\nThe ImageMagick (imagemagick.org) or GraphicsMagick package with compatibility doesn't seem to be\ninstalled. Image dimensions will not be available in the generated HTML.\nOnly JPG images are supported... falling back onto cjpeg/djpeg/pnmscale.\n\n" unless ($HAVEIM); 324 325# find out if the libjpeg commands exist 326$HAVELJ = (&exist("cjpeg") and &exist("djpeg") &exist("pnmscale")) unless ($HAVELJ or ($njpg == 0) or $HAVEIM); 327print "\nWARNING: at least one of the commands \"cjpeg\", \"djpeg\" and \"pnmscale\" is not\ninstalled. You can find these at rpmfind.net (inside libjpeg and libgr-progs)\nor you can download the source code from:\n http://www.ijg.org/ and\n http://netpbm.sourceforge.net/\n\n" unless ($HAVELJ or ($njpg == 0) or $HAVEIM); 328 329# give up if no image processing commands can be found 330die "ERROR: the necessary image processing tools aren't installed on your system.\nPlease obtain them as specified above.\n\n" unless ($HAVEIM or $HAVELJ); 331 332# initialize the arrays that will hold image file sizes 333@xdim=(); @ydim=(); @isiz=(); 334 335# Jan 13, 2003: i played around w/the various ways in which convert can 336# resize images, i.e with -scale, -sample, -geometry (equivalent to -resize) 337# and lo and behold, i realized that igal will run MUCH faster when resizing 338# is done with -scale while quality is about same as with -geometry (in igal 339# 1.3 and earlier). using -sample gives me a bit more speed advantage but 340# is not worth using as the scaled-down output seems to be pretty poor. 341# here are some timed-runs on a directory w/some images: 342# * w/convert -sample (poor quality) 7.24 sec 343# * w/convert -scale (ok quality) 9.14 sec 344# * w/convert -resize (ok quality) 23.8 sec 345# * w/cjpeg/djpeg (ok quality) 20.1 sec 346# so from now on all convert -scale is used everywhere below because it seems 347# to be the clear winner for quality vs speed. 348 349# generate .thumbnails in the same directory with the original image files (or in the given --dest directory) 350# if they don't exist already or if the -f switch is given 351 352print "Creating thumbnails: "; 353for ($i = 0; $i < $nfiles; $i++) { 354 $file = $imgfiles[$i]; 355 $fullfile = "$opt_d/$file"; 356 die "Can't open $fullfile\n" unless (-r $fullfile); 357 $fullthumb = "$opt_d/$opt_dest$thumbprefix$file"; 358 if ((! -e $fullthumb) or $opt_f) { 359 if ($HAVEIM) { 360 $command = "convert $opt_con -scale x$opt_y \"$fullfile\" \"$fullthumb\""; 361 # opt_xy handling: determine dimensions and scale the bigger dimension 362 # Bug fixing code new since version 1.4.7 363 if ($opt_xy) { 364 $temp = `identify -ping -format \"\%wx\%h %b\" \"$fullfile\"`; 365 $temp =~ m/(\d+)x(\d+)\s([\d\.]+[mkb]*)/i; 366 $width = $1; $height = $2; $temp = $3; 367 if ($width > $height) { 368 $dimension = "$opt_xy" . "x"; 369 } else { 370 $dimension = "x" . "$opt_xy"; 371 } 372 $command = "convert $opt_con -scale $dimension \"$fullfile\" \"$fullthumb\""; 373 } 374 } else { 375 if ($imgext[$i] =~ m/(gif|png)/i) { 376 print "\nIgnoring $file: get ImageMagick (imagemagick.org) to process GIF and PNG files.\n"; 377 $command = 0; 378 } else { 379 $com1 = "djpeg \"$fullfile\""; 380 $com3 = "cjpeg $opt_con -outfile \"$fullthumb\""; 381 $scale = "pnmscale -ysize $opt_y"; 382 $scale = "pnmscale -xysize $opt_xy $opt_xy" if ($opt_xy); 383 $command = $com1 . " | " . $scale . " | " . $com3; 384 } 385 } 386 system("$command") if ($command); 387 print "$thumbprefix$file " if ($command); 388 } 389} 390print "... done!\n"; 391 392# determine image file sizes 393if ($HAVEIM && !($opt_bigy)) { 394 print "Determining image sizes "; 395 foreach $file (@imgfiles) { 396 $fullfile = "$opt_d/$file"; 397 $temp = `identify -ping -format \"\%wx\%h %b\" \"$fullfile\"`; 398 $temp =~ m/(\d+)x(\d+)\s([\d\.]+[mkb]*)/i; 399 push(@xdim,$1); push(@ydim,$2); $temp = $3; 400 # round nicely in kb if identify returned the size in bytes 401 $temp = sprintf ("%.1fk", $temp/1024) if ($temp =~ s/([\d\.]+)b*$/$1/i); 402 push(@isiz,$temp); 403 print "."; 404 } 405 print " done!\n"; 406} 407 408# scale down slides if the --bigy <n> option was given 409if ($opt_bigy and !($opt_s)) { 410 if ($HAVEIM) { 411 print "Scaling down big slides and determining new slide sizes: "; 412 @xdim=(); @ydim=(); @isiz=(); # reset image size arrays 413 } else { 414 print "Scaling down big slides: "; 415 } 416 for ($i = 0; $i < $nfiles; $i++) { 417 $file = $imgfiles[$i]; 418 $fullfile = "$opt_d/$file"; 419 die "Can't open $fullfile\n" unless (-r $fullfile); 420 $fullslide = "$opt_d/$opt_dest$slideprefix$file"; 421 if ((! -e $fullslide) or $opt_f) { 422 if ($HAVEIM) { 423 $command = "convert $opt_con -scale x$opt_bigy \"$fullfile\" \"$fullslide\""; 424 } else { 425 if ($imgext[$i] =~ m/(gif|png)/i) { 426 print "\nIgnoring $file: get ImageMagick (imagemagick.org) to process GIF and PNG files.\n"; 427 $command = 0; 428 } else { 429 $com1 = "djpeg \"$fullfile\""; 430 $com3 = "cjpeg $opt_con -outfile \"$fullslide\""; 431 $scale = "pnmscale -ysize $opt_bigy"; 432 $command = $com1 . " | " . $scale . " | " . $com3; 433 } 434 } 435 system("$command") if ($command); 436 print "$slideprefix$file " if ($command); 437 } 438 if ($HAVEIM) { 439 $temp = `identify -ping -format \"\%wx\%h %b\" \"$fullslide\"`; 440 $temp =~ m/(\d+)x(\d+)\s([\d\.]+[mkb]*)/i; 441 push(@xdim,$1); push(@ydim,$2); $temp = $3; 442 # round nicely in kb if identify returned the size in bytes 443 $temp = sprintf ("%.1fk", $temp/1024) if ($temp =~ s/([\d\.]+)b*$/$1/i); 444 push(@isiz,$temp); 445 } 446 } 447 print "... done!\n"; 448} 449 450if ( $opt_m ) { 451 # This is a fairly simple watermarking method - this could be made 452 # more complex ... 453 die "ImageMagick required for watermarking\n" if (! &exist("composite")); 454 die "Cannot open watermark file $opt_m" if ( ! -r $opt_m ); 455 print "Adding watermarks:"; 456 for ($i = 0; $i < $nfiles; $i++) { 457 $file = $imgfiles[$i]; 458 $original = "$file.unmarked"; 459 # If original exists, user has re-run the script - don't 460 # add a second watermark 461 if ( -r $original ) { 462 print " [$file already marked]"; 463 } else { 464 die "Can't open $file\n" unless (-r $file); 465 rename $file, $original || die "Failed to rename $file to $original"; 466 print " $file"; 467 # Could add '&& unlink $original' but wouldn't protect against reruns 468 system "composite -dissolve 33 -geometry +20+20 $opt_m $original $file"; 469 die "Failed to add watermark to $file" if ( ! -r $file ); 470 } 471 } 472 print "\nPre-watermarked files have been left with a .unmarked extension\n"; 473 print "You may wish to remove those before publishing the gallery\n"; 474} 475 476# create the individual slide show files 477if ($opt_s) { 478 print "Linking thumbnails directly to image files... Making no html slides.\n"; 479 if (! -e "$opt_d/$opt_dest$csstemplate") { 480 print "No CSS template file ... getting $LIBDIR/$csstemplate\n"; 481 die "$LIBDIR cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r $LIBDIR); 482 die "$LIBDIR/$csstemplate cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r "$LIBDIR/$csstemplate"); 483 system("cp -f $LIBDIR/$csstemplate \"$opt_d/$opt_dest\""); 484 } 485} else { 486 $nfiles = @imgfiles; # total number of files (same as # of captions) 487 @slides = (); 488 if ($opt_n) { # decide on the slide html file names 489 for ($i = 0; $i < $nfiles; $i++) { 490 $temp = $imgfiles[$i]; 491 $temp =~ s/\.\w+?$/\.html/; # strip suffix, bug fixing (1.4.5) 492 push(@slides,$temp); 493 } 494 } else { 495 for ($i = 0; $i < $nfiles; $i++) { 496 push(@slides, $i+1 . ".html"); 497 } 498 } 499 system("rm -f \"$opt_d/$opt_dest*.html\""); 500 if (! -e "$opt_d/$opt_dest$csstemplate") { 501 print "No CSS template file ... getting $LIBDIR/$csstemplate\n"; 502 die "$LIBDIR cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r $LIBDIR); 503 die "$LIBDIR/$csstemplate cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r "$LIBDIR/$csstemplate"); 504 system("cp -f $LIBDIR/$csstemplate \"$opt_d/$opt_dest\""); 505 } else { 506 print "Found CSS template file $opt_dest$csstemplate ... using it.\n"; 507 } 508 if (! -e "$opt_d/$opt_dest.$slidetemplate") { 509 print "No $opt_dest.$slidetemplate file ... getting a copy from $LIBDIR/\n"; 510 die "$LIBDIR cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r $LIBDIR); 511 die "$LIBDIR/$slidetemplate cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r "$LIBDIR/$slidetemplate"); 512 system("cp -f $LIBDIR/$slidetemplate \"$opt_d/$opt_dest.$slidetemplate\""); 513 } else { 514 print "Found $opt_dest.$slidetemplate file ... using it.\n"; 515 } 516 print "Creating individual slides: "; 517 # read slidetemplate from filesystem once 518 $slidetemplate_string = read_file_in_string("$opt_d/$opt_dest.$slidetemplate"); 519 for ($i = 0; $i < $nfiles; $i++) { 520 $workarea = $slidetemplate_string; # fill work area with slidetemplate 521 open(SW,">$opt_d/$opt_dest$slides[$i]") or die "Can't create slide file\n"; 522 print "$slides[$i] "; 523 if ($opt_k) { # use image caption for the HTML slide title 524 $title = $captions[$i]; 525 } else { # otherwise use the image name (strip suffix) 526 $title = $imgfiles[$i]; 527 $title =~ s/\.\w+?$//; 528 } 529 $workarea =~ s/<!--SLIDE-TITLE-->/$title/g; 530 $imgfile_i_encoded = URLencode($imgfiles[$i]); 531 if ($opt_bigy) { 532 $slide = URLencode($slideprefix . $imgfiles[$i]); 533 if ($HAVEIM) { 534 $workarea =~ s/(<.*)<!--THIS-IMAGE-->(.)(.*>)/<A href=\"$destback$imgfile_i_encoded\">$1$slide$2 width=$xdim[$i] height=$ydim[$i] alt=\"$title\" title=\"click to see full-size\"$3<\/a>/; 535 } else { 536 $workarea =~ s/(<.*)<!--THIS-IMAGE-->(.)(.*>)/<A href=\"$destback$imgfile_i_encoded\">$1$slide$2 alt=\"$title\" title=\"click to see full-size\"$3<\/a>/; 537 } 538 } else { 539 if ($HAVEIM) { 540 $workarea =~ s/<!--THIS-IMAGE-->(.)/$destback$imgfile_i_encoded$1 width=$xdim[$i] height=$ydim[$i] alt=\"$title\"/g; 541 } else { 542 $workarea =~ s/<!--THIS-IMAGE-->/$destback$imgfile_i_encoded/g; 543 } 544 } 545 546 # add in the image counter unless -x is specified 547 if ($opt_x) { 548 $imagecaption = $captions[$i]; 549 } else{ 550 $imagecaption = $captions[$i] . " (" . ($i+1) ."/$nfiles)" if (! $opt_x); 551 } 552 $workarea =~ s/<!--IMAGE-CAPTION-->/$imagecaption/g; 553 554 # add EXIF information if -e is specified 555 if ($opt_e) { 556 my $exif=Image::ExifTool::ImageInfo($imgfiles[$i]); 557 my $exifinfo= "<A href=\"javascript:toggle('exifinfo');\">Show/hide EXIF data</A>\n"; 558 $exifinfo .= "<DIV id=\"exifinfo\">\n"; 559 $exifinfo .= "<TABLE><th>EXIF Tag</th><th>Value</th>\n"; 560 for my $k (sort keys %$exif) { 561 $exifinfo .= "<TR><TD>$k</TD><TD>". 562 (ref($exif->{$k}) eq "SCALAR"?'Binary data '.length(${$exif->{$k}}).' bytes':$exif->{$k})."</TD></TR>\n"; 563 } 564 $exifinfo .= "</TABLE></DIV>\n"; 565 $workarea =~ s/<!--EXIF-INFO-->/$exifinfo/g; 566 } 567 568 # find out if pagination is used and which number the index file has... 569 $index_file_number = ($opt_pagination) ? int ($i / $opt_pagination) : 0; 570 $index_filename = ($index_file_number == 0) ? $opt_i : "$index_file_number$opt_i"; 571 $workarea =~ s/<!--INDEX-FILE-->/$destback$index_filename/g; 572 573 if ($opt_bigy) { 574 $pref = $slideprefix; 575 } else { 576 $pref = $destback; 577 } 578 if ($i == 0 && $nfiles == 1) { # special treatment if there is exactly one file! 579 $temp = URLencode("$pref$imgfiles[0]"); 580 $workarea =~ s/<!--NEXT-IMAGE-->/$temp/g; 581 $temp = URLencode("$slides[0]"); 582 $workarea =~ s/<!--PREV-SLIDE-->/\"$temp\" title=\"$captions[0]\"/g; 583 $temp = URLencode("$slides[0]"); 584 $workarea =~ s/<!--NEXT-SLIDE-->/\"$temp\" title=\"$captions[0]\"/g; 585 } elsif ($i == 0) { # first image, previous points to last image 586 $temp = URLencode("$pref$imgfiles[$i+1]"); 587 $workarea =~ s/<!--NEXT-IMAGE-->/$temp/g; 588 $temp = URLencode("$slides[$nfiles-1]"); 589 $workarea =~ s/<!--PREV-SLIDE-->/\"$temp\" title=\"$captions[$nfiles-1]\"/g; 590 $temp = URLencode("$slides[$i+1]"); 591 $workarea =~ s/<!--NEXT-SLIDE-->/\"$temp\" title=\"$captions[$i+1]\"/g; 592 } elsif ($i == $nfiles-1) { # last image, next points to first image 593 $temp = URLencode("$pref$imgfiles[0]"); 594 $workarea =~ s/<!--NEXT-IMAGE-->/$temp/g; 595 $temp = URLencode("$slides[$i-1]"); 596 $workarea =~ s/<!--PREV-SLIDE-->/\"$temp\" title=\"$captions[$i-1]\"/g; 597 $temp = URLencode("$slides[0]"); 598 $workarea =~ s/<!--NEXT-SLIDE-->/\"$temp\" title=\"$captions[0]\"/g; 599 } else { 600 $temp = URLencode("$pref$imgfiles[$i+1]"); 601 $workarea =~ s/<!--NEXT-IMAGE-->/$temp/g; 602 $temp = URLencode("$slides[$i-1]"); 603 $workarea =~ s/<!--PREV-SLIDE-->/\"$temp\" title=\"$captions[$i-1]\"/g; 604 $temp = URLencode("$slides[$i+1]"); 605 $workarea =~ s/<!--NEXT-SLIDE-->/\"$temp\" title=\"$captions[$i+1]\"/g; 606 } 607 print SW "$workarea"; 608 close(SW); 609 } 610 611 print "... done!\n"; 612} 613 614 615############################################################################# 616# create the main index file with all the thumbnails 617if ($opt_r) { 618 print "Got option -r... omitting film reel effect.\n"; 619} elsif (! -e "$opt_d/$opt_dest.$itile") { 620 print "No $opt_dest.$itile file... getting a copy from $LIBDIR/\n"; 621 die "$LIBDIR cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r $LIBDIR); 622 die "$LIBDIR/$itile cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r "$LIBDIR/$itile"); 623 system("cp -f $LIBDIR/$itile \"$opt_d/$opt_dest.$itile\""); 624} else { 625 print "Found $opt_dest.$itile file ... using it.\n"; 626} 627# rescale the tiled image if the -t switch was called but -r wasn't 628if (($HAVEIM) and (! $opt_r)) { 629 $tileh = `identify -ping -format \"\%wx\%h %b\" \"$opt_d\/$opt_dest.$itile\"`; 630 $tileh =~ s/\d+x(\d+)\s[\d\.]+./$1/; 631 system("mogrify -scale x$opt_t $opt_d/$opt_dest.$itile") if ($opt_t != $tileh); 632} 633 634if (! -e "$opt_d/$opt_dest.$indextemplate") { 635 print "No $opt_dest.$indextemplate file... getting a copy from $LIBDIR/\n"; 636 die "$LIBDIR cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r $LIBDIR); 637 die "$LIBDIR/$indextemplate cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r "$LIBDIR/$indextemplate"); 638 system("cp -f $LIBDIR/$indextemplate \"$opt_d/$opt_dest.$indextemplate\""); 639} else { 640 print "Found $opt_dest.$indextemplate ... using it.\n"; 641} 642 643print "Creating the index file(s) "; 644$indexfile = read_file_in_string("$opt_d/$opt_dest.$indextemplate"); # read indexfile in string to parse it 645$indexfile =~ s/<!--#IGAL-OPTIONS#-->/@igal_options/g; # set comment about igal options in index file 646$indexfile =~ s/<!--#IGAL-CSS#-->/$opt_dest$csstemplate/g; # set the name (and path) of css template file 647 648# Generate the links for directories 649if ($opt_AddSubdir && @directories) { 650 651 if (! -e "$opt_d/$opt_dest.$directorylinefile") { 652 print "No $opt_dest.$directorylinefile file ... getting a copy from $LIBDIR/\n"; 653 die "$LIBDIR cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r $LIBDIR); 654 die "$LIBDIR/$directorylinefile cannot be read or does not exist.\nPlease install igal properly.\n" unless (-r "$LIBDIR/$directorylinefile"); 655 system("cp -f $LIBDIR/$directorylinefile \"$opt_d/$opt_dest.$directorylinefile\""); 656 } else { 657 print "Found $opt_dest.$directorylinefile file ... using it.\n"; 658 } 659 660 $output = ""; 661 $directoryline = read_file_in_string("$opt_d/$opt_dest.$directorylinefile"); 662 foreach $directory (@directories) { 663 $temp = $directoryline; 664 $temp =~ s/#DIRECTORY#/$directory/g; 665 $directoryURLencoded = URLencode($directory); 666 $temp =~ s/#DIRECTORY-URLENCODED#/$directoryURLencoded/g; 667 $output .= $temp; 668 } 669 $indexfile =~ s/<!--#DIRECTORYLINE#-->/$output/; 670} else { 671 $indexfile =~ s/<!--#DIRECTORIES-START#-->.*<!--#DIRECTORIES-END#-->/<!-- no directories -->/s; 672} 673$indexfile =~ s/<!--#IGAL-VERSION#-->/$VERSION/g; #add version information 674 675#generate the table rows 676$indexfile_copy = $indexfile; 677if ($opt_pagination && $nfiles > $opt_pagination) { # pagination necessary! 678 $paginate = $opt_pagination; 679} else { # no pagination necessary 680 $paginate = $nfiles; 681} 682 683for ($page = 0; $page * $paginate < $nfiles; $page++) { 684 $output = ""; 685 $indexfile = $indexfile_copy; 686 687 $on_this_page = int (($page+1) * $paginate <= $nfiles) ? $paginate : ($nfiles - $page*$paginate); # number of pictures on page 688 $rows = int $on_this_page/$opt_w; # number of film rows 689 $rem = $on_this_page % $opt_w; # number of thumbnails on last (incomplete) row 690# print "rows=$rows - rem=$rem - on_this_page=$on_this_page\n"; 691 692 if ($rem > 0) { $rows++; } # is there a last incomplete row? if yes, we need one more circle for this one 693 for ($i = 1; $i <= $rows; $i++) { 694 # 695 $columns = ($i == $rows && $rem > 0) ? $rem : $opt_w; # last row needs less columns 696 697 $output .= " <TABLE border=0 cellspacing=0 cellpadding=$opt_p>\n"; 698 $output .= " <TR><TD class=\"tiled\" height=$opt_t colspan=" . ($columns + 2) . "> </TD></TR>\n" unless ($opt_r); 699 $output .= " <TR>\n <TD class=\"thumb\"> </TD>\n"; 700 for ($j = 1; $j <= $columns; $j++) { 701 $fileindex = ($page * $paginate) + (($i-1)*$opt_w+$j-1); # calculate which file is in use 702# print "i=$i - j=$j (columns=$columns)- fileindex=$fileindex\n"; 703 $output .= " <TD class=\"thumb\">\n "; 704 if ($opt_s) { 705 $output .= "<A href=\"$opt_o" . URLencode($imgfiles[$fileindex]) . "\">"; 706 } else { 707 $output .= "<A href=\"$opt_o$opt_dest" . URLencode($slides[$fileindex]) . "\">"; 708 } 709 print "."; 710 $altname = $captions[$fileindex]; 711 $thumb = $opt_dest . $thumbprefix . $imgfiles[$fileindex]; 712 $thumbEncoded = $opt_dest . URLencode($thumbprefix . $imgfiles[$fileindex]); 713 if ($HAVEIM) { 714 $temp = `identify -ping -format \"\%wx\%h\" \"$opt_d/$thumb\"`; 715 $temp =~ m/(\d+)x(\d+)/; $x=$1; $y=$2; 716 $output .= "<IMG src=\"" . $thumbEncoded . "\" width=$x height=$y alt=\"$altname\" title=\"$altname\" border=0>"; 717 } else { 718 $output .= "<IMG src=\"" . $thumbEncoded . "\" alt=\"$altname\" title=\"$altname\" border=0>"; 719 } 720 $output .= "</A></TD>\n"; 721 } 722 $output .= " <TD class=\"thumb\"> </TD>\n </TR>\n"; 723 $output .= " <TR><TD class=\"tiled\" height=$opt_t colspan=" . ($columns+2) . "> </TD></TR>\n" unless ($opt_r); 724 if (($opt_a or $opt_ad or $opt_as) and $HAVEIM) { 725 $output .= " <TR>\n <TD> </TD>\n"; 726 for ($j = 1; $j <= $columns; $j++) { 727 $fileindex = ($page * $paginate) + (($i-1)*$opt_w+$j-1); # calculate which file is in use 728# print $fileindex; 729 $output .= " <TD>"; 730 $printdim = "$isiz[$fileindex]" if $opt_as; 731 $printdim = "$xdim[$fileindex]x$ydim[$fileindex]" if $opt_ad; 732 $printdim = "$xdim[$fileindex]x$ydim[$fileindex] ($isiz[$fileindex])" if $opt_a; 733 $output .= $printdim; 734 $output .= "</TD>\n"; 735 } 736 $output .= " </TR>\n"; 737 } 738 # write image captions under images if option -u is given 739 if ($opt_u) { 740 $output .= " <TR>\n <TD> </TD>\n"; 741 for ($j = 1; $j <= $columns; $j++) { 742 $fileindex = ($page * $paginate) + (($i-1)*$opt_w+$j-1); # calculate which file is in use 743# print $fileindex; 744 $output .= " <TD>" . $captions[$fileindex] . "</TD>\n"; 745 } 746 $output .= " </TR>\n"; 747 } 748 $output .= " </TABLE>\n <BR>\n"; 749 750 } 751 752 # now replace placeholder in index-file with generated html code 753 $indexfile =~ s/<!-- contents with thumbnails will be inserted here by igal -->/$output/; 754 # insert pageination 755 if ($opt_pagination && $nfiles > $opt_pagination) { # pagination necessary! 756 $numberpages = ceil($nfiles / $opt_pagination); 757 $nextpage = $page+1; 758 $tmptext = "Page $nextpage of $numberpages"; 759 # forward navigation 760 if (($page+1) * $paginate < $nfiles) { 761 $nextpagename = "$nextpage$opt_i"; 762 $lastpage = $numberpages -1; 763 $tmptext .= "<a href=\"$nextpagename\"> >></a> <a href=\"$lastpage$opt_i\">>|</a>"; 764 } 765 # backward navigation 766 if ($page > 0) { 767 $prevpage = $page-1; 768 $prevpagename = ($prevpage == 0) ? $opt_i : "$prevpage$opt_i"; 769 $tmptext = "<a href=\"$opt_i\">|< </a><a href=\"$prevpagename\"><<</a> $tmptext"; 770 } 771 $indexfile =~ s/<!--#IGAL-PAGINATION#-->/$tmptext/g; 772 } 773 $indexfile =~ s/<!-- \*{4}.*\*{4} -->//g; #clean up 774 $indexfile =~ s/<!--#.*#-->//g; #clean up 775 776 $index_filename = ($page == 0) ? $opt_i : "$page$opt_i"; 777 print "$index_filename "; 778 open(IXW,">$opt_d/$index_filename") or die "Can't create main $index_filename file\n"; 779 print IXW $indexfile; 780 close(IXW); 781} 782 783print " done!\n"; 784 785# if --www was invoked make all images world-readable at the END 786if ($opt_www) { 787 $dir = ($opt_d eq ".") ? $opt_dest : "$opt_d/$opt_dest"; 788 $dir =~ s/\ /\\ /g; # escape blanks in directory/filenames for system call 789 print "\nMaking all igal files world-readable for WWW publishing...\n"; 790 print "chmod a+r $dir$csstemplate\n"; 791 system("chmod a+r $dir$csstemplate"); 792 print "chmod a+r $dir*.html\n"; 793 system("chmod a+r $dir*.html"); 794 print "chmod a+r $dir$thumbprefix*.*\n"; 795 system("chmod a+r $dir$thumbprefix*.*"); 796 print "chmod a+r $dir$slideprefix*.*\n"; 797 system("chmod a+r $dir$slideprefix*.*"); 798 print "chmod a+r $dir.$itile\n" unless($opt_r); 799 system("chmod a+r $dir.$itile") unless($opt_r); 800 print "chmod a+r "; 801 # imagefiles are in same directory, therefore $dir has to be set different 802 $dir = ($opt_d eq ".") ? "" : "$opt_d/"; 803 foreach $file (@imgfiles) { 804 print "$dir$file "; 805 system("chmod a+r \"$dir$file\""); 806 } 807 print "\nDone!\n"; 808} 809 810############################################################################## 811 812# subroutine that checks if a certain program is in the user's path 813# usage &exist("identify") --> 1 (or 0 if it doesn't exist) 814sub exist { 815 local($program) = @_; 816 foreach $dir (split(/:/,$ENV{'PATH'})) { 817 return 1 if (-f "$dir/$program"); 818 } 819 return 0; 820} 821 822 823# subroutine that reads a file in a string... 824# called with $string = read_file_in_string("datei.txt"); 825sub read_file_in_string { 826 local($filename) = @_; 827 828 open(FILE,$filename) or die "Can't open file $filename [$!]\n"; 829 local $/; 830 $string = <FILE>; 831 close(FILE); 832 833 return $string; 834} 835 836# subroutine that URL encodes a string... 837# called with $string = URLencode("text to encode"); 838sub URLencode { 839 local($string) = @_; 840 $string =~ s/([^a-zA-Z0-9\.\_])/sprintf "%%%02X",ord($1)/eg; 841 842 return $string 843} 844