#!/bin/sh exec ${PERL-perl} -Sx $0 ${1+"$@"} #!perl # # $Id: mkthumbnail,v 1.2 2001/12/01 10:16:48 friedman Exp $ # # 'HTMLThumbnail', written by Benjamin Franz, snowhare@nihongo.org # # History: # # 1.1.4 04 Apr, 1999 - Hacked up a bit by dsully, added subpage # generation, and description grabbing. # # # 1.1.3a 06 Sep, 1998 - Corrected bug in offsets for drop # shadows that misaligned the # shadow under some circumstances. # # 1.1.3 11 May, 1998 - Added the 'rotate' filter to # allow the final icons to be rotated # through an arbitrary angle. Fixed # image link border thickness bug # (bug and fix identified by Matthew N. # Kleiman ). # # 1.1.2 10 May, 1998 - Improved handling for files with funky # characters in their names. Replaced # the use of 'pnmsmooth' with direct # use of 'pnmconvol' to improve # portability. Pushed various things # into sub-routines for code clarity and # let 'anytopnm' try and deal with unrecognized # file types. This should allow any graphic # type 'anytopnm' can deal with to be thumbnailed. # # 1.1.1 8 May, 1998 - Minor workarounds for systems with old # NetPBM libaries installed. Some old # versions have broken anytopnm routines # and a crippled 'pnmsmooth'. # # 1.1 27 February, 1998 - Color edges and drop shadows for thumbnails # # 1.0 20 February, 1998 - Release of 1.0 version # # HTMLThumbnail generates an HTML page of thumbnailed images # to allow the ready visual inspection of the contents of a directory # of images (gifs and/or jpegs). The typical resulting thumbnail # file size is around 1-2% of the size of the original images. # # Usage: # htmlthumbnail [-update ] # [-output ] # [-size ] # [-quality ] # [-link <0|1>] # [-rowsize ] # [-catalogdir ] # [-title ] # [-background <URL>] # [-bgcolor "#rrggbb"] # [-textcolor "#rrggbb"] # [-linkcolor "#rrggbb"] # [-alinkcolor "#rrggbb"] # [-vlinkcolor "#rrggbb"] # [-border <thickness of link hilight border on icons>] # [-edgewidth <thickness of applied edge on icons>] # [-edgecolor "#rrggbb"] <color of applied edge on icons>] # [-dropshadow <0|1>] # [-dshadowblur <n>] # [-dshadowoffset <n>] # [-dshadowcolor "#rrggbb"] # [-rotate <ndegrees] # [-progressive] # [-tempdir <temporary directory>] # <list of image files> # # It creates the thumbnails in the 'catalogdir' sub-directory # of the *current* directory - so you have to 'cd' to the directory # above where you want the thumbnails to go before starting. # # cd /www/somedirectorywithimages # htmlthumbnail *jpg -output test.html # # for example. # # The -update mode can be used to greatly improve processing # efficiency by only making icons for images that are new or # seem to have changed since the last time a catalog was generated. # Use it that way like this: # # htmlthumbnail -update catalog.html -output catalog.html *jpg *gif # # The -link option controls whether or not the thumbnails are # linked to the original images in the catalog. # '-link 0' results in NO links, '-link 1' results in links. # # This utility depends on the Independent JPEG Group's software # (available at <URL:ftp://ftp.uu.net/graphics/jpeg>) # (in particular it depends on the 'cjpeg' and 'djpeg' routines) and the # NetPBM package (available at # <URL:ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM> # # If those are already installed on your system, you are good to # go. If not, you will have to download and install them before # you can use this utility. # # The default 'quality' setting I've chosen for the thumbnails is # only '50'. If the resulting icons don't come up to your standards, # bump it up to 75 or so. # # Credit should also be given to Andrew Tong, werdna@ugcs.caltech.edu # and alex@ed.ac.uk since the logic for the gif and jpeg size # detection sub-routines is based on that found in 'wwwimagesize' # (hacked up a bit and with better handling of a couple # of bogus cases) # # Known issues: # # Transparent 1 x X pixel 'spacer' GIFs may not be processed # correctly. # # It is not likely that HTMLThumbnail will work on non-Unix # type machines without a bit of hacking # on your part. IOW: It probably will not # work on a Mac or under Windows. # # GIFs with transparent areas will have the transparent # areas shown with the actual index color (not transparent). # # If for some reason the routine can't generate a # thumbnail image from an original, it will skip it # in the HTML catalog and generate an error message. # The usual cause is damaged original images. # # No error checking is performed on command line parameters. # # The 'backtick' calls to 'cjpeg', 'djpeg', 'giftopnm', # 'anytopnm, 'pnmscale', 'pnmconvol', 'ppmmake', 'pnmpaste' # assume that they can be found in your PATH. # If they can't you need to either add them to your PATH # or give the FULL path to them in the backtick calls. # # Some old versions of 'cjpeg' can't handle the 'progressive' # flag. If you can't upgrade to the current version, # turn off the progressive flag by setting the # line reading "$progressive=1;" to read # "$progressive='';". # # Some old versions of 'anytopnm' are broken and will try to # call 'giftoppm', which doesn't exist. You can # fix this by changing the places in 'anytopnm' # that call 'giftoppm' with 'giftopnm'. Or update # your NetPBM as above. # # NOTE: HTMLThumbnail is not meant to work as a CGI but from the # command line. If you want to hack it to work as a CGI, fine - # but don't email me about it not working as CGI. That's # because it *ISN'T* a CGI program. # # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS # OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE. # # Use of this software in any way or in any form, source or binary, # is not allowed in any country which prohibits disclaimers of any # implied warranties of merchantability or fitness for a particular # purpose or any disclaimers of a similar nature. # # IN NO EVENT SHALL I BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, # SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE # USE OF THIS SOFTWARE AND ITS DOCUMENTATION (INCLUDING, BUT NOT # LIMITED TO, LOST PROFITS) EVEN IF I HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE # # Copyright February 1998, Benjamin Franz &ReadCommandLine('update:output:size:quality:link:rowsize:catalogdir:background:textcolor:bgcolor:vlinkcolor:alinkcolor:linkcolor:title:tempdir:edgecolor:edgewidth:dropshadow:dshadowblur:dshadowoffset:dshadowcolor:rotate:border'); ####################################################################### # Global setting defaults. # ####################################################################### # Title of the page # Command line control: -title "Title stuff" $title = ''; # Thumbnails should be *small* # Command line control: -size <value> $thumbnailsize = 100; # Border size on images # Command line control: -border <value> $border = 0; # 1-100. Thumbnails don't usually need great quality # Command line control: -quality <1-100> $qualityfactor = 80; # 1=link to original image, 0=don't link # Command line control: -link <0|1> $linkimage = 1; # Rule of thumb: $imagesperrow=int(400/$thumbnailsize) # Command line control: -rowsize <value> $imagesperrow = 5; # name of the sub-directory to place the icon images in # Command line control: -catalogdir <value> $catalogdirectory = '.thumbs'; # Without a defined outputfile, (either here or on the command line) # the HTML output will go to STDOUT # Command line control: -output <filename> $outputfile = 'index.html'; # BACKGROUND # Command line control: -background <URL> # $background="/graphics/background/background.jpg"; $background = ''; # BGCOLOR # Command line control: -bgcolor #rrggbb $bgcolor = '#FFFFFF'; # TEXT # Command line control: -textcolor #rrggbb $textcolor = '#000000'; # LINK # Command line control: -linkcolor #rrggbb $linkcolor = '#0000CC'; # ALINK # Command line control: -alinkcolor #rrggbb $alinkcolor = '#CC0000'; # VLINK # Command line control: -vlinkcolor #rrggbb $vlinkcolor = '#CC00CC'; # Make 'progressive' jpgs for the thumbnails # I think it is safe enough now (early 1998). # If you don't agree, (or if you just want # slightly better compression), set it to 0 to # get old style non-progressive jpeg by default. $progressive = 1; # Temporary scratch directory to use # Command line control: -tempdir <dirname> $tempdir = '/tmp'; # Edge thickness (must be an integer) # Command line control: -edgewidth <n> $edgewidth = 1; # Edge color (hexadecimal color code) # Command line control: -edgercolor #rrggbb $edgecolor = '#000000'; # Drop shadow color (hexadecimal color code) # Command line override: -dshadowcolor #rrggbb $dropshadowcolor = '#333333'; # Drop shadow offset (integer) # Command line override: -dshadowoffset <n> $dropshadowoffset = 3; # Drop shadow blur (integer - even numbers will be rounded # up to odd numbers internally. '0' is no blur.) # Command line override: -dshadowblur <n> $dropshadowblur = 5; # Make drop shadow (flag - 0 = no, 1 = yes) # Command line override: -dropshadow <0|1> $makedropshadow = 1; # Rotate the final image through an angle (degrees) # Command line override: -rotate <ndegrees> $rotationangle = 0; ####################################################################### # Handle command line options # ####################################################################### # Read the catalog to be updated before opening the # output file to prevent wiping out the data # if they are the same file (they probably will be in general) &readcatalog($opt{'update'}) if defined $opt{'update'}; $outputfile = $opt{'output'} if defined $opt{'output'}; if ($outputfile) { if (!open OUTPUTFILE, ">$outputfile") { die ("Could not open $outputfile for writing\n$!"); } select OUTPUTFILE; } $title = $opt{'title'} if defined $opt{'title'}; $border = $opt{'border'} if defined $opt{'border'}; $background = $opt{'background'} if defined $opt{'background'}; $bgcolor = $opt{'bgcolor'} if defined $opt{'bgcolor'}; $textcolor = $opt{'textcolor'} if defined $opt{'textcolor'}; $linkcolor = $opt{'linkcolor'} if defined $opt{'linkcolor'}; $alinkcolor = $opt{'alinkcolor'} if defined $opt{'alinkcolor'}; $vlinkcolor = $opt{'vlinkcolor'} if defined $opt{'vlinkcolor'}; $edgecolor = $opt{'edgecolor'} if defined $opt{'edgecolor'}; $edgewidth = $opt{'edgewidth'} if defined $opt{'edgewidth'}; $thumbnailsize = $opt{'size'} if defined $opt{'size'}; $qualityfactor = $opt{'quality'} if defined $opt{'quality'}; $imagesperrow = $opt{'rowsize'} if defined $opt{'rowsize'}; $catalogdirectory = $opt{'catalogdir'} if defined $opt{'catalogdir'}; $tempdir = $opt{'tempdir'} if defined $opt{'tempdir'}; $linkimage = $opt{'link'} if defined $opt{'linkdir'}; $makedropshadow = $opt{'dropshadow'} if defined $opt{'dropshadow'}; $dropshadowcolor = $opt{'dshadowcolor'} if defined $opt{'dshadowcolor'}; $dropshadowblur = $opt{'dshadowblur'} if defined $opt{'dshadowblur'}; $dropshadowoffset = $opt{'dshadowoffset'} if defined $opt{'dshadowoffset'}; $progressive = 1 if defined $opt{'progressive'}; $rotationangle = $opt{'rotate'} if defined $opt{'rotate'}; ####################################################################### # Set final pre-processing elements # ####################################################################### my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$fsize,$atime,$mtime,$ctime, $blksize,$blocks,$file,$icon,$newfile,$image,$height,$width, $iheight,$iwidth,$counter,$filetype); $background = "BACKGROUND=\"$background\"" if $background; $rawbgcolor = $bgcolor; $bgcolor = "BGCOLOR=\"$bgcolor\"" if $bgcolor; $textcolor = "TEXT=\"$textcolor\"" if $textcolor; $linkcolor = "LINK=\"$linkcolor\"" if $linkcolor; $alinkcolor = "ALINK=\"$alinkcolor\"" if $alinkcolor; $vlinkcolor = "VLINK=\"$vlinkcolor\"" if $vlinkcolor; $progressive = $progressive ? '-progressive' : ''; if (!-e $catalogdirectory) { mkdir $catalogdirectory, 0755 or die "No $catalogdirectory directory and could not create\n$!\n"; } if (!-d $catalogdirectory) { die "$catalogdirectory exists, but is not a directory\n"; } # Round the dropshadow blur *up* to the nearest odd integer # if it is not '0' if ($dropshadowblur && (! ($dropshadowblur % 2))) { $dropshadowblur++; } # If we need to blur a drop shadow, we need a convolution map for it if ($makedropshadow && $dropshadowblur) { my ($convol_map) = &get_convol_map($dropshadowblur); &savefile ("$tempdir/$$-dropshadow.cnv",$convol_map); } undef $/; print <<EOF; <HTML><HEAD><TITLE>$title

$title

EOF my $i = 0; $counter = 0; my (@filelist,%desc) = (); foreach my $file (sort @ARGV) { next if (! (-f $file && -r _ )); push @filelist, $file; } if (-f 'index.txt') { print "Please use 'desc.txt' instead of 'index.txt'\n"; print "Exiting..\n"; exit; } if (-f 'desc.txt') { open INDEX, 'desc.txt' or die $!; local $/ = "\n"; while () { chomp; my ($file,$desc) = split /\s+/, $_, 2; next if $desc eq 'SKIP'; $desc{$file} = $desc; } close INDEX; } for my $file (@filelist) { next if ($file =~ m#-indexicon\.jpg$#oi); my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$fsize,$atime,$mtime, $ctime,$blksize,$blocks)=stat($file); if ( defined($newfile=$images{"$file thumbnail"}) && (-e "$catalogdirectory/$newfile") && ($images{"$file lastmod"} == $mtime) && ($images{"$file size"} == $fsize) ) { $width = $images{"$file width"}; $height = $images{"$file height"}; $newfile = $images{"$file thumbnail"}; $iwidth = $thumbnails{"$newfile width"}; $iheight = $thumbnails{"$newfile height"}; } else { # Make up a name for the icon file $newfile = $file; $newfile =~ s/\.([a-z]{3,4})$/-$1-indexicon.jpg/oi; # flatten funny chars to '_' $newfile =~ s/[^-_a-z0-9.]/_/oigs; # Handle the case if they index sub-directories # by flattening the '/'s to '-' for the icon names $newfile =~ s/\//-/g; # get the various meta info about the file ($width,$height,$fsize) = &get_image_stats($file); if (! $fsize) { print STDERR "Unable to determine $file contents. Skipping\n"; next; } # Create the initial icon $icon = &scale_image_file($file,$thumbnailsize); if (length($icon) == 0) { print STDERR "Unable to generate a thumbnail of $file. Skipping.\n"; next; } # Add a border to the image, if requested if ($edgewidth > 0) { $icon = &add_border($icon,$edgewidth,$edgecolor); if (length($icon) == 0) { print STDERR "Could not add requested border to icon for $file. Skipping\n"; next; } } # Add a drop shadow to the image if requested # (Note: Only works with 'flat' color backgrounds) # graphic backgrounds are not supported at this time. if ($makedropshadow) { $icon = &add_dropshadow($icon,$dropshadowblur,$dropshadowoffset,$dropshadowcolor,$rawbgcolor); if (length($icon) == 0) { print STDERR "Unable to add requested dropshadow to icon for $file\n"; next; } } # Rotate the image, if requested if ($rotationangle > 0) { $icon = &rotate($icon,$rotationangle,$rawbgcolor); if (length($icon) == 0) { print STDERR "Could not rotate icon for $file. Skipping\n"; next; } } # Compress it into a jpg and save it &savefile("| cjpeg -quality $qualityfactor -optimize $progressive > '$catalogdirectory/$newfile'",$icon); ($iwidth,$iheight)=&pnmsize($icon); } if (($counter % $imagesperrow) == 0) { print "\n"; } $counter++; print ' \n"; $link .= "\n"; $link .= "\n"; print HTML "
'; # DFS my $html = $file; $html =~ s/\.jpg$/\.html/i; if ($linkimage) { print ""; } open HTML, ">$html" or die $!; print HTML qq!\n\n!; my $link = '
'; if ($i != 0) { $link .= 'Prev'; } else { $link .= ' '; } $link .= "Up"; if ($i != $#filelist) { $link .= 'Next'; } else { $link .= ' '; } $link .= "
\n"; print HTML $link; print HTML "\n"; if ($desc = $desc{$file}) { print HTML "\n"; } print HTML $link; print HTML "
$desc
\n"; print HTML "\n"; close HTML; print "\"[$file]\""; print '' if $linkimage; #print "
$file
${fsize} bytes
$width x $height
"; print "\n"; print "\n" if ($counter % $imagesperrow) == 0; $i++; } print "\n" if ($counter % $imagesperrow) != 0; print <
EOF # if any of the temporary files are still hanging around - get rid of them for (qw(scratchfile0.pnm scratchfile1.pnm scratchfile2.pnm dropshadow.cnv)) { unlink "$tempdir/$$-$_" if -e "$tempdir/$$-$_"; } ###################################################################### # Get the height, width and size in bytes of the file # ###################################################################### sub get_image_stats { my ($file) = @_; my ($filetype) = &get_file_type($file); if (! open (ORIGINAL,$file)) { print STDERR "Could not open $file for reading\n$!"; return; } $image=; close(ORIGINAL); if ($filetype eq 'jpg') { ($width,$height)= &jpegsize($image); } elsif ($filetype eq 'gif') { ($width,$height) = &gifsize($image); } else { # Let 'anytopnm' have a shot at it. "Do you feel lucky, punk?" $image = `anytopnm $file`; if (length ($image) == 0) { # print STDERR "Could not determine type of $file. Skipping\n"; return; } ($width,$height) = &pnmsize($image); } if (! ($height && $width)) { print STDERR "Could not determine height and width of $file. Skipping\n"; return; } $fsize=length($image); return ($width,$height,$fsize); } ###################################################################### # Guess the file type # ###################################################################### sub get_file_type { my ($file) = @_; my ($filetype) = ''; if ($file =~ m/\.(pjpeg|jpg|pjpg|jpeg)$/oi) { $filetype = 'jpg'; } elsif ($file =~ m/\.gif$/oi) { $filetype = 'gif'; } else { $filetype = 'unknown'; } return ($filetype); } ###################################################################### # Rotate an image through an angle # ###################################################################### sub rotate { my ($icon,$angle,$bgcolor) = @_; if (! &savefile ("$tempdir/$$-scratchfile1.pnm",$icon)) { print STDERR "Failed to save image $tempdir/$$-scratchfile0.pnm to temp dir\n"; return; } # Add a two pixel bgcolor margin to the icon (so the alpha # mask doesn't eat any of the icon) `pnmmargin -color '$bgcolor' 2 $tempdir/$$-scratchfile1.pnm > $tempdir/$$-scratchfile0.pnm`; # Make and rotate our alpha mask my ($width,$height) = &pnmsize($icon); `ppmmake '#ffffff' $width $height > $tempdir/$$-scratchfile1.pnm`; `pnmmargin -color '#000000' 2 $tempdir/$$-scratchfile1.pnm > $tempdir/$$-scratchfile3.pnm`; `pnmrotate $angle $tempdir/$$-scratchfile3.pnm > $tempdir/$$-scratchfile2.pnm`; `ppmtopgm $tempdir/$$-scratchfile2.pnm > $tempdir/$$-scratchfile1.pnm`; # Rotate the image `pnmrotate $angle $tempdir/$$-scratchfile0.pnm > $tempdir/$$-scratchfile2.pnm`; if ( ($temp = &readfile("$tempdir/$$-scratchfile1.pnm")) ) { my ($newwidth,$newheight) = &pnmsize($temp); # Regenerate our background `ppmmake '$bgcolor' $newwidth $newheight > $tempdir/$$-scratchfile0.pnm`; # Composite the rotated image $icon = `pnmcomp -invert -alpha $tempdir/$$-scratchfile1.pnm $tempdir/$$-scratchfile0.pnm $tempdir/$$-scratchfile2.pnm`; unlink ("$tempdir/$$-scratchfile0.pnm","$tempdir/$$-scratchfile1.pnm", "$tempdir/$$-scratchfile2.pnm","$tempdir/$$-scratchfile3.pnm"); } else { $icon = ''; } return $icon; } ###################################################################### # Return a scaled portable anymap of the requested image # ###################################################################### sub scale_image_file { my ($file,$size) = @_; my ($filetype) = &get_file_type($file); my ($icon) = ''; # generate a PNM scaled to the icon size if ($filetype eq 'jpg') { $icon=`djpeg '$file' | pnmscale -xysize $size $size`; } elsif ($filetype eq 'gif') { # Because 'anytopnm' screws up for gifs $icon=`giftopnm '$file' | pnmscale -xysize $size $size`; } else { # maybe we'll get lucky and 'anytopnm' will guess right. $icon=`anytopnm '$file' | pnmscale -xysize $size $size`; } return ($icon); } ####################################################################### # Add a drop shadow to the image if requested # # (Note: Only works with 'flat' color backgrounds) # # graphic backgrounds are not supported at this time. # ####################################################################### sub add_dropshadow { my ($er) = @_; my ($icon,$dropshadowblur,$dropshadowoffset,$dropshadowcolor,$rawbgcolor) = @_; my ($leftpad,$rightpad,$toppad,$bottompad,$iwidth,$iheight,$dswidth,$dsheight); $leftpad = $dropshadowblur-$dropshadowoffset; $leftpad = 0 if ($leftpad < 0); $rightpad = $dropshadowblur+$dropshadowoffset; $rightpad = 0 if ($rightpad < 0); $toppad = $dropshadowblur-$dropshadowoffset; $toppad = 0 if ($toppad < 0); $bottompad = $dropshadowblur+$dropshadowoffset; $bottompad = 0 if ($bottompad < 0); ($dswidth,$dsheight) = &pnmsize($icon); my $dsoffset = $dropshadowoffset; $dsoffset += $leftpad; $iwidth = $dswidth; $iheight = $dsheight; $dswidth = $dswidth+$leftpad+$rightpad; $dsheight = $dsheight+$toppad+$bottompad; # Make the color block for the dropshadow `ppmmake '$dropshadowcolor' $iwidth $iheight > $tempdir/$$-scratchfile0.pnm`; # Make the padded block `ppmmake '$rawbgcolor' $dswidth $dsheight > $tempdir/$$-scratchfile1.pnm`; # insert the dropshadow block into the padded block `pnmpaste -replace $tempdir/$$-scratchfile0.pnm $dsoffset $dsoffset $tempdir/$$-scratchfile1.pnm> $tempdir/$$-scratchfile2.pnm`; # Blur the shadow, if a blur has been specified if ($dropshadowblur) { `pnmconvol $tempdir/$$-dropshadow.cnv $tempdir/$$-scratchfile2.pnm > $tempdir/$$-scratchfile0.pnm`; } else { # "mv" - but faster # Should add error checks.... unlink ("$tempdir/$$-scratchfile0.pnm"); link ("$tempdir/$$-scratchfile2.pnm","$tempdir/$$-scratchfile0.pnm"); unlink ("$tempdir/$$-scratchfile2.pnm"); } # Insert the raw icon into its drop shadow frame if (! &savefile ("$tempdir/$$-scratchfile1.pnm",$icon)) { print STDERR "Failed to save image to temp dir\n"; next; } $icon = `pnmpaste -replace $tempdir/$$-scratchfile1.pnm $leftpad $toppad $tempdir/$$-scratchfile0.pnm`; # Dispose of the temporary files unlink ("$tempdir/$$-scratchfile0.pnm", "$tempdir/$$-scratchfile1.pnm", "$tempdir/$$-scratchfile2.pnm"); return ($icon); } ####################################################################### # Add a colored border to an icon # ####################################################################### sub add_border { my ($icon,$edgewidth,$edgecolor) = @_; if (! &savefile ("$tempdir/$$-scratchfile0.pnm",$icon)) { print STDERR "Failed to save image $tempdir/$$-scratchfile0.pnm to temp dir\n"; return; } $icon = `pnmmargin -color $edgecolor $edgewidth $tempdir/$$-scratchfile0.pnm`; unlink ("$tempdir/$$-scratchfile0.pnm"); return $icon; } ####################################################################### # saves the data passed in 'image' to $filename # ####################################################################### sub savefile { my ($filename,$image)=@_; if (! ($filename =~ m#^\s*[|><]#o)) { $filename=">$filename"; } if (! open (NEWFILE,"$filename")) { print STDERR "$filename could not be opened for writing\n$!"; return 0; } print NEWFILE $image; close (NEWFILE); 1; } ####################################################################### # returns the contents of $filename # ####################################################################### sub readfile { my $filename = shift; if (!open NEWFILE, $filename) { print STDERR "$filename could not be opened for reading\n$!"; return; } my ($savedreadstate) = $/; $/ = undef; $data = ; $/ = $savedreadstate; close NEWFILE; return $data; } ####################################################################### # Generates the convolution map needed by pnmcovol to do a blur # ####################################################################### sub get_convol_map { my ($blursize) = @_; my ($map,$offset,$rowvalue,$x,$y); # Round the blur *up* to the nearest odd integer # if it is not '0' if ($blursize && (! ($blursize % 2))) { $blursize++; } $offset = $blursize * $blursize; $rowvalue = $offset + 1; $offset = $offset * 2; $map = "P2\n$blursize $blursize\n$offset\n"; for ($y=1;$y<=$blursize;$y++) { for ($x=1;$x<=$blursize;$x++) { $map .= $rowvalue; if ($x != $blursize) { $map .= " "; } } $map .= "\n"; } return ($map); } ######################################################################## # Determines the size of a jpeg # ######################################################################## sub jpegsize { my($JPEG) = @_; my($count) = 2; my($length)= length($JPEG); my($ch) = ""; my ($c1,$c2,$a,$b,$c,$d,$width,$height); while (($ch ne "\xda") && ($count<$length)) { # Find next marker (JPEG markers begin with 0xFF) while (($ch ne "\xff") && ($count < $length)) { $ch=substr($JPEG,$count,1); $count++; } # JPEG markers can be padded with unlimited 0xFF's while (($ch eq "\xff") && ($count<$length)) { $ch=substr($JPEG,$count,1); $count++; } # Now, $ch contains the value of the marker. if ((ord($ch) >= 0xC0) && (ord($ch) <= 0xC3)) { $count+=3; ($a,$b,$c,$d)=unpack("C"x4,substr($JPEG,$count,4)); $width=$c<<8|$d; $height=$a<<8|$b; return($width,$height); } else { # We **MUST** skip variables, since FF's within variable names are # NOT valid JPEG markers ($c1,$c2)= unpack("C"x2,substr($JPEG,$count,2)); $count += $c1<<8|$c2; } } } ######################################################################## # Determines the size of an anymap # ######################################################################## sub pnmsize { my $pnm = shift; my ($width,$height) = ($pnm =~ m#^P\d+\s+(\d+)\s+(\d+)\s+\d+\s#ois); return ($width,$height) if ($width && $height); } ######################################################################## # Determines the size of a gif # ######################################################################## sub gifsize { my($GIF) = @_; my ($type,$a,$b,$c,$d,$s,$width,$height); $type=substr($GIF,0,6); if(!($type =~ m/GIF8[7,9]a/) || (length($s=substr($GIF, 6, 4)) != 4) ){ return; } ($a,$b,$c,$d)=unpack("C"x4,$s); $width= $b<<8|$a; $height= $d<<8|$c; return ($width,$height); } sub readcatalog { my($catalogfile)=@_; undef %images; undef %thumbnails; my ($thumbnailname,$thumbnailwidth,$thumbnailheight, $imagename,$imageheight,$imagewidth,$imagesize, $qcat); if (! open(CATALOG,$catalogfile)) { warn("Catalog file $catalogfile not readable\n$!"); return; } $qcat=quotemeta($catalogdirectory); while () { chop; $imagelastmod=0; ($thumbnailname,$thumbnailheight,$thumbnailwidth, $imagename,$imagesize,$imagewidth,$imageheight,$imagelastmod)= m#^\s*.*]*>\S{0,4}
\s*(.+)
\s*(\d+)\sbytes
\s*(\d+)\sx\s(\d+)
\s*#o; next if (! $imagelastmod); # push(@thumbnailslist,$thumbnailname); # push(@imageslist,$imagename); $thumbnails{"$thumbnailname height"} = $thumbnailheight; $thumbnails{"$thumbnailname width"} = $thumbnailwidth; $thumbnails{"$thumbnailname imagename"}= $imagename; $images{"$imagename lastmod"} = $imagelastmod; $images{"$imagename height"} = $imageheight; $images{"$imagename width"} = $imagewidth; $images{"$imagename size"} = $imagesize; $images{"$imagename thumbnail"} = $thumbnailname; } close (CATALOG); } # I *DON'T* use the standard Perl lib for parsing command lines # because I've had trouble with core dumping Perl using those routines # before. This is simple and reliable. And it doesn't *EVER* core dump. sub ReadCommandLine { # parse list has the form 'a:b:c:' # flags with parse list entries must take values my($parselist)=$_[0]; my(@CommandLine)=@ARGV; my(@ParseList,%ParseRules,@GenericList,$item,$parm,$value); (@ParseList)=split(/:/,$parselist); foreach $item (@ParseList) { $ParseRules{$item} = 1; } while ($parm=shift(@CommandLine)) { if ($parm =~ m#^\-([a-zA-Z]+)$#o) { $parm=$1; $opt{$parm}=1; if ($ParseRules{$parm}) { $value=shift(@CommandLine); if ($value eq "") { die ("Invalid comand line switch usage, '-$parm' requires value\n"); } $opt{$parm}=$value; } next; } push(@GenericList,$parm); } @ARGV=@GenericList; } sub htmlname { my $i = shift; my $r = $filelist[$i]; $r =~ s/\.jpg$/\.html/i; return $r; }