[TriLUG] Digital Photos, Thumbnails, and Web Pages
William Sutton
william at trilug.org
Tue Dec 6 06:38:17 EST 2005
While we're throwing home-grown scripts into the mix...
attached is a Perl script I wrote some time ago to archive phtoos/desktop
wallpapers/graphic art/etc that I come up with...its chief features are
the ability to specify the following:
- max thumb height
- max thumb width
- max thumbs per column
- max sample thumbs
- alternating row display colors to group similar items
plus it stores an md5sum hash of photo information so that you can add
images to a directory and have them processed without reprocessing the
entire thing....good if--like me--you have lots of photocds lying around
see the comments in the code for details
if the attachment gets stripped, you can retrieve it from wget
http://trilug.org/~william/dl/index.pl
create a directory /home/your_name/gallery/scripts and drop the program in
the scripts directory; your galleries go in /home/your_name/gallery
(adjust in code to suit)
requires ImageMagick, Image::Magick (Perl module), and File::Slurp
I could make it use XML::Simple to take the input parameters as an XML
file and Getopts::Long to take named parameters if that's your thing....
--
William Sutton
On Tue, 6 Dec 2005, John F. Davis wrote:
> On Mon, Dec 05, 2005 at 07:48:21AM -0500, Scott Chilcote wrote:
> > Hi Folks,
> >
> > After taking several pictures at our Thanksgiving event last month, I
> > got requests to send the pictures to some of my relatives. I'm pretty
> > sure they don't want thirty or so 3-megapixel images arriving in their
> > mailboxes.
> >
> ...
> stuff deleted
> ...
> >
> > I'm looking for something basic. I'd write it myself if I had less
> > going on right now.
> >
> > What are other people using to accomplish this?
> >
>
> Hello,
>
> I wrote a simple script which generates thumbnails and creates web page
> with links to them in bash. It does not generate the thumbnails on the
> fly. Intead it simply creates them as permanent files on the disk. In
> my opinion disk space is cheap now days, but cpu cycles and time are
> not.
>
> If you are interested, here is the result
>
> http://www.trilug.org/~davis/nov_30
>
> and here is portion of the code:
>
> Happy Trails,
>
> John F. Davis
>
> ...........................
> makepicpage.sh
> ..........................
> #!/bin/bash
>
> page="index.html"
> >$page
>
> cat ~/bin/template.head > $page
>
>
> printf "<Table>\n" >> $page
> let i=0;
> for filename in *.jpg *.JPG ; do
> test -f "$filename" || continue;
> [[ "$filename" != *-t.jpg ]] || continue;
> [[ "$filename" != *-t.JPG ]] || continue;
>
> if ((i%5==0)) ; then
> let j=0;
> printf "<TR>\n" >> $page
> else
> ((j++))
> fi
>
> printf "<TD>" >> $page
> stem=${filename%.*};
> extension=${filename##*.};
>
> printf "<a href=\"%s\"><img src=\"%s\"></a>" "$filename" "$stem-t.$extension" >> $page
> printf "</TD>\n" >> $page
>
> if ((j==4)) ; then
> printf "</TR>\n" >> $page
> fi
>
> ((++i));
>
> makethumbs.sh $filename ;
> if [[ $? -ne 0 ]] ; then
> echo "failure. makethumbs.sh failed."
> exit
> fi
>
> done
>
>
> printf "</Tbody>\n" >> $page
> printf "</Table>\n" >> $page
>
> cat ~/bin/template.footer >> $page
>
> exit
>
> .......................
> makethumbs.sh
> .......................
>
> #!/bin/bash
> # check for proper parms
> if [ $# -ne 1 ] ; then
> echo "usage: $0 <input file>
> echo "eg. $0 file1.jpg
> fi
>
> # find the file extension part
> #echo $1
> # %.* deletes one match of "period anything" from the end.
> stem=${1%.*}
> # ##*. deletes as many matches of "anything period" that exist.
> extension=${1##*.}
> #echo $stem
> #echo $extension
>
>
> convert $1 -thumbnail 100x100 $stem-t.$extension
> if [ $? -ne 0 ] ; then
> echo "failure. convert failed to convert file."
> exit
> fi
>
>
>
-------------- next part --------------
#!/usr/bin/perl
use strict;
use Data::Dumper;
use File::Slurp;
use Image::Magick;
################################################################################
#
################################################################################
# notes:
# expects a directory structure of the following:
# /home/your_name/gallery
# /photos
# /2005-10-20
# /2005-10-21
# /2005-11-15
# /art
# /2004-05-30
# /2004-07-19
# ...
my $root = "/home/your_name/gallery"; # top gallery directory
my $dump_file = "$root/scripts/dump.txt"; # Data::Dumper file
my $md5sum = "/usr/bin/md5sum"; # md5sum program
my $catalog;
my $color0 = "FFFFFF";
my $color1 = "AAAAAA";
my $max_thumb_x = 150; # max allowable thumb width
my $max_thumb_y = 150; # max allowable thumb height
my $max_thumb_col = 5; # max thumbs per column
my $max_thumb_sample = 10; # max number of sample thumbs on index pages
# (shows all thumbs on detail pages)
################################################################################
#
################################################################################
# preload a data file containing information about known images and thumbs;
# this stops us from reprocessing things; the eval() reads a Data::Dumper
# formatted output
if (-e $dump_file)
{
my $dump_data = read_file($dump_file);
$dump_data =~ s/VAR1/catalog/;
eval($dump_data);
}
else
{
$catalog = {};
}
# operate per top directory
my @top_dirs = map { chomp($_); $_; } `ls -1 $root`;
foreach my $top_dir (@top_dirs)
{
next unless (-d "$root/$top_dir");
next if $top_dir eq "scripts";
print "* working on $top_dir\n";
my @gallery_dirs = map { chomp($_); $_; } `ls -1 $root/$top_dir`;
# operate per gallery directory
foreach my $gallery_dir (@gallery_dirs)
{
next unless (-d "$root/$top_dir/$gallery_dir");
print " * working on $top_dir - $gallery_dir\n";
my @gallery_files =
map { chomp($_); $_; } `ls -1 $root/$top_dir/$gallery_dir`;
# operate per gallery file
foreach my $gallery_file (@gallery_files)
{
next unless (-f "$root/$top_dir/$gallery_dir/$gallery_file");
next if $gallery_file =~ m/\.html/;
# rename if filename is mixed case
if ($gallery_file ne lc($gallery_file))
{
print " * lc($gallery_file)\n";
my $new_file = lc($gallery_file);
`mv $root/$top_dir/$gallery_dir/$gallery_file $root/$top_dir/$gallery_dir/$new_file`;
$gallery_file = $new_file;
}
# see if we can skip the file
my $sum = `$md5sum $root/$top_dir/$gallery_dir/$gallery_file`;
chomp($sum);
$sum =~ s/\s+.+$//;
my $catalog_sum =
$catalog->{$top_dir}->{$gallery_dir}->{$gallery_file}->{md5sum};
#print " * $catalog_sum ?= $sum\n";
next if $catalog_sum eq $sum;
print " * working on $gallery_file\n";
# analyze the file and catalog its data
my $pm = new Image::Magick;
$pm->Read("$root/$top_dir/$gallery_dir/$gallery_file");
my $file_data = {
path => "$root/$top_dir/$gallery_dir",
name => $gallery_file,
height => $pm->Get('height'),
width => $pm->Get('width'),
'x-resolution' => $pm->Get('x-resolution'),
'y-resolution' => $pm->Get('y-resolution'),
'md5sum' => $sum,
};
$catalog->{$top_dir}->{$gallery_dir}->{$gallery_file} = $file_data;
# now, operate on the data
# need to create a thumbnail
my $thumbnail = "$root/$top_dir/$gallery_dir/thumb/$gallery_file";
unless (-e $thumbnail)
{
unless (-d "$root/$top_dir/$gallery_dir/thumb/")
{
print " * making thumb dir\n";
`mkdir $root/$top_dir/$gallery_dir/thumb`;
}
my $scaling_factor = 0;
if ($file_data->{width} > $file_data->{height})
{
$scaling_factor = $max_thumb_y / $file_data->{width};
}
else
{
$scaling_factor = $max_thumb_x / $file_data->{height};
}
my $scaled_x = int($file_data->{width} * $scaling_factor);
my $scaled_y = int($file_data->{height} * $scaling_factor);
$pm->Scale(width => $scaled_x, height => $scaled_y);
$pm->Write($thumbnail);
}
}
}
}
print "\n* saving catalog\n";
write_file($dump_file, Dumper($catalog));
print "\n\n";
#print Dumper $catalog;
print "* creating general index\n";
my @galleries = sort keys %{$catalog};
my $html = "";
foreach my $gallery (@galleries)
{
print "* creating samples for $gallery\n";
my $gallery_title = "$gallery gallery";
my @gallery_samples = undef;
my $sample_count = 0;
my $i = 0;
my $j = 0;
my $set_count = scalar keys %{$catalog->{$gallery}};
foreach my $set (sort keys %{$catalog->{$gallery}})
{
last if ($sample_count == $max_thumb_sample);
print " * working on set $set\n";
if ($j == $max_thumb_col)
{
$i++;
$j = 0;
}
my @files = (
map { $catalog->{$gallery}->{$set}->{$_}; }
sort keys %{$catalog->{$gallery}->{$set}}
);
$gallery_samples[$i][$j] = $files[0];
$j++;
$sample_count++;
}
$html .= <<END_HTML;
<B>$gallery_title</B> <FONT SIZE="-1" COLOR="#666666">($set_count sets)</FONT><BR><BR>
<TABLE CELLPADDING="5" CELLSPACING="0" BORDER="0">
END_HTML
foreach my $row (@gallery_samples)
{
$html .= <<END_HTML;
<TR>
END_HTML
#print Dumper $row;
foreach my $col (@{$row})
{
$html .= <<END_HTML;
<TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"><A HREF="$root/$gallery/index.html"><IMG SRC="$col->{path}/thumb/$col->{name}" ALT="$col->{path}" BORDER="0"></A></TD>
END_HTML
}
$html .= <<END_HTML;
</TR>
END_HTML
}
$html .= <<END_HTML;
</TABLE>
<BR>
END_HTML
}
write_file("$root/index.html", body_html("General Gallery Index", $html));
foreach my $gallery (@galleries)
{
print "* creating index for $gallery\n";
$html = "";
my $gallery_title = "$gallery gallery";
my $i = 0;
my $j = 0;
$html .= <<END_HTML;
<B>$gallery_title</B><BR><BR>
<TABLE CELLPADDING="5" CELLSPACING="0" BORDER="0">
END_HTML
my $highlight = 1;
my $group = "";
my @colors = ($color0, $color1);
foreach my $set (sort keys %{$catalog->{$gallery}})
{
print " * working on set $set\n";
$set =~ m/^(\d+)-/;
my $block = "$1";
if ($block ne $group)
{
$group = $block;
$highlight = ($highlight == 1 ? 0 : 1);
}
my @files = (
map { $catalog->{$gallery}->{$set}->{$_}; }
sort keys %{$catalog->{$gallery}->{$set}}
);
my $pic_count = scalar(@files);
$html .= <<END_HTML;
<TR BGCOLOR="#$colors[$highlight]">
<TD COLSPAN="$max_thumb_col"><I>$set set</I> <FONT SIZE="-1" COLOR="#000000">($pic_count pics)</FONT></TD>
</TR>
<TR BGCOLOR="#$colors[$highlight]">
END_HTML
for (my $j = 0 ; $j < $max_thumb_col ; $j++)
{
if (!defined $files[$j])
{
$html .= <<END_HTML;
<TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"></TD>
END_HTML
}
else
{
my $col = $files[$j];
$html .= <<END_HTML;
<TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"><A HREF="$col->{path}/index.html"><IMG SRC="$col->{path}/thumb/$col->{name}" ALT="$col->{path}" BORDER="0"></A></TD>
END_HTML
}
}
$html .= <<END_HTML;
</TR>
END_HTML
}
$html .= <<END_HTML;
</TABLE>
<BR>
END_HTML
write_file("$root/$gallery/index.html", body_html($gallery_title, $html));
}
foreach my $gallery (@galleries)
{
print "* working on gallery $gallery\n";
my $i = 0;
my $j = 0;
foreach my $set (sort keys %{$catalog->{$gallery}})
{
print " * working on set $set\n";
my @files = (
map { $catalog->{$gallery}->{$set}->{$_}; }
sort keys %{$catalog->{$gallery}->{$set}}
);
#print Dumper $catalog->{$gallery}->{$set};
my $num_thumbs = scalar(@files);
my $thumb_count = 0;
$html = <<END_HTML;
<B>$set set</B><BR><BR>
<TABLE CELLPADDING="5" CELLSPACING="0" BORDER="0">
END_HTML
while ($thumb_count < $num_thumbs)
{
$html .= <<END_HTML;
<TR>
END_HTML
for (my $j = 0 ; $j < $max_thumb_col ; $j++)
{
if (!defined $files[$thumb_count])
{
$html .= <<END_HTML;
<TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"></TD>
END_HTML
}
else
{
my $col = $files[$thumb_count];
$html .= <<END_HTML;
<TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"><A HREF="$col->{path}/$col->{name}"><IMG SRC="$col->{path}/thumb/$col->{name}" ALT="$col->{path}" BORDER="0"></A></TD>
END_HTML
}
$thumb_count++;
}
$html .= <<END_HTML;
</TR>
END_HTML
}
$html .= <<END_HTML;
</TABLE>
<BR>
END_HTML
write_file("$root/$gallery/$set/index.html",
body_html("$set set", $html));
}
}
################################################################################
#
################################################################################
sub body_html
{
my $title = shift;
my $body = shift;
my $HTML = <<END_HTML;
<HTML>
<HEAD>
<TITLE>$title</TITLE>
</HEAD>
<BODY>
$body
</BODY>
</HTML>
END_HTML
}
More information about the TriLUG
mailing list