#!/usr/bin/perl $ME = 'thumbindex v1.21B'; # # this is still a program being developed... so bear with me. # dont mind the debugging stuff (!).... # # USAGE: thumbindex index.jpg image_file1 image_file2 ... > outfile.html # # this is where PBM stuff lives (also jpeg utils) # probably the only thing you need to change (famous last words) $BIN = '/usr/bin'; #where image utils live $ACROSS = 6; #default width in number of images $SIZE = 100; #default size (square) of each thumbnail tile # these are used to identify the process as unique and make intermediate files $ID = $$; $TMP = "/tmp/index$ID-"; #regexp for valid file types (returned by `file` and also extension) $VALID_TYPES = "(gif|jpe?g)"; #case gets ignored chop($DATE = `/bin/date '+%m/%d/%y %H:%M'`); $URL = 'scribble.com/thumb/'; #http:// gets prepended in href # fills out 2 or more open tiles with this text $NOTE = "created by $ME $DATE $URL"; $NO_NOTE = 1; #set this if you want no note created (which is fine by me) # but would be cool if you left the note in the html comments # # start of main functionality # $row = 1; $col = 1; ($INDEX_IMAGE,@IMAGES) = @ARGV; # would be nice NOT to die, but this will help prevent me from writing # over all my precious photos!! hah die "$INDEX_IMAGE exists!! first arg is the index image to create. usage: $0 index_image image1 image2 ...\n" if (-e $INDEX_IMAGE); $IMG_SRC = $INDEX_IMAGE; $IMG_SRC = $1 if ($IMG_SRC =~ /\/([^\/]+)$/); @IMAGES = sort(@IMAGES); #handle case where we have less images than $ACROSS $ACROSS = $#IMAGES + 1 if (($#IMAGES + 1) < $ACROSS); # if there are more than 7 rows, shrink the tile size and increase # across if ($#IMAGES > 41) { #more than 7 rows... $ACROSS = 7; $SIZE = 75; } print STDERR "across=$ACROSS, size=$SIZE\n"; foreach $image (@IMAGES) { push(@row_images,$image); ###print STDERR "($row,$col) -> $image\n"; if ($col == $ACROSS) { &do_row($row,@row_images); $col = 0; $row++; @row_images = (); } $col++; } # dropped out of above, but didnt finish current row: &do_row($row,@row_images) if ($col > 1); # NOT the above case, so $row is falsely incremented $row-- if ($col == 1); $ROWS = $row; #set as global reference to how many rows we made @all_rows = (); for ($i = 1 ; $i <= $ROWS ; $i++) { push(@all_rows,"${TMP}row$i.pnm"); #array of all row images } # do the magic to stack the rows!! $cmd = "$BIN/pnmcat -black -tb -jleft " . join(' ',@all_rows) . " | $BIN/cjpeg -quality 25 /dev/stdin > $INDEX_IMAGE"; print STDERR "combining to $INDEX_IMAGE\n"; ###print STDERR "($cmd)\n"; `$cmd`; print &build_html_index; #spit out the html `rm /tmp/index*`; #clean up #done! ## ## subroutines ## # build row image from (row_num,@images) sub do_row { my ($r,@i) = @_; my $i,$type,$cmd,$file,@f,$c,$name; @f = (); $c = 0; ###print STDERR "ROW: $r; " . join(',',@i) . "\n\n"; foreach $i (@i) { #each image $c++; #determine type of file... might vary by system!! chop($type = `file $i | cut -d' ' -f2`); #if not a valid type, try the extension of it (may be wrong!) if ($type !~ /^$VALID_TYPES$/i) { $type = $1 if ($i =~ /\.([^\/]+)$/); } print STDERR "BAD TYPE ($type)\n" if ($type !~ /^$VALID_TYPES$/i); #give up $type =~ tr/A-Z/a-z/; #shh, no shouting if ($type =~ /^gif$/i) { $cmd = "$BIN/giftopnm"; #converting a gif } elsif ($type =~ /^jpe?g$/i) { $cmd = "$BIN/djpeg -pnm"; #converting a jpeg } else { $cmd = $type . "topnm"; #may produce error, but what else can we do? } $name = $1 if ($i =~ /\/*([^\/]+)\.[^\/]*$/); #pulls out name (no ext) $file = "$TMP${row}-$c.pnm"; #destination file # special file info: $INFO{'R,C'} = description for javascript $INFO{sprintf("%05d,%05d",$row,$c)} = sprintf("$name (%sK $type) - %s",&nice_stat($i)); push(@f,$file); #@f is a list of all files being made for this row $cmd = "$cmd '$i' | $BIN/pnmscale -width $SIZE -height $SIZE > $file"; ##print STDERR "((($cmd)))\n"; `$cmd`; print STDERR sprintf("$r: %d/%d = $file\n",$c,$#i+1); # check to see if all went well... if (!(-s $file)) { #zero or non-existent file $cmd = "echo \"BAD!\n$name\n$type\" | $BIN/pbmtext | $BIN/pnmscale -width $SIZE -height $SIZE > $file"; `$cmd`; print STDERR "*** ERROR *** $i\n"; $INFO{sprintf("%05d,%05d",$row,$c)} = "***BAD***"; } } # handle the special case where we want to make an info tile, # which is actually 2 tiles wide. only do if 2 or more blank spots open. if (!$NO_NOTE && ($#i < ($ACROSS - 2))) { print STDERR "adding info block = ${TMP}info.pnm\n"; my $w = $SIZE * 2; #scale to 2x1 size-units `echo \"$NOTE\" | $BIN/pbmtext | $BIN/pnmcrop -right | $BIN/pnmcrop -bottom | $BIN/pnminvert | $BIN/pnmscale -width $w -height $SIZE > ${TMP}info.pnm`; push(@f,"${TMP}info.pnm"); #add this tile (x2) to array of this row # create the extra map line needed for html when info is used $EXTRA_MAP = "\n"; } $file = "${TMP}row$row.pnm"; #row file, now create it: $cmd = "$BIN/pnmcat -black -lr -jbottom " . join(' ',@f) . " > $file"; ###print STDERR "((($cmd)))\n"; `$cmd`; print STDERR " ROW $r -> $file\n"; } # creates the html. edit as you like! sub build_html_index { my $w = $ACROSS * $SIZE; my $h = $ROWS * $SIZE; my $map = ""; my $k,$r,$c,$f; # we get pieces and relative info from %INFO for $k (sort keys %INFO) { # $r and $c start counting at 1 (not 0), dont forget... ($r,$c) = split(/,/,$k); #results in something like (1,1) #the filename is found by looking in @IMAGES $f = $IMAGES[($r-1)*$ACROSS+($c-1)]; $r *= $SIZE; #convert to pixels $c *= $SIZE; $map .= sprintf("\n", $c-$SIZE,$r-$SIZE,$c,$r,$f,$INFO{$k}); } # once we get out, we use $c and $r to know where to put info tile $EXTRA_MAP = sprintf($EXTRA_MAP,$c,$r-$SIZE,$w,$h); # the rest is just html to return!! # would be nice to leave $NOTE in the comments, but remove if ya like return < $ME: $ID
created by $ME



$DATE $map $EXTRA_MAP ENDHTML } # a simple little routine to return (size,date) of a file sub nice_stat { my @date = stat($_[0]); my $size = $date[7]; #size will be in KB @date = localtime($date[9]); #work actual date out $date[4]++; #month (sprintf("%.1f",$size/1024),sprintf("%d/%d/%d %02d:%02d",@date[4,3,5,2,1])); }