From owner-freebsd-questions Mon Sep 11 7: 8:21 2000 Delivered-To: freebsd-questions@freebsd.org Received: from smtpproxy1.mitre.org (mb-20-100.mitre.org [129.83.20.100]) by hub.freebsd.org (Postfix) with ESMTP id 5BD6437B424 for ; Mon, 11 Sep 2000 07:08:01 -0700 (PDT) Received: from avsrv1.mitre.org (avsrv1.mitre.org [129.83.20.58]) by smtpproxy1.mitre.org (8.9.3/8.9.3) with ESMTP id KAA15435 for ; Mon, 11 Sep 2000 10:07:54 -0400 (EDT) Received: from mailsrv2.mitre.org (mailsrv2.mitre.org [129.83.221.17]) by smtpsrv1.mitre.org (8.9.3/8.9.3) with ESMTP id KAA02184 for ; Mon, 11 Sep 2000 10:05:02 -0400 (EDT) Received: from mitre.org ([128.29.145.140]) by mailsrv2.mitre.org (Netscape Messaging Server 4.1) with ESMTP id G0Q79400.OX6; Mon, 11 Sep 2000 10:07:52 -0400 Message-ID: <39BCE73F.80D641D@mitre.org> Date: Mon, 11 Sep 2000 10:07:59 -0400 From: "Andresen,Jason R." Organization: The MITRE Corporation X-Mailer: Mozilla 4.73 [en]C-20000509M (Win98; U) X-Accept-Language: en MIME-Version: 1.0 To: Chip Cc: "freebsd-questions@freebsd.org" Subject: Re: Making thumbnail images References: <39BC0225.520792D6@wiegand.org> Content-Type: multipart/mixed; boundary="------------B99DCB6011E8489934A3C988" Sender: owner-freebsd-questions@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG This is a multi-part message in MIME format. --------------B99DCB6011E8489934A3C988 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Chip wrote: > > I am interested in a program that will take a large number (over > 600) of jpg images and create thumbnails of them. I have tried > something called qp and it doesn't seem to do squat. I also > looked > at webmagick but it appears to have a huge learning curve and I > just don't have time for that. Any other suggestions? Well, I've got this old perl script that I whipped up ages ago. You'll need netpbm and jpeg installed. The command like options you most likely want are: ./genindex -s index -f jpg [-i] You will need to edit a couple of paths near the top of the script if you want to use the -i option, just point them to the included html files (and modify those if you want. :) The -i generates HTML index pages with clickable imagemaps. Be warned, the netpbm code still has a bug that occasionally munges the colors on the generated index page. Caveat empretor. -- _ _ _ ___ ____ ___ ______________________________________ / \/ \ | ||_ _|| _ \|___| | Jason Andresen -- jandrese@mitre.org / /\/\ \ | | | | | |/ /|_|_ | Views expressed may not reflect those /_/ \_\|_| |_| |_|\_\|___| | of the Mitre Corporation. --------------B99DCB6011E8489934A3C988 Content-Type: text/plain; charset=iso-8859-1; name="genindex" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="genindex" #!/usr/bin/perl -w # genindex -- Generate indexes from JPEGs, GIFs, and PNGs using = # minimal disk space # Thanks to Jef Poskanzer for the original pnmindex, which gave me the # idea for this script. = # Copyright (C) 1991 by Jef Poskanzer. # Copyright (C) 1997 Jason Andresen # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, provid= ed # that the above copyright notice appear in all copies and that both that= # copyright notice and this permission notice appear in supporting # documentation. This software is provided "as is" without express or # implied warranty. # Revision History: # 1.0: Inital release, complete rewrite of Jef Poskanzer's pnmindex utili= ty # 1.1: Added -o support. # 1.2: Added support for different file output types (gif, jpeg). # 1.2.5: Checked extension of -o file to determine what type of compress= ion # to use on the output file. # 1.3: Added support for splitting output files. # 1.3.5: Added help screen # 2.0: Added the Client-Side imagemap generation option. # 2.1.1: Fixed bug with >2 indexes. # 2.1: Added the -r option to force remaking of directories. # 2.2: Added the -d option to show progress dots. # 2.3: Added the -p option to show percentage progress. # Libraries use Cwd; use English; use IO::Handle; # Set for autoflush STDOUT->autoflush(1); # Signal trapper handler sub sighand { system "rm -f $tempdir/$$.image.temp*"; system "rm -f $tempdir/$$.index.temp*"; exit (0); } # Trap all apropriate signals and clean up before quitting $SIG{INT}=3D'sighand'; $SIG{QUIT}=3D'sighand'; $SIG{HUP}=3D'sighand'; $SIG{KILL}=3D'sighand'; $SIG{TERM}=3D'sighand'; # Some user defined constants # These are the base web pages that are modified to create the imagemaps # you don't need to bother with these if you are not making client-side = # imagemaps (-i option). = # These files replace strings embeded in the HTML file to create the = # web pages. These are the strings: # *DIRECTORY Replaced with the imagemaps CWD # *SHORTDIR Replaced with the imagemaps Directory name # *MAPDEF Replaced with the imagemap Definition # *IMAP Replaced with the invocation of the Imagemap # *FILELIST Replaced with the list of imagemaps (for multiple # indexes) # The strings must be alone on the line: # Correct # ------- # Directory of = # *DIRECTORY # # # Incorrect # --------- # Directory of *DIRECTORY # See included examples for more information. $mappage =3D "/home/jandrese/bin/imap.html"; $multipage =3D "/home/jandrese/bin/mmap.html"; $mainout =3D "index.html"; $imapprefix =3D "subindex"; # Initalize the variables $size=3D100; # Scale each image to approx $size x $size $across=3D8; # Number of images across. $colors=3D256; # Maximum number of colors to use. $back=3D"-white"; # The default background color. $tempdir=3D"/tmp"; # Your temporary directoy. $outfile=3D"STDOUT"; # This is the output file. $outformat=3D"pnm"; # This is the format of the output. $jpegquality=3D75; # The quality of the jpeg output. = # ( 0 <=3D N <=3D 100 ) $splitprefix=3D""; # The prefix of the splitted files. $splitnum=3D6; # The number of rows per split index. $testmode=3D"FALSE"; # Test the index instead of actually creating it $verbose=3D"FALSE"; # Verbose mode. $dir=3Dcwd(); # Get the current working directory. $printhelp=3D"FALSE"; # Display the help message and quit. $genIMAP=3D"FALSE"; # Create a client side imagemap. $forceremake=3D"FALSE"; # Force the index to be remade, weather it # needs it or not. $showdots=3D"TRUE"; # Show percentage dots $termwidth=3D80; # Width of the terminal in characters $showperc=3D"FALSE"; # Show progress as a percentage # Process all of the command line arguments while ( $arg =3D shift ) { SWITCH: { if ( $arg eq "-black" ) { $back=3D"-black"; last SWITCH; } if ( $arg eq "-white" ) { $back=3D"-white"; last SWITCH; } if ( $arg eq "-size" ) { $size =3D shift; last SWITCH; } if ( $arg eq "-across" ) { $across =3D shift; last SWITCH; } if ( $arg eq "-colors" ) { $colors =3D shift; last SWITCH; } if ( $arg eq "-depth" ) { $colors =3D 2**shift; last SWITCH; } if ( $arg eq "-o" ) { $outfile =3D shift; last SWITCH; } if ( $arg eq "-f" ) { $outformat =3D shift; last SWITCH; } if ( $arg eq "-s" ) { $splitprefix =3D shift; last SWITCH;} if ( $arg eq "-sn" ) { $splitnum =3D shift; last SWITCH; } if ( $arg eq "-t" ) { $testmode =3D "TRUE"; last SWITCH; } if ( $arg eq "-v" ) { $verbose =3D "TRUE"; last SWITCH; } if ( $arg eq "-h" ) { $printhelp =3D "TRUE"; last SWITCH; } if ( $arg eq "-i" ) { $genIMAP =3D "TRUE"; last SWITCH; } if ( $arg eq "-r" ) { $forceremake =3D "TRUE"; last SWITCH; } if ( $arg eq "-d" ) { $showdots =3D "TRUE"; = $showperc =3D "FALSE"; last SWITCH; } if ( $arg eq "+d" ) { $showdots =3D "FALSE"; last SWITCH; } if ( $arg eq "-p" ) { $showperc =3D "TRUE"; = $showdots =3D "FALSE"; last SWITCH; } if ( $arg eq "+p" ) { $showperc =3D "FALSE"; last SWITCH; } print STDERR "Sorry, I don't understand $arg.\n"; } } # Help screen if ( $printhelp eq "TRUE" ) { print "$0: Generate indexes.\n"; print "\n"; print "This script generates an index image (thumbnails with names)\n"; print "in the directory it is executed in. Several options are\n"; print "recognised, including:\n"; print "\t-black: black background\n"; print "\t-white: white background\n"; print "\t-size: size of thumbnail, default: $size\n"; print "\t-across: number of thumbnails in a row, default: $across\n"; print "\t-colors: number of colors to quanitize to, default: $colors\n";= print "\t-depth: final image depth (duplicates colors, as 2**depth)\n"; print "\t-o: outfile, filename for single output (example: index.gif)\n"= ; print "\t-f: outformat, format for index (gif, jpg, pnm)\n"; print "\t-s: Split prefix, prefix to append to split files (ex: index)\n= "; print "\t-sn: Number of rows in a split index, default: $splitnum\n"; print "\t-t: Testmode, only print out what would be done.\n"; print "\t-v: Verbose, tell the user way more than they need to know.\n";= print "\t-h: But you've found this feature already ;)\n"; print "\t-i: Generate a client side imagemap HTML file for index\n"; print "\t-r: Remake the index, even if it does not need it\n"; print "\t-d: Show progress dots (do not use with -v)\n"; print "\t-p: Show progress meter as a percentage\n"; exit(0); } # Set up some temporary variables $pict =3D 0; $splitpict =3D 0; $dotpos =3D 0; # Check to see if the index needs to be remade or not if ($verbose eq "TRUE" ) { print STDERR "Checking to see if the index for $dir needs to be updated.= \n" } if ( -e ".index.txt" ) { system ("ls > .$$.index.new.txt"); $diffout =3D `diff .index.txt .$$.index.new.txt`; unlink(".$$.index.new.txt"); if ($diffout eq "") { if ($verbose eq "TRUE" || $testmode eq "TRUE" ) { print STDERR "$dir is up to date\n"; } if ( $forceremake eq "FALSE" ) { # Do not exit if we are going to force the index to # be remade, but exit if we aren't and the directory # has not changed. exit 0; # The index is up to date } } = else { if ($testmode eq "TRUE") { die "$dir needs to be updated.\n"; } } } if ($testmode eq "TRUE") { die "$dir needs to be updated.\n"; } if ($verbose eq "TRUE" ) { print STDERR "Determining output format.\n"; } # Figure out what type of file the user wants as output $tpos =3D -1; $pos =3D $tpos; while (( $tpos =3D index($outfile, ".", $tpos)) > -1 ) { $pos =3D ++$tpos; } $extn =3D substr($outfile, $pos); # Set up the output format filters for the output you select if ( $outformat eq "gif" || $extn eq "gif" ) { = $outfilter=3D" | ppmtogif -quiet "; = $outformat=3D"gif"; $extn=3D"gif"; } elsif ( $outformat eq "jpeg" || $outformat eq "jpg" || $extn eq "jpg" || $extn eq "jpeg" ) { = $outfilter=3D" | cjpeg -optimize -quality $jpegquality "; = $outformat=3D"jpeg"; $extn=3D"jpg"; } else { = $outfilter=3D""; $outformat=3D"pnm"; $extn=3D"pnm"; } if ($verbose eq "TRUE") { print STDERR "File: $outfile, Format: $outformat, Extension: $extn.\n"; } # This is a hack that removes the old index first (only if it is named th= e = # same as the index you are creating. This is to prevent the inclusion o= f = # old indexes in the new index. if ($splitprefix ne "") { system("rm -f $splitprefix*$extn"); } if ($outfile ne "STDOUT") { system("rm -f $outfile"); } # Get all of the known images from the current directory @images=3Dsort glob("*.{gif,jpg,png}"); $numImages=3D@images; $currsplitnum=3D0; $makenew=3D1; # Display the dot header, if we have one if ( $showdots eq "TRUE" ) { print "Index for $dir\n"; print "0 10 20 30 40 50 60 70 80= 90 100\n"; } if ( $showperc eq "TRUE" ) { print "Index for $dir\n"; print "00%"; } # HTML generation Initalization area if ( $genIMAP eq "TRUE" ) { @rowwidths =3D $_; # The width of each row = @rowheights =3D $_; # The height of each row @xsize =3D $_; # The x dimention of each thumbnail $currrow =3D 0; # The current row number (starting at 0) } if ($verbose eq "TRUE" ) { print STDERR "Generating index now...\n"; } # Generate the index while ($pict < $numImages) { @rownames=3D$_; # Create a row. for ($lcv =3D 0; $lcv < $across && $pict < $numImages; $lcv++) { $type =3D `file -L $images[$pict]`; SWITCH: { if ($type =3D~ /GIF/ ) { system "giftopnm -quiet $images[$pict] | pnmscale -xysize $size $size= -quiet | ppmquant -quiet $colors > $tempdir/$$.index.temp.$lcv"; last SWITCH; } if ($type =3D~ /JPEG/ ) { system "djpeg -pnm -fast $images[$pict] | pnmscale -xysize $size $siz= e -quiet | ppmquant -quiet $colors > $tempdir/$$.index.temp.$lcv"; last SWITCH; } if ($type =3D~ /PNG/ ) { system "pngtopnm $images[$pict] | pnmscale -xysize $size $size -quiet= | ppmquant -quiet $colors > $tempdir/$$.index.temp.$lcv"; last SWITCH; } system "ppmmake rgb:ff/ff/ff $size $size > $tempdir/$$.index.temp.$lcv= "; } if ( -z "$tempdir/$$.index.temp.$lcv" ) { # File is corrupt or something, I'll make a # placeholder system "pbmtext \"Corrupt\" > $tempdir/$$.index.temp.$lcv"; } = # Add the text to the bottom of the images if ( $back eq "-white" ) { system "pbmtext \"$images[$pict]\" | pnmcat $back -tb $tempdir/$$.inde= x.temp.$lcv - > $tempdir/$$.image.temp.$lcv"; } else { system "pbmtext \"$images[$pict]\" | pnminvert | pnmcat $back -tb $tem= pdir/$$.index.temp.$lcv - > $tempdir/$$.image.temp.$lcv"; } system "rm -f $tempdir/$$.index.temp.$lcv"; $rownames[$lcv] =3D "$tempdir/$$.image.temp.$lcv "; if ($verbose eq "TRUE") = { print STDERR "Picture $images[$pict] complete on position $lcv...\n"; } = # Add the info to the HTML generation arrays if we're = # generating the client side imagemap if ( $genIMAP eq "TRUE" ) = { open THUMBNAIL, "$tempdir/$$.image.temp.$lcv"; $xtmp =3D ; # Skip the magic number $xtmp =3D ; $xsize[$pict] =3D (split / /,$xtmp)[0]; close THUMBNAIL; = # Clean up some of the namespace undef $xtmp; } $pict++; # Update the counter of the screen, if it was requested if ( $showdots eq "TRUE" ) { $currdotpos =3D $pict / $numImages * $termwidth; for ( ; $dotpos < $currdotpos; $dotpos++) { print "."; } STDOUT->flush; } if ( $showperc eq "TRUE" ) { $currdotpos =3D $pict / $numImages; printf "=08=08=08%02d%%", $currdotpos; STDOUT->flush; } = } # Done creating the row. = # Now join all of the pictures in the row together into a single row system "pnmcat $back -lr -jbottom @rownames > $tempdir/$$.index.temp.row= "; = if ($verbose eq "TRUE") { print STDERR "Joining that row.\n"; } = # If we're generating an Client side imagemap, then get the info for # the current row if ( $genIMAP eq "TRUE" ) { open CURRROW, "$tempdir/$$.index.temp.row"; $rtmp =3D ; # Skip the magic number $rtmp =3D ; @rowsize =3D (split / /,$rtmp); $rowwidths[$currrow] =3D $rowsize[0]; $rowheights[$currrow++] =3D $rowsize[1]; close CURRROW; # Just a little tiding up... undef $rtmp; undef @rowsize; } = if ( $splitprefix ne "" && = (( $splitpict % $splitnum ) =3D=3D 0 ) = && $splitpict > 0 = ) { $outfile =3D "$splitprefix$currsplitnum"; if ($outformat eq "gif") { $outfile =3D "$outfile.gif"; } elsif ( $outformat eq "jpeg") { $outfile =3D "$outfile.jpg"; } else { $outfile =3D "$outfile.pnm"; } system "cat $tempdir/$$.index.temp | ppmquant -quiet $colors $outfilter = > $outfile"; $currsplitnum++; $makenew=3D1; } $splitpict++; = # Finally, append that row to the index file (creating a new one if it # doesn't exist) if ( $makenew =3D=3D 1 ) = { $makenew =3D 0; system "mv $tempdir/$$.index.temp.row $tempdir/$$.index.temp"; } else { system "pnmcat $back -tb $tempdir/$$.index.temp $tempdir/$$.index.temp.= row > $tempdir/$$.index.temp.2"; system "mv $tempdir/$$.index.temp.2 $tempdir/$$.index.temp"; } } if ($verbose eq "TRUE" ) { print STDERR "Compressing imagemap...\n"; } if ($splitprefix ne "") { if ( $currsplitnum =3D=3D 0 ) { $outfile =3D $splitprefix ; } else { $outfile =3D "$splitprefix$currsplitnum"; } if ( $outformat eq "gif" ) { $outfile =3D "$outfile.gif"; } elsif ( $outformat eq "jpeg") { $outfile =3D "$outfile.jpg"; } else { $outfile =3D "$outfile.pnm"; } system "cat $tempdir/$$.index.temp | ppmquant -quiet $colors $outfilter = > $outfile"; } elsif ( $outfile eq "STDOUT" ) { $redir=3D""; } else { $redir=3D" > $outfile"; } if ( $splitprefix eq "") { system "cat $tempdir/$$.index.temp | ppmquant -quiet $colors $outfilter = $redir"; } system "rm -f $tempdir/$$.image.temp*"; system "rm -f $tempdir/$$.index.temp*"; # Generate the HTML for a client side image map if the option -i was set # Client side imagemaps work like this: # In the head (or anywhere in the HTML), there is an imagemap definition.= # The format looks like so: # First a header with the image map's name # # Then the area definitions, these are the regions that the user is suppo= sed # to click on: # 3D"filename" # finally, you include a default region, that does nothing for areas outs= ide # of the picture # # And at the end, the standard closing tag # # Now to use the imagemap, simply put a tag in your HTML like so: # if ( $genIMAP eq "TRUE" ) { $numrows =3D @rowwidths; # First we have to determine if we have multiple indexes if ( $splitprefix ne "" && $currsplitnum > 0 ) { # There are multple indexes. This is tricky, now we have # to create a top level index of indexes and let the user # choose which index to look at. = processHTML($multipage, $mainout, 0, $numrows, = @rowwidths, @rowheights); for ( $lcv =3D 0; $lcv <=3D $currsplitnum; $lcv++) { processHTML($mappage, "$imapprefix$lcv.html", $lcv, $numrows, @rowwidths, @rowheights); } } else { # There is only one index to catagorize, do not make the # chooser page. = processHTML($mappage, $mainout, 0, $numrows, @rowwidths, @rowheights); } } system("ls > .index.txt"); if ($verbose eq "TRUE") { print STDERR "Done.\n"; } if ( $showdots eq "TRUE" ) { print "\n"; } if ( $showperc eq "TRUE" ) { print "=08=08=08100%\n"; } exit 0; # This is the HTML generation subroutine. It does the actual work of # generating the imagemaps through processing the template files. Be car= eful, # this subroutine cannot tell the difference between index files and # multi-index files, so no error checking can be preformed. (This may # actually be a feature :) # The indexnum is not required if you are generating the multi-index. sub processHTML ( $$$$@@ ) { $template =3D shift; $htmloutfile =3D shift; $indexnum =3D shift; $numrows =3D shift; my $shortdir =3D $dir; $shortdir =3D~ s#.*?/([^/]*)$#$1#; for ( $foolcv =3D 0; $foolcv < $numrows; $foolcv++) { $rowwidths[$foolcv] =3D shift; } for ( $foolcv =3D 0; $foolcv < $numrows; $foolcv++) { $rowheights[$foolcv] =3D shift; } if ($verbose eq "TRUE") { print STDERR "Processing HTML file $template into $htmloutfile.\n" } = open TEMPLATE, $template or die "I cannot open $template, please set tha= t constant.\n"; open OUTFILE, ">$htmloutfile" or die "I cannot open $htmloutfile, check = the permissions.\n"; while ( $html =3D