thumbnailtools/0042755000175000017500000000000010015241316012615 5ustar artoartothumbnailtools/rotate_images.pl0100600000175000017500000001230007700556157015777 0ustar artoarto#!/usr/bin/perl # # Rotates jpeg images $AMOUNT degrees clockwise. Moves originals to # _orig.jpg. # # Copyright Arto Teräs 1999-2003 # # Version: 1.12 # Licence: GNU General Public License (version 2 or any later version) # http://www.gnu.org/copyleft/gpl.txt # # Changelog: # # 1.0 Initial version # 1.1 Automatic rotation feature and lossless rotation added. # Changed the output to interlaced (progressive) JPEG files # in the case of lossy rotation. # 1.11 Fixed handling of filenames which contain spaces (thanks # to Edward for finding the bug and providing a patch) # 1.12 File name extension check fixed to accept capital letters # # Latest version: http://www.iki.fi/ajt/software/thumbnailtools/ ###################################################################### # # Global defaults: # $AMOUNT = "auto"; # the amount to rotate, either keyword "auto" # or a number (degrees clockwise). # Amount "auto" rotates automatically images which # are marked as rotated in the EXIF header # Can be adjusted with the command line option -a. $QUALITY = "lossless"; # output image quality, either keyword "lossless" # for lossless rotation (requires jpegtrans) or # a number, for example 75 for "JPEG 75% quality". # Can be adjusted with the command line option -q # ###################################################################### use Getopt::Std; sub find_program { # Quick check if the given program can be found in the PATH # This will work only on Unix machines... my $program = shift; @system_dirs = split(':', $ENV{PATH}); foreach (@system_dirs) { if (-x "$_/${program}") { return 1; } } # not found return 0; } # The main program # my %Options; getopts('a:q:', \%Options); if (@ARGV) { if (exists($Options{"a"})) { $AMOUNT = $Options{"a"}; } if (exists($Options{"q"})) { $QUALITY = $Options{"q"}; } # Check that the necessary program(s) can be executed: if ($AMOUNT eq "auto") { # This needs jhead if (find_program("jhead") == 0) { print STDERR "Couldn't find the \"jhead\" utility.\n\n"; print STDERR "Please make sure that it can be found in the PATH and try again.\n"; exit(1); } } # If we want lossless rotation, jpegtran (or jpegtran-mmx) does the job, # otherwise use convert (old behaviour) my $jpegtran_name = "jpegtran-mmx"; # use the optimized one by default if ($QUALITY eq "lossless") { if (find_program("jpegtran-mmx") == 0) { if (find_program("jpegtran") == 0) { print STDERR "Couldn't find the \"jpegtran\" utility.\n\n"; print STDERR "Please make sure that it can be found in the PATH and try again.\n"; exit(1); } else { $jpegtran_name = "jpegtran"; } } } else { if (find_program("convert") == 0) { print STDERR "Couldn't find the \"convert\" utility (part of the ImageMagick package).\n\n"; print STDERR "Please make sure that it can be found in the PATH and try again.\n"; exit(1); } } my $image; foreach $image (@ARGV) { # Accept filenames ending in .jpg, .JPG, .jpeg and .JPEG if ($image =~ /(.*)\.([jJ][pP][eE]{0,1}[gG])/) { print "Processing image ${image}"; my $basename = $1; my $extension = $2; my $origname = "$basename" . "_orig.${extension}"; my $rotate = 1; my $degrees = $AMOUNT; if (-f $origname) { print " ($origname already exists, using that!)"; } if ($AMOUNT eq "auto") { # We'll use the original if it exists # (made sense with convert but maybe not any more...) if (-f $origname) { $jheadoutput = `jhead "$origname"`; } else { $jheadoutput = `jhead "$image"`; } # By default no rotation if we don't find the field $rotate = 0; my @lines = split("\n", $jheadoutput); my $field; my $value; foreach $line (@lines) { ($field, $value) = split(':', $line); if ($field =~ /^Orientation/ && $value =~ /^ rotate /) { $degrees = scalar(substr($value, 8)); if ($degrees > 0) { $rotate = 1; } } } if ($rotate == 1) { } } if ($rotate == 1) { print ": rotating $degrees degrees.\n"; # Let's preserve the original, if it doesn't exist if (! (-f $origname)) { `mv "$image" "$origname"`; } # Generate rotated image (lossless rotation by jhead or lossy with convert) if ($QUALITY eq "lossless") { # Parameter -copy all necessary for not to lose the EXIF header info `$jpegtran_name -rotate $degrees -copy all "$origname" >"$image"`; } else { `convert -rotate $degrees -quality $QUALITY -interlace Line $origname $image`; } } else { print ": no rotation.\n"; } } else { print "Skipping image $image\n"; } } } else { print "Usage: rotate_images.pl [OPTIONS] IMAGEFILES (in jpeg format)\n\n"; print "Available options:\n"; print "-a degrees the amount to rotate (clockwise, default $AMOUNT)\n"; print "-q quality the output jpeg quality (default ${QUALITY}%)\n"; exit(1); } thumbnailtools/thumbgenerator.pl0100600000175000017500000004315507700556145016213 0ustar artoarto#!/usr/bin/perl # # Thumbnail and html page generator # Copyright Arto Teräs 1999-2003 # # Some inspiration from thumbs.sh by Adam Kopacz / kLoGraFX # http://www.klografx.de/ - Adam.K@klografx.de # # Multicolumn mode contributed by Jan Kester # # Version: 1.11 # Licence: GNU General Public License (version 2 or any later version) # http://www.gnu.org/copyleft/gpl.txt # # Changelog: # # 1.0 Initial version # 1.01 Fixed a small error in command line utilities detection # 1.02 Fixed parsing problem with recent versions of ImageMagick # and added rounding image sizes to nearest integer if # dividing with SCALEFACTOR produced a non-integer. # 1.1 Several new features: generating several sizes in one pass, # multicolumn mode, caption file etc. # 1.11 File name extension check fixed to accept capital letters # # Latest version: http://www.iki.fi/ajt/software/thumbnailtools/ ################################################################################ # # Global defaults (modify according to your preferences): # $AUTHOR = "Unknown Author"; # Author of pictures to be written on the resulting # html page (Replace "Unknown author" with your name.) $AUTHOR_EMAIL = "unknown\@some.domain"; # Email of the author, @-character escaped # for not to be interpreted as perl list. # (Replace with your email address.) @SCALEFACTORS = (L256); # The size of the original picture is divided # by the SCALEFACTORS to get the thumbnail sizes. # May also be Xn (n a number) for a fixed thumbnail # width, Yn for fixed height or Ln for limiting # the longer edge of thumbnail to the given number # of pixels. # # This is a list with at least one element, more # elements mean that several sizes are generated for # each image. Can be adjusted using the command line # option -d. @NAMESUFFIXES = ("_small", "_medium", "_large"); # String to add in the file name # before the final suffix .jpg. # At least as many as scalefactors. # Can be adjusted using the command # line option -e. $SKIPSUFFIXNAMES = 1; # if > 0, skip filenames which end in one of the suffixes # (e.g. "_small.jpg") when generating thumbnails. $MULTICOLUMN = 0; # if > 0, use multicolumn mode: images organized in a table # with the specified number of columns (actually the default # layout is also a table with images in one column and info # (date, size etc.) in another column. Can be adjusted using # the command line option -m. $THUMBQUALITY = 75; # thumbnail image quality, can be adjusted using # the command line option -q. $PAGE_TITLE = "Some pictures"; # The default title, can be adjusted # using the command line option -s. $OUTPUT_FILE = "index.html"; # The default output file, can be adjusted # using the command line option -o. $ASK_OVERWRITE = 1; # If one, asks the user whether the output file # should be overwritten in case it exits. # (not adjustable from command line) $TIMESTAMP_FROM_ORIGINAL = 1; # file date picked from the # picture_orig.jpg, if it exists # (not adjustable from command line) $DO_THUMBNAILS = 1; # if zero, just regenerates the html page (fast), # can be set to zero using the command line # option -n. $CAPTIONS_FROM_FILE = 0; # If one, reads image captions from a file and # adds them to the html page. Can be set using # the command line option -c, following a file # containing the captions as the second argument. $CHARSET = "iso-8859-1"; # Character set of the captions in the file # (and the resulting web page) # ################################################################################ use Getopt::Std; use POSIX; # Modify the html code to suit your needs. sub print_html_header { my $fh = shift; my $title = shift; my $h1 = shift; print $fh "\n"; print $fh "\n"; print $fh "\n"; print $fh "\n"; print $fh "$title\n"; print $fh "\n"; print $fh "\n"; print $fh "

$h1

\n"; if ($MULTICOLUMN) { print $fh "\n\n"; } else { print $fh "
\n\n"; } } # Modify the html code to suit your needs. sub print_html_footer { my $fh = shift; my @time = localtime(time); my $datestr = POSIX::strftime("%d.%m.%Y.", @time); my $yearstr = POSIX::strftime("%Y", @time); print $fh "\n"; if ($MULTICOLUMN) { print $fh "\n"; print $fh "\n"; print $fh "
\n"; } else { print $fh "\n"; } print $fh "
\n"; print $fh "
\n"; print $fh "Copyright $AUTHOR "; print $fh "<\;$AUTHOR_EMAIL>\; ${yearstr}.
\n"; print $fh "Redistribution of this document as a whole or any of the pictures\n"; print $fh "individually is permitted in any medium provided this copyright\n"; print $fh "notice is preserved.\n"; my $time = scalar localtime; print $fh "

Last update $datestr\n"; print $fh "

\n"; print $fh "
\n"; print $fh "\n"; print $fh "\n"; } sub find_program { # Quick check if the given program can be found in the PATH # This will work only on Unix machines... my $program = shift; @system_dirs = split(':', $ENV{PATH}); foreach (@system_dirs) { if (-x "$_/${program}") { return 1; } } # not found return 0; } # The main program # my %descdir; # Hash for image descriptions my @scalemodes; # An array to match @SCALEFACTORS, each entry # "divider", "xsize", "ysize" or "longest" my %Options; getopts('c:d:e:m:no:q:s:', \%Options); if (@ARGV) { if (exists($Options{"c"})) { # Read captions in a hash from the given file $captionfilename = $Options{"c"}; print "Reading captions from $captionfilename...\n"; $CAPTIONS_FROM_FILE = 1; open(CFILE, "$captionfilename") or die "Couldn't open $captionfilename\n"; while () { my $line = $_; if ($line =~ /^\#/) { #ignore comments next; } my @desc = split("\t+", $line); # Let's add to the global description dir. If # incorrect number of elements, just ignore the line # (probably missing description) if (scalar(@desc) == 2) { chomp($desc[1]); # Remove trailing newline $descdir{"$desc[0]"} = $desc[1]; } } close(CFILE); print "...done.\n"; } if (exists($Options{"d"})) { @SCALEFACTORS = split(';', $Options{"d"}); } if (exists($Options{"e"})) { @NAMESUFFIXES = split(';', $Options{"e"}); } if (exists($Options{"m"})) { $MULTICOLUMN = $Options{"m"}; } if (exists($Options{"n"})) { $DO_THUMBNAILS = 0; } if (exists($Options{"o"})) { $OUTPUT_FILE = $Options{"o"}; } if (exists($Options{"q"})) { $THUMBQUALITY = $Options{"q"}; } if (exists($Options{"s"})) { $PAGE_TITLE = $Options{"s"}; } # Check scalemode: Each element is allowed to have different scalemode # (for example, have fixed xsize (width) for all thumbnails visible # on the html page and a divider for the next size level) for $i (0 .. scalar(@SCALEFACTORS) - 1) { if ($SCALEFACTORS[$i] =~ /^[xX]/) { $scalemodes[$i] = "xsize"; $SCALEFACTORS[$i] = int(substr($SCALEFACTORS[$i], 1)); } elsif ($SCALEFACTORS[$i] =~ /^[yY]/) { $scalemodes[$i] = "ysize"; $SCALEFACTORS[$i] = int(substr($SCALEFACTORS[$i], 1)); } elsif ($SCALEFACTORS[$i] =~ /^[lL]/) { $scalemodes[$i] = "longest"; $SCALEFACTORS[$i] = int(substr($SCALEFACTORS[$i], 1)); } else { $scalemodes[$i] = "divider"; } } # Check for necessary command line utilities $USE_IMAGEMAGICK = 0; if (! (find_program("cjpeg") == 1 && find_program("djpeg") == 1 && find_program("pnmscale") == 1 && find_program("identify") == 1)) { # Ok, not all the programs available, but we can do the same a bit # slower with the convert utility from ImageMagick $USE_IMAGEMAGICK = 1; if (find_program("convert") == 0 || find_program("identify") == 0) { print STDERR "Couldn't find all the necessary utilities.\n\n"; print STDERR "Please make sure that following programs can be found in the PATH:\n"; print STDERR "1. identify (ImageMagick package)\n"; print STDERR "2. convert (ImageMagick package)\n"; print STDERR "(works faster if you also have cjpeg, djpeg and pnmscale)\n"; exit(1); } } # Open the output file if (-f $OUTPUT_FILE) { if ($ASK_OVERWRITE) { print "$OUTPUT_FILE exists, overwrite (y/n)? "; my $response = getc; if ($response ne "y" && $response ne "Y") { die "Quitting..."; } } } if (scalar(@SCALEFACTORS) > scalar(@NAMESUFFIXES)) { die "Number of scalefactors exceeds the available number of suffixes\n"; } for $i (0 .. scalar(@NAMESUFFIXES) - 1) { if ($NAMESUFFIXES[$i] eq "") { die "Empty suffix, would overwrite the original file! Quitting..."; } } open(OUTFILE, ">$OUTPUT_FILE") or die "Couldn't open $OUTPUT_FILE for output\n"; # The title and H1 header of the page are the same print_html_header(\*OUTFILE, $PAGE_TITLE, $PAGE_TITLE); my $image; my $image_counter = 0; # Necessary for multicolumn mode output my $origsuffix = "_orig"; IMAGE: foreach $image (@ARGV) { # Accept filenames ending in .jpg, .JPG, .jpeg and .JPEG if ($image =~ /(.*)\.([jJ][pP][eE]{0,1}[gG])/) { my $basename = $1; my $extension = $2; # We might not want to generate thumbnails of thumbnails... if ($SKIPSUFFIXNAMES) { foreach $suffix (@NAMESUFFIXES) { if ($image =~ /.*$suffix\.$extension/) { print "Skipping image $image\n"; next IMAGE; } } # Also skip the images moved to XXX_orig.jpg when compressing / rotating if ($image =~ /.*$origsuffix\.$extension/) { print "Skipping image $image\n"; next IMAGE; } } print "Processing image $image\n"; $image_counter++; my $origname = "$basename" . "${origsuffix}.${extension}"; my $i; my $scalings = scalar(@SCALEFACTORS); my @thumbnames; my $thumbname; for $i (0 .. $scalings-1) { $thumbnames[$i] = "${basename}" . $NAMESUFFIXES[$i] . ".${extension}"; } my @imagestats = stat($image); my $imagesize = POSIX::floor(($imagestats[7] / 1024)+0.5); # in kilobytes if (($TIMESTAMP_FROM_ORIGINAL) && (-f $origname)) { @imagestats = stat($origname); } my $imagedate = scalar localtime($imagestats[9]); # If the image name contains spaces, parsing the output of identify # would fail without this trick: my $parts_in_image_name = scalar(split(' ', $image)); my @imageinfo = split(' ', `identify -ping "$image"`); my $dimensions = $imageinfo[$parts_in_image_name+1]; # In older versions of ImageMagick identify gave the image dimensions # as first element after image name, so let's check that we got it # correctly and try the older format too. if (! ($dimensions =~ /\d+x\d+/)) { $dimensions = $imageinfo[$parts_in_image_name]; if (! ($dimensions =~ /\d+x\d+/)) { die "Couldn't figure out the image dimensions from identify program output.\n"; } } my ($xsizeorig, $ysizeorig) = split('x', $dimensions); my @thumbsizes; for $i (0 .. $scalings-1) { my $xsize; my $ysize; if ($scalemodes[$i] eq "divider") { $xsize = $xsizeorig / $SCALEFACTORS[$i]; $ysize = $ysizeorig / $SCALEFACTORS[$i]; } if ($scalemodes[$i] eq "xsize") { $xsize = $SCALEFACTORS[$i]; $ysize = $ysizeorig / ($xsizeorig / $xsize); } if ($scalemodes[$i] eq "ysize") { $ysize = $SCALEFACTORS[$i]; $xsize = $xsizeorig / ($ysizeorig / $ysize); } if ($scalemodes[$i] eq "longest") { if ($xsizeorig >= $ysizeorig) { $xsize = $SCALEFACTORS[$i]; $ysize = $ysizeorig / ($xsizeorig / $xsize); } else { $ysize = $SCALEFACTORS[$i]; $xsize = $xsizeorig / ($ysizeorig / $ysize); } } $xsize = POSIX::floor($xsize+0.5); # Make sure the size is a valid integer $ysize = POSIX::floor($ysize+0.5); $thumbname = $thumbnames[$i]; # Generate thumbnail if ($DO_THUMBNAILS) { if ($USE_IMAGEMAGICK) { `convert -geometry ${xsize}x${ysize} -quality ${THUMBQUALITY} -interlace Line "$image" "$thumbname"`; } else { # This is noticeably faster `djpeg -pnm "$image" | pnmscale -xsize $xsize | cjpeg -quality $THUMBQUALITY -optimize -progressive > "$thumbname"`; } } # Store some information about the generated image for later processing my @thumbstats = stat($thumbname); my $thumbsize = POSIX::floor(($thumbstats[7] / 1024)+0.5); # in kilobytes $thumbsizes[$i] = [$xsize, $ysize, $thumbsize]; } # Modify the html code to suit your needs. if ($MULTICOLUMN) { if (($image_counter) % $MULTICOLUMN == 1) { print OUTFILE "\n"; } } else { print OUTFILE "\n"; } # Make the smallest version visible and links for others if ($scalings == 1) { # only one scaling, link straight to image print OUTFILE "\n"; print OUTFILE "\"$image\""; } else { # link to the second smallest image print OUTFILE "\n"; print OUTFILE "\"$thumbnames[1]\""; } if ($MULTICOLUMN) { print OUTFILE "
\n"; } else { print OUTFILE "\n"; print OUTFILE "\n"; } if ($CAPTIONS_FROM_FILE) { if (exists($descdir{"$image"})) { my $desc = $descdir{"$image"}; print OUTFILE "${desc}
\n"; } } print OUTFILE "$imagedate
\n"; # Create textual links for all image sizes in the info cell for $i (1 .. $scalings-1) { print OUTFILE "$thumbsizes[$i][0]x$thumbsizes[$i][1] "; print OUTFILE "($thumbsizes[$i][2] kB)
\n"; } print OUTFILE "${xsizeorig}x${ysizeorig} ($imagesize kB)\n"; # Close the table cell, check if need to close the table row too print OUTFILE "\n"; if ($MULTICOLUMN > 0) { if ( ($image_counter) % $MULTICOLUMN == 0) { print OUTFILE "\n\n"; } } else { print OUTFILE "\n\n"; } } else { print "Skipping image $image\n"; } } # Add empty cells and a closing if not ending on a full amount in multicolumn mode if ($MULTICOLUMN && ($image_counter) % $MULTICOLUMN != 0) { for $i (($image_counter) % $MULTICOLUMN .. $MULTICOLUMN-1) { print OUTFILE " "; } print OUTFILE "\n\n"; } print_html_footer(\*OUTFILE); close(OUTFILE); exit(0); } else { # Print usage, need to do some formatting to display default correctly. my $dividerstring = ""; my $suffixstring = ""; for $i (0 .. scalar(@SCALEFACTORS) - 1) { $dividerstring = $dividerstring . $SCALEFACTORS[$i] . ";"; } chop($dividerstring); # Get rid of the last semicolon for $i (0 .. scalar(@NAMESUFFIXES) - 1) { $suffixstring = $suffixstring . $NAMESUFFIXES[$i] . ";"; } chop($suffixstring); # Get rid of the last semicolon print "Usage: thumbgenerator.pl [OPTIONS] IMAGEFILES (in jpeg format)\n\n"; print "Available options:\n"; print "-c filename read image captions from a file given as an argument\n"; print "-d dividers the scaling factors / pixel counts for thumbnail size(s):\n"; print " a list of values separated by semicolons - see documentation\n"; print " for syntax details. (default \"$dividerstring\")\n"; print "-e endings file name endings (suffixes) to use with each scalefactor\n"; print "-m columns if > 0, use multicolumn mode: images organized in a table\n"; print " with \"columns\" columns (default $MULTICOLUMN)\n"; print "-n if set, just regenerate html (no thumbnail generation)\n"; print "-o name the output file name (default ${OUTPUT_FILE})\n"; print "-q quality the output jpeg quality (default ${THUMBQUALITY}%)\n"; print " (default \"$suffixstring\")\n"; print "-s subject the page title (default \"${PAGE_TITLE}\")\n"; exit(1); } thumbnailtools/compress_images.pl0100644000175000017500000000544007700556167016354 0ustar artoarto#!/usr/bin/perl # # Compresses jpeg images to a preset quality. Moves originals to # _orig.jpg. # # Copyright Arto Teräs 1999-2003 # # Version: 1.02 # Licence: GNU General Public License (version 2 or any later version) # http://www.gnu.org/copyleft/gpl.txt # # Changelog: # # 1.0 Initial version # 1.01 Changed the output to interlaced (progressive) JPEG files. # 1.02 File name extension check fixed to accept capital letters. # # Latest version: http://www.iki.fi/ajt/software/thumbnailtools/ ###################################################################### # # Global defaults: # $QUALITY = 75; # output image quality, can be adjusted with the # command line option -q $NO_COMPRESS_IF_ORIGINAL = 1; # doesn't do the compression if there # already is a picture _orig.jpg # (not adjustable from command line) # ###################################################################### use Getopt::Std; sub find_program { # Quick check if the given program can be found in the PATH # This will work only on Unix machines... my $program = shift; @system_dirs = split(':', $ENV{PATH}); foreach (@system_dirs) { if (-x "$_/${program}") { return 1; } } # not found return 0; } # The main program # getopts('q:'); if (@ARGV) { if ($opt_q != 0) { $QUALITY = $opt_q; } # Check that the program convert can be executed: if (find_program("convert") == 0) { print STDERR "Couldn't find the \"convert\" utility (part of the ImageMagick package).\n\n"; print STDERR "Please make sure that it can be found in the PATH and try again.\n"; exit(1); } my $image; my $skip; foreach $image (@ARGV) { $skip = 0; # Accept filenames ending in .jpg, .JPG, .jpeg and .JPEG if ($image =~ /(.*)\.([jJ][pP][eE]{0,1}[gG])/) { my $basename = $1; my $extension = $2; my $origname = "$basename" . "_orig.${extension}"; # Let's preserve the original, if it doesn't exist if (-f $origname) { if ($NO_COMPRESS_IF_ORIGINAL) { print "Skipping image $image\n"; $skip = 1; } else { print "Processing image $image\n"; print "$origname already exists, using that!\n"; } } else { print "Processing image $image\n"; `mv $image $origname`; } # Generate compressed image if (! $skip) { `convert -quality $QUALITY -interlace Line $origname $image`; } } else { print "Skipping image $image\n"; } } } else { print "Usage: compress_images.pl [OPTIONS] IMAGEFILES (in jpeg format)\n\n"; print "Available options:\n"; print "-q quality the output jpeg quality (default ${QUALITY}%)\n"; exit(1); }