#!/usr/bin/perl # thumbnail.pl, copyright Casey Muller # a somewhat specialized image thumbnailing script use POSIX; $topdir = "/usr/media/images/digitalcamera/"; $tagdir = "/usr/media/images/tags/"; $recentfile = "/usr/media/web/generate/recentPhotos"; $locationmapfile = "/usr/media/web/generate/root/null-terminated/visuals/photography/map/map.rss"; $locationtripfile = "/usr/media/web/generate/root/null-terminated/visuals/photography/map/trip.rss"; $datelocfile = "/usr/media/images/dateloc"; $currentloc = ""; $locstarted = "present"; $prefix = "http://images.null-terminated.com/"; $encodedprefix = "http%3A%2F%2Fimages.null-terminated.com%2Fdigitalcamera%2F"; $formdir = "http://home.null-terminated.com:81/cgi-bin/"; $tagform = $formdir."suggesttag.pl"; $multitagform = $formdir."multitagsug.pl"; $thumbpath = "/visuals/photography/by-date/"; $thumbprefix = "http://null-terminated.com".$thumbpath; $tagpath = "/visuals/photography/tags/"; $tagprefix = "http://null-terminated.com".$tagpath; $imageproc = "-normalize -unsharp 3"; $sizes{"tiny"} = "-size 36x24 -resize 36x24 +profile \"*\" $imageproc"; #$sizes{"tiny"} = "-size 48x32 -resize 48x32 +profile \"*\" $imageproc"; $sizes{"thumb"} = "-size 320x240 -resize 320x240 +profile \"*\" $imageproc"; #$sizes{"thumb"} = "-size 480x320 -resize 480x320 +profile \"*\" $imageproc"; $sizes{"medium"} = "-size 1024x1200 -resize 1024x1200"; # load the location mappings require 'encodedlocs.pl'; # open recent file open(RECENT, '>', $recentfile); # open date location file open(DATELOC, '>', $datelocfile); # open the main index open(HTML, '>', $topdir."contactsheet.html"); print HTML <






Once the images have loaded, mousing over them should reveal a larger thumbnail.
HEADER $today = strftime "%Y-%m-%dT%H:%M:%SZ", gmtime(); open(RSS, '>', $topdir."allphotos.rss"); #open(RSS, '>', $topdir."photos.rss"); $photocount = 0; $datecount = 0; print RSS < null-terminated photography $today Casey Muller atomfeed\@nullterminated.com RSSHEADER system("cp", $topdir."allphotos.rss", $locationmapfile); system("cp", $topdir."allphotos.rss", $locationtripfile); system("cp", $topdir."allphotos.rss", $topdir."allphotodates.rss"); open(DATERSS, '>>', $topdir."allphotodates.rss"); use File::Find; use Image::EXIF; $exif = new Image::EXIF; find { preprocess => sub { # calculate the path $dir = substr $File::Find::dir, length($topdir); print HTML "

$prefix$dir

\n"; # open the directory-level html file if($dir =~ /_\d\d$/) { print "checking $File::Find::dir\n"; open(DIR, '>', "$File::Find::dir/index.html"); print DIR "
\n"; print DIR "\n"; if(/(\d+)_(\d+)_(\d+)/) { $dirsummary = "Photography from $2/$3/$1"; $rssdate = "$1-$2-$3T12:00:00-08:00"; } else { $dirsummary = "Photography from $dir"; $rssdate = $today; } print DIR "$dirsummary\n\n"; $datersscounter = 0; print DATERSS < $dirsummary $dir $rssdate $rssdate 0) { $_ = $_[$i-1]; if(/\.[Jj][Pp][Gg]$/ and !/^tiny/ and !/^thumb/ and !/^medium/) { $previmage{$_[$i]} = $_; } } } return @_; } else { #directories sorted by reverse date reverse sort @_; } }, wanted => sub { /^\./ && return; if(/\.[Jj][Pp][Gg]$/ and !/^tiny/ and !/^thumb/ and !/^medium/) { $name = $_; # get the exif data $#settings = -1; $exif->file_name($File::Find::name); $info = $exif->get_camera_info(); $lens = $info->{"Lens Size"}; $info = $exif->get_image_info(); $exposure = $info->{"Exposure Time"}; push @settings, $exposure; $aperture = $info->{"Lens Aperture"}; push @settings, $aperture; $focal = $info->{"Focal Length"}; if($lens == "") { # fixed primes don't have a lens $lens = $focal; } push @settings, "lens".$lens; $iso = $info->{"ISO Speed Rating"}; push @settings, "iso".$iso; $created = $info->{"Image Created"}; # clean up this crap $created =~ s/(\d+):(\d+):(\d+) +(\d+):(\d+):(\d+)/$1-$2-$3T$4:$5:$6-08:00/; $distance = $info->{"Subject Distance"}; @commenttags = split('\|', $info->{"Comment"}); if($#commenttags < 0) { # no comments or tags $comment = ""; $titlecomment = ""; $#commenttags = -1; $#tags = -1; $tagurls = ""; $alltagurls = ""; } else { $comment = shift @commenttags; if(length $comment > 0) { $titlecomment = " title=\"$comment\""; } else { $titlecomment = ""; } if($#commenttags > -1) { # get user tags $tagurls = "

"; $fulltagurls = "

"; $tagcats = ""; $mediacats = ""; $alltagurls = "

"; @tags = split ' ', $commenttags[0]; } else { $#tags = -1; } # make tags for the technical settings foreach $faketag (@settings) { # remove the whitespace $faketag =~ s/ //g; # and trailing zeros $faketag =~ s/\.00//g; if($faketag ne "") { # mark this as a tech tag if it exists $techtags{$faketag} = "yes"; push @tags, $faketag; } } $loctag = "unknown"; foreach $tag (@tags) { $tag = lc $tag; ($safetag = $tag) =~ s#/#-#g; # a location tag? if(exists $locationtag{$tag}) { $loctag = $tag; } # do we need a new file if(!exists $tagfiles{$tag}) { print "creating file for tag: $tag ($safetag)\n"; open($tagfiles{$tag}, '>', $tagdir.$safetag.".html"); print { $tagfiles{$tag} } <

tag: $tag









Once the images have loaded, mousing over them should reveal a larger thumbnail.
HTMLBLOCK # keep track of the latest pic $lastpicture{$tag} = "$thumbpath$dir/tiny$name"; } # add ourselves print { $tagfiles{$tag} } "\n"; $alltagurls .= " ($tag)"; if(!exists $techtags{$tag}) { $tagurls .= " ($tag)"; $fulltagurls .= " ($tag)"; $tagcats .= ""; $mediacats .= "$tag,"; } # increment the counters $tagcount{$tag}++; } $fulltagurls .= "

"; $tagcats .= ""; if($loctag ne "") { if(length $locationlist{$loctag} < 1000) { $locationlist{$loctag} .= ""; if(length $locationlist{$loctag} >= 1000) { $locationlist{$loctag} .= "see more $loctag"; } } if($loctag ne $currentloc) { # new location print DATELOC "$loctag: $dir - $locstarted\n"; if($datersscounter > 1) { print DATERSS "

Possible aspect change in target: $loctag

\n"; $datersscounter = 1; } push @mapcoords, $loctag; $currentloc = $loctag; $locstarted = $dir; } } } foreach(keys(%sizes)) { if(!-e "$File::Find::dir/$_$name") { print "$name ($_) in $File::Find::dir\n"; system("convert $sizes{$_} $File::Find::name $File::Find::dir/$_$name"); } } if(1 || !-e "$File::Find::dir/$name.html") { # if(!-e "$File::Find::dir/$name.html") { open(FILE, '>', "$File::Find::dir/$name.html"); $encodedurl = "$encodedprefix$dir/$name"; $encodedurl =~ s!/!%2F!g; #http%3A%2F%2Fbigfiles.null-terminated.com%2Fdigitalcamera%2F2005_07_05%2FIMG_3251.JPG print FILE "
Get a postcard or t-shirt! Want to use this image another way?

\n

$comment

Basic settings: $exposure $aperture @ ISO $iso with $focal from lens ($lens) focused on $distance at $created

$alltagurls

\n"; print FILE < add tags

HTMLBLOCK # previous and next links print FILE "Navigate:\n"; if(exists $previmage{$name}) { print FILE "prev\n"; } print FILE "index\n"; if(exists $nextimage{$name}) { print FILE "next\n"; } print FILE "\n"; print FILE "Non-coralized links: medium and large (try these in case of problems).\n\n"; print FILE "

Full EXIF data:

\n"; $info = $exif->get_all_info(); foreach(sort keys %$info) { uc; print FILE "

$_

\n"; $subinfo = $info->{$_}; foreach(keys %$subinfo) { print FILE "$_ = ".$subinfo->{$_}."
\n"; } } close FILE; } print HTML "\n"; if($photocount < 20) { print RECENT "\n"; } print DIR <

$comment

$exposure $aperture @ $focal

$tagurls add

HTMLBLOCK if($datersscounter++ < 2) { print DATERSS <

RSSBLOCK } $date = $dir; $date =~ s/_/-/g; print RSS < $name $dir/$name $created $created

$exposure $aperture @ ISO $iso with $focal from lens ($lens) focused on $distance at $created

$fulltagurls ]]>
$locationtag{$loctag} $name $name $mediacats atomfeed\@nullterminated.com $tagcats RSSBLOCK if($photocount++ == 50) { system("cp", $topdir."allphotos.rss", $topdir."photos.rss"); open(SMALLRSS, '>>', $topdir."photos.rss"); print SMALLRSS "\n"; close SMALLRSS; } } }, postprocess => sub { close DIR; print DATERSS <See all photos from this day

]]>
RSSBLOCK if($datecount++ == 20) { system("cp", $topdir."allphotodates.rss", $topdir."photodates.rss"); open(SMALLDATERSS, '>>', $topdir."photodates.rss"); print SMALLDATERSS "
\n"; close SMALLDATERSS; } }}, $topdir; close HTML; print RSS "\n"; close RSS; print DATERSS "\n"; close DATERSS; open(TAGS, '>', $tagdir."index.html"); print TAGS "Content tags:\n"; foreach(keys %tagfiles) { if(!exists $techtags{$_}) { if($tagcount{$_} > $maxtagcount) { $maxtagcount = $tagcount{$_}; } if($tagcount{$_} < $mintagcount) { $mintagcount = $tagcount{$_}; } } } foreach(sort keys %tagfiles) { ($safetag = $_) =~ s#/#-#g; # size is 0 to 1 $size = ($tagcount{$_} - $mintagcount) / ($maxtagcount - $mintagcount); # interpolate $fontsize = $size * 36 + 9; $imagesize = int($size * 12 + 12); $taghtml = "$_($tagcount{$_}) \n"; print "last: $lastpicture{$_}\n"; if(exists $techtags{$_}) { print "tech "; $techhtml .= $taghtml; } else { print TAGS $taghtml; } print "$_ = $tagcount{$_}\n"; close $tagfiles{$_}; } # open location files open(MAPRSS, '>>', $locationmapfile); # write the locationsf foreach(sort keys %locationlist) { print MAPRSS < $_ $_ $today $today $locationtag{$_} RSSBLOCK } # footer print MAPRSS "\n"; close MAPRSS; print TAGS "\n\nOr look at the technical tags.\n"; close TAGS; open(TAGS, '>', $tagdir."technicaltags.html"); print TAGS "\n\nTechnical tags:\n$techhtml"; close TAGS; open(TRIPRSS, '>>', $locationtripfile); for($i=0; $i<$#mapcoords; $i++) { print TRIPRSS < $mapcoords[$i] to $mapcoords[$i+1] $mapcoords[$i] $today $today $locationtag{$mapcoords[$i]} $locationtag{$mapcoords[$i+1]} RSSBLOCK } print TRIPRSS "\n"; close TRIPRSS;