#!/bin/sh -- # A comment mentioning perl eval 'exec perl -S $0 ${1+"$@"}' if 0; chop($Program = `basename $0`); chomp($Title0 = 'Photos: ' . `date +%m-%d-%y`); $Debug = 0; $N_from = ''; $N_to = ''; $N_string = ''; $N_shift = ''; $Merge = ''; $Gphoto_Cmd = 'gphoto'; $yaya = 1 if `hostname` =~ /haystack/ || $ENV{USER} eq 'runge'; $Gphoto_Cmd = "gw $Gphoto_Cmd" if $yaya; $Use_convert = 0; $convert_Small_Cmd_geometry = "convert -blur 60 -quality 75 -sample %GEOM '%OLD' '%NEW'"; $convert_Small_Cmd_shrink_by_2 = "convert -blur 60 -quality 75 -geometry 50%x50% '%OLD' '%NEW'"; $djpeg_Small_Cmd_geometry = "djpeg '%OLD' | pnmscale -xysize %GEOM | cjpeg -quality 75 -outfile '%NEW'"; $djpeg_Small_Cmd_shrink_by_2 = "djpeg '%OLD' | pnmscale 0.5 | cjpeg -quality 75 -outfile '%NEW'"; #$djpeg_Small_Cmd_shrink_by_2 = "djpeg -scale 1/2 '%OLD' | cjpeg -quality 75 -outfile '%NEW'"; $Filter_Cmd = ''; $Small_Geometry = 'halfsize'; $Make_Small = 1; $Small_Subdir = 'Small'; $Large_Width = 1000; $Source_Dir = ''; $Redo_Thumbnails = 1; $Download_Thumbnails = 1; $Do_Deletes = 0; $Order_Only = 1; $Do_Moves = 0; $Do_Copy_Only = 0; $Move_Dir = ''; $Renum_Dir = ''; $Do_URL_Always = 0; $Columns = 4; $Dfmt = '%03d'; $Start_Date = scalar(localtime); ################################################################################## $Usage = <<"END"; $Program: Use gphoto to download images and thumbnails from camera and make a simple html interface. Usage: $Program Options: -T Set the title of the photo collection. -f <n> Start downloading from image <n> -t <n> Download only up to image <n> -n n1,n2,... Only download images in comma separated list. Can be range too -n 6,10-18 -shift <n> Shift the image numbering (output files) by amount <n>. -html or -H Only make the html for output_dir (this will update the small images, unless given by -html_only or -HO). -order_only or -O Only use images in Set.order, do not append orphans to the end. (the default) -order_append or -OA First use images in Set.order, then append orphans to the end. -small Only make/update the small image section -no_small Do not make the small image section. -small_size <geom> Set the geom of small images. Def: $Small_Geometry -filter <cmd> Filter ALL downloaded photos with the command which must be of the form: filter_command -args %OLD %NEW -large_width w Set the cutoff pixel for a large photo -lw w (default $Large_Width) -in <dir> Read images from input directory <dir>, e.g. a mounted flash memory card, perhaps this on haystack: -in /auto/smartmedia -m <merge_dir> Merge all the images (with renumbering) in the output_dirs into a single directory, <merge_dir> -u Launch the URL browser no matter what. -D <number> ... In current directory (an outdir), remove all files associated with an number. Use two -D for no prompts about removal. Three for no sleep before removal. <number> can be individual numbers, or list n,m,k or range n-m -M <dir> <number> ... Like -D but move them to directory <dir> instead of deleting. -C <dir> <number> ... Like -M but copy them to directory <dir> -R <dir> Renumber everything starting from 001 and place in <dir> NOTE: for -D -M -C -R you must be in the top of the photo source directory. -nt Do not remake the small thumbnails. -dt Download the small thumbnails only. Notes: Programs needed: gphoto, convert, image_size If the size of an image is more than 1000 pixels wide, it is saved to "large-NNN.jpg" and shrunk by 50%. A link to the very large image is provided for printing. END @ALL_ARGS = @ARGV; select(STDERR); $| = 1; select(STDOUT); $| = 1; LOOP: while (@ARGV) { $_ = shift; CASE: { /^-T$/ && ($Title = shift, last CASE); /^-n$/ && ($N_string = shift, last CASE); /^-f$/ && ($N_from = shift, last CASE); /^-t$/ && ($N_to = shift, last CASE); /^-shift$/ && ($N_shift = shift, last CASE); /^-d$/ && ($Debug = 1, last CASE); /^-m$/ && ($Merge = shift, last CASE); /^(-in|-s)$/ && ($Source_Dir = shift, last CASE); /^-nt$/ && ($Redo_Thumbnails = 0, last CASE); /^-dt$/ && ($Download_Thumbnails = 2, last CASE); /^-small$/ && ($Make_Small = 2, last CASE); /^-filter$/ && ($Filter_Cmd = shift, last CASE); /^-small_size$/ && ($Small_Geometry = shift, last CASE); /^(-lw|-large_width)$/ && ($Large_Width = shift, last CASE); /^-no_small$/ && ($Make_Small = 0, last CASE); /^(-html|-H)$/ && ($HTML_only = 1, last CASE); /^(-html_only|-HO)$/ && ($HTML_only = 2, last CASE); /^(-order_only|-O)$/ && ($Order_Only = 1, last CASE); /^(-order_append|-OA)$/ && ($Order_Only = 0, last CASE); /^-u$/ && ($Do_URL_Always = 1, last CASE); /^-D$/ && ($Do_Deletes = 1, last CASE); /^-DD$/ && ($Do_Deletes = 2, last CASE); /^-DDD$/ && ($Do_Deletes = 3, last CASE); /^-M$/ && ($Do_Moves = 1, $Move_Dir = shift, last CASE); /^-MM$/ && ($Do_Moves = 2, $Move_Dir = shift, last CASE); /^-MMM$/ && ($Do_Moves = 3, $Move_Dir = shift, last CASE); /^-C$/ && ($Do_Moves = 1, $Move_Dir = shift, $Do_Copy_Only = 1, last CASE); /^-CC$/ && ($Do_Moves = 2, $Move_Dir = shift, $Do_Copy_Only = 1, last CASE); /^-CCC$/ && ($Do_Moves = 3, $Move_Dir = shift, $Do_Copy_Only = 1, last CASE); /^-R$/ && ($Renum_Dir = shift, last CASE); /^--$/ && (last LOOP); # -- means end of switches /^-(-.*)$/ && (unshift(@ARGV, $1), last CASE); /^(-h|-help)$/ && ((print STDOUT $Usage), exit 0, last CASE); if ( /^-(..+)$/ ) { # split bundled switches: local($y, $x) = ($1, ''); foreach $x (reverse(split(//, $y))) { unshift(@ARGV,"-$x") }; last CASE; } /^-/ && ((print STDERR "Invalid arg: $_\n$Usage"), exit 1, last CASE); unshift(@ARGV,$_); last LOOP; } } use File::Basename; sub date_finish { my $fin = scalar(localtime); print STDERR "\nStart: $Start_Date\n"; print STDERR "Finish: $fin\n"; } if ( $Merge ) { merge_dirs($Merge, @ARGV); if ( ! -d $Merge ) { die "some problem with merging... $!\n"; } # duh collect the args and call ourselves again. my @args = (); while (@ALL_ARGS) { my $arg = shift(@ALL_ARGS); if ( $arg eq '-m' ) { shift(@ALL_ARGS); next; } foreach my $argv (@ARGV) { if ( $arg eq $argv ) { @ALL_ARGS = (); $arg = ''; last; } } push (@args, $arg) if $arg; } print STDERR "\n >>>> creating HTML via: $0 -html -order_append @args, $Merge\n\n"; sleep 1; system $0, '-html', '-order_append', @args, $Merge; $rc = $?; &show_html("$Merge/index.html") if $Do_URL_Always; &date_finish(); exit($rc/255); } elsif ( $Do_Deletes ) { delete_numbers(@ARGV); &date_finish(); exit 0; } elsif ( $Do_Moves ) { move_numbers($Move_Dir, @ARGV); &date_finish(); exit 0; } elsif ( $Renum_Dir ) { renumber($Renum_Dir); &date_finish(); exit 0; } if ($Use_convert) { if ($Small_Geometry eq 'halfsize' || $Small_Geometry eq '50%x50%') { $Small_Cmd = $convert_Small_Cmd_shrink_by_2; } else { $Small_Cmd = $convert_Small_Cmd_geometry; $Small_Cmd =~ s/%GEOM/$Small_Geometry/; } $Shrink_by_2_Cmd = $convert_Small_Cmd_shrink_by_2; $Small_Geom_Cmd = $convert_Small_Cmd_geometry; $Small_Geom_Cmd_x = 'x'; } else { if ($Small_Geometry eq 'halfsize' || $Small_Geometry eq '50%x50%') { $Small_Cmd = $djpeg_Small_Cmd_shrink_by_2; } else { $Small_Cmd = $djpeg_Small_Cmd_geometry; my $geom = $Small_Geometry; $geom =~ s/x/ /; $Small_Cmd =~ s/%GEOM/$geom/; } $Shrink_by_2_Cmd = $djpeg_Small_Cmd_shrink_by_2; $Small_Geom_Cmd = $djpeg_Small_Cmd_geometry; $Small_Geom_Cmd_x = ' '; } $Dir = shift; if ( $Dir eq '' ) { chomp($Dir = 'pics-' . `date +%m-%d-%y`); } if ( ! -d $Dir ) { system("mkdir -p '$Dir'"); } if ( ! -d $Dir ) { die "No $Dir: $!\n"; } print STDERR "\nOutput dir is: $Dir\n\n"; if ( $HTML_only || $Make_Small == 2 ) { # no downloading needed. if ($Make_Small && $HTML_only != 2 ) { update_smalls($Dir, $Small_Subdir); } if ( $Make_Small == 2 ) { make_html($Dir, $Small_Subdir); } else { make_html($Dir); make_html($Dir, $Small_Subdir) if $Make_Small; } print STDERR "\nurl $Dir/index.html\n"; &show_html("$Dir/index.html") if $Do_URL_Always; &date_finish(); exit 0; } if ($Source_Dir) { my @list; if (! -d $Source_Dir) { @dirs = split(/,/, $Source_Dir); } else { @dirs = ($Source_Dir); } foreach my $dir (@dirs) { open(FIND, "find '$dir' -iname '*.jpg'|") || die "$!"; while (<FIND>) { chomp; next if $_ =~ /\.xvpics/; push(@list, $_); } close(FIND); open(FIND, "find '$dir' -iname '*.jpeg'|") || die "$!"; while (<FIND>) { chomp; next if $_ =~ /\.xvpics/; push(@list, $_); } close(FIND); } @Source_Pics = sort(@list); $N = scalar(@list); $Download_Thumbnails = 0; } else { chomp($N = `$Gphoto_Cmd -n`); if ( $N !~ /^\d+$/ || $N == 0 ) { print STDERR "Bad number $N, trying again ...\n"; sleep 4; chomp($N = `$Gphoto_Cmd -n`); } if ( $N !~ /^\d+$/ || $N == 0 ) { print STDERR "Bad number $N, trying again ...\n"; sleep 4; chomp($N = `$Gphoto_Cmd -n`); } if ( $N !~ /^\d+$/ ) { die "Bad number: $N\n"; } } if ( $N_string ne '' ) { if ($N_from ne '' || $N_to ne '') { print STDERR "do not specify both -n and -f/-t\n"; exit 1; } foreach my $n (split(/,/, $N_string)) { if ($n =~ /-/) { my $n1 = $`; my $n2 = $'; if ( $n1 !~ /^\d+$/ || $n2 !~ /^\d+$/ || $n2 < $n1) { print STDERR "Bad -n number $n\n"; exit 1; } foreach my $n3 ($n1 .. $n2) { $N_only{$n3}++; } } else { $N_only{$n}++; } } } print STDERR "\nDownloading "; if ( %N_only ) { print STDERR "images $N_string from $N total "; } else { print STDERR "$N images "; } if ( $N_from ne '' ) { print STDERR ">= $N_from "; } if ( $N_to ne '' ) { print STDERR "<= $N_to "; } print STDERR "...\n\n"; $start_time = time; $total_size = 0; $count = 0; $converting = 0; for ($i=1; $i<=$N; $i++) { next if $N_from ne '' && $i < $N_from; next if $N_to ne '' && $i > $N_to; if ( %N_only && ! exists($N_only{$i}) ) { next; } $n = $i; if ( $N_shift ne '' ) { if ( $N_shift !~ /^\d+$/ ) { print STDERR "*** bad shift: $N_shift ***\n"; exit 1; } $n += $N_shift; } $n = sprintf("$Dfmt", $n); $count++; my $th = "$Dir/thumb-$n.jpg"; if ( $Download_Thumbnails && ! $Source_Dir ) { $cmd = "$Gphoto_Cmd -t $i '$th'"; } else { print STDERR "Creating old, empty temporary thumbnail image $n " . "as $th: -\n"; $cmd = "touch -t 199901010000 '$th'"; } my ($t0, $dt, $sz, $rate); $t0 = time; $gt0 = &gettime(); system($cmd); if ( $? != 0 ) { print STDERR "*** some error *** $!\n"; exit 1; } system("cp -p '$th' '$th.orig'; sync"); $gt1 = &gettime(); $gdt = $gt1 - $gt0; $dt = time - $t0; if ($dt < 2) { $dt = sprintf("%.3f", $gdt); $dt = 0.01 if $dt <= 0.0; } $sz = -s $th; $total_size += $sz; $rate = sprintf("%.2f", $sz/(1024 * $dt) ); print STDERR "$sz bytes in $dt seconds, $rate KB/sec\n"; if ($converting) { if ($Use_convert) { fsleep(0.3); } else { fsleep(0.05); } } else { fsleep(0.01); } my $ph = "$Dir/photo-$n.jpg"; my $ph2 = "$Dir/_photo-$n.jpg"; if ( $Download_Thumbnails == 2 ) { print STDERR "Thumbnails only, NOT downloading full image,\n" . " creating an empty one instead: $ph\n"; system("touch '$ph'"); next; } if ($Source_Dir) { $src = $Source_Pics[$i-1]; if ($src =~ m,/auto,) { # automounted, smartmedia, etc. $cmd = "dd bs=16384 if='$src' of='$ph'"; } else { $cmd = "cp '$src' '$ph'"; } if ($ph =~ m,/auto,) { $cmd .= '; sync'; } print STDERR "$cmd\n"; } else { $cmd = "$Gphoto_Cmd -s $i '$ph'"; } $t0 = time; $gt2 = &gettime(); system($cmd); if ( $? != 0 ) { print STDERR "*** some error *** $!\n"; exit 1; } $dt = time - $t0; $gt3 = &gettime(); $gdt = $gt3 - $gt2; if ($dt < 2) { $dt = sprintf("%.3f", $gdt); $dt = 0.01 if $dt <= 0.0; } $sz = -s $ph; $total_size += $sz; $rate = sprintf("%.2f", $sz/(1024 * $dt) ); print STDERR "$sz bytes in $dt seconds, $rate KB/sec\n"; if ($count % 10 == 0) { system("sync"); } if ($converting) { if ($Use_convert) { fsleep(0.4); } else { fsleep(0.05); } } else { fsleep(0.01); } if ( $Filter_Cmd ) { my ($old, $new); $old = $ph; $new = $ph2; $cmd = $Filter_Cmd; $cmd =~ s/%OLD/$old/g; $cmd =~ s/%NEW/$new/g; $converting = 1; print STDERR "filtering photo: $cmd\n"; system($cmd); if ( $? != 0 ) { print STDERR "*** WARNING: some error shrinking *** $!\n"; } unlink $old; rename $new, $old; } if ( $Shrink_by_2_Cmd ) { my ($xsize, $ysize) = jpeg_size($ph); if ( $xsize > $Large_Width ) { my ($old, $new); $old = $ph; $new = $ph2; $cmd = $Shrink_by_2_Cmd; $cmd =~ s/%OLD/$old/g; $cmd =~ s/%NEW/$new/g; my $flag = "/tmp/$Program.bg.$$.$i"; system("touch $flag"); $converting = 1; if ( fork ) { push(@BG_flags, $flag); fsleep(0.3); my $njobs = 0; foreach my $bgf (@BG_flags) { $njobs++ if -f $bgf; } $extra_sleep = int($njobs/3.0) * 6; if ($extra_sleep > 0) { print STDERR " % njobs=$njobs extra sleep: $extra_sleep\n"; fsleep($extra_sleep) if $extra_sleep; } } else { print STDERR " shrinking HUGE photo in background:\n $cmd\n"; system($cmd); if ( $? != 0 ) { print STDERR "*** WARNING: some error HUGE shrinking *** $!\n"; } my $big = "$Dir/large-$n.jpg"; rename $old, $big; rename $new, $old; if ( $Make_Small ) { my $small_dir = "$Dir/$Small_Subdir"; print STDERR "\n"; &make_small($ph, $small_dir); } unlink($flag); exit 0; } } } } system("sync"); $total_time = time - $start_time; $rate = sprintf("%.2f", $total_size/(1024 * $total_time) ); print STDERR "\nTotal: downloaded $total_size bytes in $total_time seconds. $rate KB/sec\n"; if ( @BG_flags ) { foreach my $i (1..200) { my $saw = 0; foreach my $flag (@BG_flags) { $saw++ if -f $flag; } last unless $saw > 0; print STDERR "Waiting for background shrinking to finish ($saw outstanding) ...\n"; sleep 3; } } if ( $Dir =~ /^\.+$/ ) { $raw_dir = "$Dir/../RAW"; } else { $raw_dir = dirname($Dir) . "/RAW"; } if ( ! -d $raw_dir ) { system("mkdir -p '$raw_dir'"); } if ( -d $raw_dir ) { my ($try, $try2); if ( basename($Dir) =~ /^\.+$/ ) { $try = $raw_dir . "/" . "gphoto_download-$$" . ".tar"; } else { $try = $raw_dir . "/" . basename($Dir) . ".tar"; } my $raw_tarball = ''; foreach my $suffix ('', 1 .. 20) { if ( $suffix eq '' ) { $try2 = $try; } else { $try2 = "$try.$suffix"; } if ( ! -e $try2 ) { $raw_tarball = $try2; last; } } if ( $raw_tarball ne '' ) { print STDERR "\nMaking backup of raw images to: $raw_tarball\n"; system("(cd '$Dir'; tar -cvf - --exclude Small --exclude Ext .) > $raw_tarball"); system("ls -l $raw_tarball"); print STDERR "\n"; } else { print STDERR "\nCould not make unique backup name: $try\n"; } } else { print STDERR "$raw_dir: $!\n"; } make_html($Dir); if ( $Make_Small ) { update_smalls($Dir, $Small_Subdir); make_html($Dir, $Small_Subdir); } print STDERR "launching browser: url '$Dir/index.html'\n"; &show_html("$Dir/index.html") if $yaya; &date_finish(); exit 0; ############################################################################## sub show_html { my($index) = @_; if ( ! -f $index ) { $index = "$Dir/index.html"; } system("url '$index' 2>/dev/null"); } sub update_smalls { my($dir, $small) = @_; my $dir_small = "$dir/$small"; if ( $Download_Thumbnails == 2 ) { print STDERR "\nThumbnails only, skipping updating of smaller images ..\n"; return; } print STDERR "\nUpdating smaller images ..\n"; my @photos = <$dir/photo*.jpg>; foreach my $photo (@photos) { &make_small($photo, $dir_small); } } sub make_small { my($photo, $dir_small) = @_; if ( ! -d $dir_small ) { system("mkdir -p '$dir_small'"); if ( ! -d $dir_small ) { print STDERR "*** no small directory $dir_small: $!\n"; exit 1; } } my $base = basename($photo); my $small = "$dir_small/$base"; my $cmd = $Small_Cmd; $cmd =~ s,%OLD,$photo,g; $cmd =~ s,%NEW,$small,g; my $age_old = -M $photo; my $age_new = -M $small; if ( -e $small && $age_old > $age_new ) { print STDERR "$small is up to date.\n"; return; } print STDERR " smaller image:\n $cmd\n"; system($cmd); if ( $? != 0 ) { print STDERR "*** WARNING: some error shrinking *** $!\n"; } } sub make_html { my($dir0, $small) = @_; my $dir = $dir0; if ( $small ) { $dir = "$dir/$small"; } my $set_title = "Set.title"; my $set_order = "Set.order"; if ( $Make_Small && $small ) { $set_title = "../Set.title"; $set_order = "../Set.order"; } if ( -f "$dir/$set_order.append" ) { $Order_Only = 0; } if ( $Title eq '' && -f "$dir/$set_title" ) { # try to extract previous Title if ( open(TITLE, "<$dir/$set_title") ) { chomp($Title = <TITLE>); print STDERR "\nset title to: $Title\n"; } close(TITLE); } $Title = $Title0 unless $Title ne ''; if ( ! $small && open(TITLE, ">$dir/$set_title") ) { print TITLE $Title, "\n"; close(TITLE); } my @photos = <$dir/photo*.jpg>; if ( -f "$dir/$set_order" && open(ORDER, "<$dir/$set_order") ) { my $tmp = ''; while (<ORDER>) { chomp; $tmp .= $_ . ' '; } my @list; foreach my $i (split(' ', $tmp)) { next unless $i =~ /^\d+$/; push(@list, sprintf($Dfmt, $i) ); } my %photos; foreach my $pic (@photos) { $photos{$pic} = 1; } my @orig = @photos; @photos = (); foreach my $i (@list) { my $try = "$dir/photo-$i.jpg"; if ( ! -f $try ) { print STDERR "make_html: trying to order: $i -- $try, $!\n"; next; } $photos{$try} = 2; push(@photos, $try); } foreach my $pic (@orig) { if ( $photos{$pic} == 1 && ! $Order_Only ) { print STDERR "make_html: order appending: $pic\n"; push(@photos, $pic); } } } print STDERR "\nMaking HTML in $dir ...\n\n"; my $total = scalar(@photos); my $font_fam = 'Lucida, Verdana, Helvetica, Arial'; my $color = '#000077'; my $style = <<"END"; i, p, blockquote, ul li, ul, dl {font-family: $font_fam; font-size: 10pt; color: #000000} all.pb {font-family: $font_fam; font-size: 12pt; color: #000000} b {font-family: $font_fam; font-size: 10pt; color: #000000} cite, small {font-family: $font_fam; font-size: 10pt; color: $color } h4, smaller { font-family: $font_fam; font-size: 12pt; color: $color} h3, big { font-family: $font_fam; font-size: 14pt; color: $color} h2 { font-family: $font_fam; font-size: 18pt; color: $color} h1 { font-family: $font_fam; font-size: 24pt; color: $color} tt, pre { font-family: Courier, Lucidatypewriter; font-size: 10pt; color: #006600} END if ( ! -d "$dir/Ext" ) { system("mkdir -p '$dir/Ext'"); } ##################################################################### my $i = 0; foreach my $photo (@photos) { print STDERR "$photo\n"; my $html = $photo; $html =~ s/\.jpg$/.html/; my $base = basename($photo); my $dirname = dirname($photo); my $n = $base; $n =~ s/photo-//; $n =~ s/\.jpg$//; if ( ! -e "$dir/Ext/$base" ) { system("ln -s '../$base' '$dir/Ext/$base'"); my $base2 = $base; $base2 =~ s/^photo-/large-/; if ( -f "$dirname/$base2" ) { if ( ! -e "$dir/Ext/$base2" ) { system("ln -s '../$base2' '$dir/Ext/$base2'"); } } } my $prev = ''; my $next = ''; if ( $i == 0 ) { $prev = "index.html"; } else { $prev = basename($photos[$i-1]); $prev =~ s/\.jpg$/.html/; } if ( $i == $total - 1 ) { $next = "index.html"; } else { $next = basename($photos[$i+1]); $next =~ s/\.jpg$/.html/; } my $txt_file = $photo; $txt_file =~ s/\.jpg$/.txt/; if ( $Make_Small && $small ) { $txt_file =~ s,/(photo-\d+\.txt$),/../$1,; #/ } my $text = ''; if ( -f $txt_file ) { system("target_top '$txt_file'"); if ( open(TXT, "<$txt_file") ) { while (<TXT>) { $text .= $_; } close(TXT); } } if ( $text ne '' ) { $text = '<p class="pb">' . $text . '</p>'; } my $img0 = "<img alt=\"$n\" src=\"$base\" border=1><br>"; my $img = $img0; my $sm_html = ''; if ( $Make_Small && $small ) { $sm_html = $base; $sm_html =~ s/\.jpg$/-big.html/; $img = "<a href=\"$sm_html\">" . $img . "</a>"; } my $picture_number = sprintf($Dfmt, $i+1); my $large = $photo; my $large2 = $photo; $large =~ s/photo-/large-/; $large2 =~ s/photo-/..\/large-/; if ( -f $large ) { $lbase = basename($large); $large = "<p><a href=\"$lbase\">Very <font size=\+1><b>LARGE</b></font> Image (for printing)</a>"; } elsif ( -f $large2 ) { $lbase = basename($large2); $large = "<p><a href=\"../$lbase\">Very <font size=\+1><b>LARGE</b></font> Image (for printing)</a>"; } else { $large = ''; } my $str = <<"END"; <html> <head> <title>$Title

Picture $picture_number in   $Title

Previous | Index | Next

$text

$img

$large

Previous | Index | Next

END open(HTML, ">$html") || die "$!"; print HTML $str; close(HTML); system("image_size -O '$html'"); if ( $sm_html ne '' ) { my $outfile = $html; $outfile =~ s/\.html/-big.html/; $str =~ s/-big\.html/.html/; $str =~ s,src=",src="../,; #/ open(HTML, ">$outfile") || die "$!"; print HTML $str; close(HTML); system("image_size -O '$outfile'"); } $i++; } # END OF photos LOOP ##################################################################### my $other = ''; my $other2 = ''; if ( $Make_Small ) { if ( ! $small ) { $other = <<"END"; (for slower internet connections, go to the 50% Smaller images Index.) END } else { $other = <<"END"; (for the bigger images, go to the Larger images Index.) END $other2 = <<"END";   (50% Smaller Images) END } $other = "   $other"; } chomp($other); chomp($other2); my $index = "$dir/index.html"; my $txt = $index; $txt =~ s/\.html$/.txt/; if ( $Make_Small && $small ) { $txt =~ s,/index,/../index,; #/ } if ( -f $txt ) { system("target_top '$txt'"); $txt = `cat '$txt'`; } else { $txt = '' } if ( $txt ne '' ) { $txt = '

' . $txt . '

'; } open(INDEX, ">$index") || die "$!"; print INDEX <<"END"; $Title

$Title$other2

$txt

Click on a tiny image below to view its fullsize image. $other

END my $cnt = 0; my $order_string = ''; ##################################################################### foreach my $photo (@photos) { print STDERR "$photo\n"; my $dirname = dirname($photo); my $base = basename($photo); my $n = $base; $n =~ s/photo-//; $n =~ s/\.jpg$//; $order_string .= sprintf("%5d", $n); my $html = $base; $html =~ s/\.jpg$//; $html .= '.html'; my $thumb = $base; $thumb = "../$thumb" if $small; $thumb =~ s/photo-/thumb-/; if ( $Redo_Thumbnails && ! $small ) { my $thumb_path = "$dirname/$thumb"; my $age_old = -M $photo; my $age_new = -M $thumb_path; if ( -e $thumb_path && $age_old > $age_new ) { print STDERR "thumbnail $thumb_path is up to date.\n"; } else { my($x, $y) = jpeg_size($photo); if ( $x =~ /^\d+$/ && $y =~ /^\d+$/ ) { my $cmd = $Small_Geom_Cmd; my $y_new = 120; my $x_new = int( ($x/$y) * $y_new); if ( $x_new > 160 ) { $x_new = 160; $y_new = int( ($y/$x) * $x_new); } my $geom = "${x_new}${Small_Geom_Cmd_x}${y_new}"; $cmd =~ s/%GEOM/$geom/g; $cmd =~ s/%OLD/$photo/; $cmd =~ s/%NEW/$thumb_path/; print STDERR "thumbnail redo image: $cmd\n"; system($cmd); } else { print STDERR "error running jpeg_size($photo) x=$x y=$y\n"; } } } my $large = $photo; $large =~ s/photo-/large-/; print INDEX <<"END"; END ### $cnt++; if ( $cnt >= $Columns ) { $cnt = 0; $order_string .= "\n"; print INDEX <<"END"; END } } ##################################################################### print INDEX <<"END";
$n

$n

$n - $thumb

END close(INDEX); if ( ! $small && open(ORDER, ">$dir/$set_order") ) { print ORDER $order_string, "\n"; close(ORDER); } system("image_size -O '$index'"); } sub merge_dirs { my($outdir, @indirs) = @_; if ( ! -d $outdir ) { system("mkdir -p '$outdir'"); } if ( ! -d $outdir ) { die "No $outdir: $!\n"; } my $shift = 0; my $order_string = ''; foreach my $dir (@indirs) { if ( ! -d $dir ) { die "bad input directory: $dir $!\n"; } my ($n1, $n2, $nmax); $nmax = 0; foreach my $file (<$dir/photo-*.jpg>) { if ( $file =~ m,photo-(\d+)\.jpg$, ) { $n1 = $1; } else { die "bad filename: $file\n"; } $n2 = $n1 + $shift; if ( $n2 > $nmax ) { $nmax = $n2; } $n2 = sprintf("$Dfmt", $n2); my $file2 = "$outdir/photo-$n2.jpg"; print STDERR "cp -p $file $file2\n"; system 'cp', '-p', $file, $file2; my $tfile = $file; my $tfile2 = $file2; $tfile =~ s,/photo-,/thumb-,; $tfile2 =~ s,/photo-,/thumb-,; print STDERR "cp -p $tfile $tfile2\n"; system 'cp', '-p', $tfile, $tfile2; if ( -f "$tfile.orig" ) { print STDERR "cp -p $tfile.orig $tfile2.orig\n"; system 'cp', '-p', "$tfile.orig", "$tfile2.orig"; } $tfile =~ s/\.jpg$/.txt/; $tfile2 =~ s/\.jpg$/.txt/; if ( -f $tfile ) { print STDERR "cp -p $tfile $tfile2\n"; system 'cp', '-p', $tfile, $tfile2; } $tfile = $file; $tfile2 = $file2; $tfile =~ s,/photo-,/large-,; $tfile2 =~ s,/photo-,/large-,; if ( -f $tfile ) { print STDERR "cp -p $tfile $tfile2\n"; system 'cp', '-p', $tfile, $tfile2; } } if ( -f "$dir/Set.order" ) { my $tmp = `cat '$dir/Set.order'`; $tmp =~ s/(\d+)/$1+$shift/eg; $order_string .= $tmp; } $shift = 10 * (int($nmax/10) + 1); print STDERR "shift: $shift\n"; } if ( -f "$indirs[0]/Set.title" ) { system 'cp', '-p', "$indirs[0]/Set.title", $outdir; } if ( $order_string ne '' && open(ORDER, ">$outdir/Set.order") ) { print ORDER $order_string; close(ORDER); } } sub delete_numbers { my (@numbers) = @_; if ( ! @numbers && $Order_Only ) { my (%nlist); foreach my $f (<./photo-*>) { if ( $f =~ /photo-(\d+)\./ ) { $f = sprintf($Dfmt, $1); $nlist{$f} = 1; } } die "no files to delete:\n" unless %nlist; my $order_string = ''; if ( -f "./Set.order" ) { $order_string = `cat './Set.order'`; } if ( $order_string eq '' ) { die "no order_string from ./Set.order\n"; } $order_string =~ s/\n/ /g; foreach my $n (split(' ', $order_string)) { next unless $n =~ /^\d+$/; my $m = sprintf($Dfmt, $n); $nlist{$m} = 0; } foreach my $n (sort {$a <=> $b} (keys(%nlist))) { push(@numbers, $n) if $nlist{$n} > 0; } } my(@nums, @nums2); foreach my $n (@numbers) { push(@nums2, split(/,/, $n)); } foreach my $n (@nums2) { if ( $n =~ /^(\d+)-(\d+)$/) { my $n1 = $1; my $n2 = $2; if ( $n1 >= $n2) { push (@nums, $n1, $n2); } else { my $k; for ($k = $n1; $k <= $n2; $k++) { push(@nums, $k); } } } else { push(@nums, $n); } } my %did; foreach my $n (@nums) { my $fn = sprintf($Dfmt, $n); next if $did{$n}; $did{$n} = 1; print "\nDeleting photo-$fn* large-$fn* thumb-$fn* ...\n"; my @list = (); open(FIND, "find . -name \"photo-$fn*\" -o -name \"thumb-$fn*\" -o -name \"large-$fn*\" |") || die "$!"; while () { chomp; push(@list, $_); } next unless @list; print STDERR "will do: rm -f on:\n\t", join("\n\t", sort(@list)), "\n"; if ( $Do_Deletes > 1 ) { sleep 1 unless $Do_Deletes > 2; system 'rm', '-f', sort(@list); } else { print STDERR "delete them? y/[n] "; my $reply = ; if ( $reply =~ /y/i ) { system 'rm', '-f', sort(@list); } else { print STDERR "skipped.\n"; } } } print STDERR "\nyou may want to rerun: $Program -H -u .\n"; } sub move_numbers { my ($moveto, @numbers) = @_; if (! -d $moveto) { system("mkdir -p '$moveto'"); } if (! -d $moveto) { system("ls -l '$moveto'"); exit 1; } my(@nums, @nums2); foreach my $n (@numbers) { push(@nums2, split(/,/, $n)); } foreach my $n (@nums2) { if ( $n =~ /^(\d+)-(\d+)$/) { my $n1 = $1; my $n2 = $2; if ( $n1 >= $n2) { print STDERR "warning $n: $n1 >= $n2\n"; push (@nums, $n1, $n2); } else { my $k; for ($k = $n1; $k <= $n2; $k++) { push(@nums, $k); } } } else { push(@nums, $n); } } my %did; foreach my $n (@nums) { my $fn = sprintf($Dfmt, $n); next if $did{$n}; $did{$n} = 1; my $mv1 = 'Moving'; my $mv2 = 'move'; $mv1 = 'Copying' if $Do_Copy_Only; $mv2 = 'copy' if $Do_Copy_Only; print "\n$mv1 photo-$fn* large-$fn* thumb-$fn* to $moveto ...\n"; my @list = (); open(FIND, "find . -name \"photo-$fn*\" -o -name \"thumb-$fn*\" -o -name \"large-$fn*\" |") || die "$!"; while () { chomp; push(@list, $_); } next unless @list; print STDERR "will do: $mv2 on:\n\t", join("\n\t", sort(@list)), "\n"; my $list = join(' ', sort(@list)); print STDERR "tar -cvf - $list | (cd '$moveto'; tar -xvpf -)\n"; if ( $Do_Moves > 1 ) { sleep 1 unless $Do_Moves > 2; system("tar -cvf - $list | (cd '$moveto'; tar -xvpf -)"); unlink(@list) unless $Do_Copy_Only; } else { print STDERR "$mv2 them? y/[n] "; my $reply = ; if ( $reply =~ /y/i ) { system("tar -cvf - $list | (cd '$moveto'; tar -xvpf -)"); unlink(@list) unless $Do_Copy_Only; } else { print STDERR "skipped.\n"; } } } print STDERR "\nyou may want to rerun: $Program -H -u .\n"; print STDERR "you may want to rerun: $Program -H -u $moveto\n"; } sub renumber { my ($renumdir) = @_; if (! -d $renumdir) { system("mkdir -p '$renumdir'"); } if (! -d $renumdir) { system("ls -l '$renumdir'"); exit 1; } my(@nums); foreach my $file (<./photo-*.jpg>) { if ( $file =~ m,photo-(\d+)\.jpg$, ) { $n1 = $1; } else { die "bad filename: $file\n"; } push(@nums, $n1); } my $count = 1; my (%renum, @renum); foreach my $n (sort {$a <=> $b} (@nums)) { next if exists $renum{$n}; $renum{$n} = $count; push(@renum, $n); $count++; } my %did; foreach my $n (@renum) { my $fn = sprintf($Dfmt, $n); my $fn2 = sprintf($Dfmt, $renum{$n}); next if $did{$n}; $did{$n} = 1; print "\nCopying photo-$fn* large-$fn* thumb-$fn* to $renumdir ...\n"; my @list = (); open(FIND, "find . -name \"photo-$fn*\" -o -name \"thumb-$fn*\" -o -name \"large-$fn*\" |") || die "$!"; while () { chomp; push(@list, $_); } next unless @list; foreach my $f (@list) { my $f2 = $f; $f2 =~ s/-$fn/-$fn2/; my $d = dirname($f2); if (! -d "$renumdir/$d") { system("mkdir -p '$renumdir/$d'"); if (! -d "$renumdir/$d") { die "$renumdir/$d: $!"; } } print STDERR "cp -p $f $renumdir/$f2\n"; system 'cp', '-p', $f, "$renumdir/$f2"; } } if (-f "./Set.title") { system("cp -p ./Set.title $renumdir"); } if (-f "./index.html") { system("cp -p ./index.html $renumdir"); } print STDERR "you may want to rerun: $Program -H -u $renumdir\n"; } sub jpeg_size { my($image) = @_; my $str = `jpeg_size '$image'`; my($f, $x, $y, $rest) = split(' ', $str, 4); if ( $x =~ /width=(\d+)/ ) { $x = $1; } else { $x = ''; } if ( $y =~ /height=(\d+)/ ) { $y = $1; } else { $y = ''; } #print STDERR "x=$x y=$y\n"; return($x, $y); } sub fsleep { my ($time) = @_; select(undef, undef, undef, $time) if $time; } sub gettime { if ( ! $GetTime_Syscall_Init ) { my ($dir, $found_it); $found_it = 0; foreach $dir (@INC) { if ( -f "$dir/sys/syscall.ph" ) { $found_it = 1; # whew! last; } } if ( ! $found_it ) { # bummer... try to guess the syscall # $OS_Name = `uname -s` unless $OS_Name; if ( $OS_Name =~ /sunos/i ) { eval "sub SYS_gettimeofday { return 156; }"; } elsif ( $OS_Name =~ /linux/i ) { eval "sub SYS_gettimeofday { return 78; }"; } } else { require 'sys/syscall.ph'; } &SYS_gettimeofday() || die "$!"; $GetTime_Syscall_Init = &SYS_gettimeofday(); print STDERR "Initialized: GetTime_Syscall\n" if $Debug; } # let's keep these global... # my ($tv, $tv_sec, $tv_usec); # Allocate the "timeval" space: $tv = ("\0" x 4) x 2; # assumes long is 4 bytes. $tz = ("\0" x 4) x 2; # assumes long is 4 bytes. syscall($GetTime_Syscall_Init, $tv, $tz); ($tv_sec, $tv_usec) = unpack("L2", $tv); # $tv_sec = substr($tv, 0, 4); # $tv_usec = substr($tv, 4, 4); # $tv_sec = unpack("l", $tv_sec); # $tv_usec = unpack("l", $tv_usec); $tv_usec2 = sprintf("%8.6f", $tv_usec/1000000.0); if ( $tv_usec2 =~ /^0\./ ) { $tv_usec2 =~ s/^0\././; $tv_sec = "$tv_sec$tv_usec2"; } else { $tv_sec = $tv_sec + ($tv_usec/1000000.0); } if ( $StartTime ne '' ) { $tv_sec -= $StartTime; } return $tv_sec; }