Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

thumbnails generator

by spx2 (Deacon)
on Apr 20, 2008 at 15:21 UTC ( #681786=CUFP: print w/replies, xml ) Need Help??

I've seen allot of people asking for thumbnail generators and
scripts solving some problem similar to this.
I also needed to do this recently so I spent some minutes writing a script
for it.
It's not the most interesting/efficient thing but it cuts some time and
probably it will help somebody.
I tested it using Windows.It is dependant on Image Magick.
The exact behaviour is the following:
1)get all files in directory
2)traverse each and every one of them and see if it has usual image extension
3)if 2 happens then it gets dimensions of image
4)if height>width then it uses some predefined resolutions to which it creates new
copies of the image scaled down to the predefined resolutions.
5)if width>height it reverses the predefined resolutions height with width and does the same
as described in step 4


use strict; use warnings; my @Ll=(800,600); my @Ls=(108,81); sub get_dimensions { my ($N)=@_; my $o = `identify $N`; my ($X,$Y) = $o=~ /\ (\d+)x(\d+)\ /; return ($X,$Y); } sub convert { my ($X,$Y,$N,$M)=@_; #X,Y dimensions to convert to #N-original name of file #M-name of converted/modified file my $cmd = "convert -resize %s %s %s"; $cmd=sprintf $cmd,"$X".'x'."$Y!",$N,$M; `$cmd`; #print $cmd; } sub convert_small_large { my ($N)=@_; my ($name,$ext)=split '\.',$N; my ($Xi,$Yi)=get_dimensions $N; if($Xi>$Yi) { convert @Ll,$N,"$name-l.$ext"; convert @Ls,$N,"$name-s.$ext"; } else { convert reverse @Ll,$N,"$name-l.$ext"; convert reverse @Ls,$N,"$name-s.$ext"; }; } my @files = <*>; print join "\n",@files; for (@files) { print "converting $_ ...\n"; my $namelow=lc $_; next unless $namelow =~ /(gif|bmp|jpg|wmf|jpeg|png)$/; eval { convert_small_large $_; }; }

Replies are listed 'Best First'.
Re: thumbnails generator
by zentara (Archbishop) on Apr 20, 2008 at 16:42 UTC
    I know you admit it's not the most efficient, but if you had alot of thumbs to convert, I would think you would be better off doing it all in Perl, and not calling convert thru system for each image. The ImageMagick object can be created once, cleaned out of data, and reused for the next image. I havn't benchmarked it, but I think it would be much more efficient that way. For anyone looking, it would be done something like this, to reuse a single IM object.
    #!/usr/bin/perl use warnings; use strict; use Image::Magick; my $image = Image::Magick->new; umask 0022; my @pics= <*.jpg>; #my @pics= <*.jpg *.gif *.png>; #add all your extensions here foreach my $pic (@pics){ my ($picbasename) = $pic =~ /^(.*).jpg$/; my $ok; $ok = $image->Read($pic) and warn ($ok); my $thumb = $picbasename . '-t.jpg'; $image->Scale(geometry => '100x100'); $ok = $image->Write($thumb) and warn ($ok); undef @$image; #needed if $image is created outside loop print "$pic -> $thumb\n"; }

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum

      Now there is a good reason to do it in Perl! I don't think it would be much slower than a script, but that might be worth testing.

      #!/bin/bash shopt -s nullglob for image in *.{gif,bmp,jpg,wmf,jpeg,png} do printf "Converting $image\n" bits=(`/usr/bin/identify -format "%h %w" "$image"`) if [ ${bits[0]} -gt ${bits[1]} ] then sizes=(600x800 81x108) else sizes=(800x600 108x81) fi ext=${image##*.} /usr/bin/convert -resize ${sizes[0]}! "$image" "${image/.$ext/-l.$ +ext}" /usr/bin/convert -resize ${sizes[1]}! "$image" "${image/.$ext/-s.$ +ext}" done

      Update: Fixed a few subtle problems in the script that surfaced with more extensive testing (not that anybody will care, this not being Perl - but I do. :)

      
      -- 
      Human history becomes more and more a race between education and catastrophe. -- HG Wells
      
Re: thumbnails generator
by oko1 (Deacon) on Apr 20, 2008 at 16:04 UTC

    Since you're not really using Perl to do anything but arrange the various *nix programs, why not use a shell script instead? It would be simpler, shorter, and wouldn't involve spawning an unnecessary interpreter.

    #!/bin/bash for image in *.{gif,bmp,jpg,wmf,jpeg,png} do size=`/usr/bin/identify $image` ... [do whatever with "$size" here] ... convert -geometry 800x600 $image ${image/./-l.} convert -geometry 80x60 $image ${image/./-s.} done

    ...and so on. This may be just a personal quirk of mine, but I find shell scripts (or batch files) coerced into another language (whatever it happens to be) gratingly pointless.

    Update: Incidentally, it fails in Linux.

    ben@Tyr:/tmp/Sorayama$ ../thumbnail hajime1.jpg hajime10.jpg hajime2.jpg hajime3.jpg hajime4.jpg hajime5.jpg hajime6.jpg hajime7.jpg hajime8.jpgconverting hajime1.jpg ... convert: invalid argument for option `hajime1-l.jpgxhajime1.jpg!': -re +size. convert: invalid argument for option `hajime1-s.jpgxhajime1.jpg!': -re +size. converting hajime10.jpg ... converting hajime2.jpg ... convert: invalid argument for option `hajime2-l.jpgxhajime2.jpg!': -re +size. convert: invalid argument for option `hajime2-s.jpgxhajime2.jpg!': -re +size. converting hajime3.jpg ... convert: invalid argument for option `hajime3-l.jpgxhajime3.jpg!': -re +size. convert: invalid argument for option `hajime3-s.jpgxhajime3.jpg!': -re +size. converting hajime4.jpg ... convert: invalid argument for option `hajime4-l.jpgxhajime4.jpg!': -re +size. convert: invalid argument for option `hajime4-s.jpgxhajime4.jpg!': -re +size. converting hajime5.jpg ... convert: invalid argument for option `hajime5-l.jpgxhajime5.jpg!': -re +size. convert: invalid argument for option `hajime5-s.jpgxhajime5.jpg!': -re +size. converting hajime6.jpg ... convert: invalid argument for option `hajime6-l.jpgxhajime6.jpg!': -re +size. convert: invalid argument for option `hajime6-s.jpgxhajime6.jpg!': -re +size. converting hajime7.jpg ... converting hajime8.jpg ... convert: invalid argument for option `hajime8-l.jpgxhajime8.jpg!': -re +size. convert: invalid argument for option `hajime8-s.jpgxhajime8.jpg!': -re +size.
    
    -- 
    Human history becomes more and more a race between education and catastrophe. -- HG Wells
    
      I agree but I don't know much bash/shell scripting so I'm using what I know.
      Also shell scripting is not very flexible.In particular,what you wrote there
      in brackets "do whatever with $size here" will probably not be accomlished
      very easily using shell scripting.

        Actually, it is indeed accomplished very easily. The fact that it's so complicated in your script is a demonstration that you're coercing a square peg into a round hole.

        size=`/usr/bin/identify "$image"|/usr/bin/cut -d' ' -f 3` /usr/bin/convert -geometry "$size" "$old_name" "$new_name"
        
        -- 
        Human history becomes more and more a race between education and catastrophe. -- HG Wells
        
Re: thumbnails generator
by GrandFather (Saint) on Apr 20, 2008 at 20:43 UTC
Re: thumbnails generator
by Lu. (Hermit) on Apr 21, 2008 at 09:22 UTC
    You don't really need to check whether the image is 800x600 or 600x800, actually. Image::Magick will do that on its own if you convert to '108x108', converting the longest side to 108 px, and the shortest to whatever it would proportionally amount to.

    Here is some code I've been using to generate an HTML index for images files, with thumbnails :
    #!/usr/bin/perl use strict; use warnings; use utf8; use Image::Magick; my $dir = $ENV{'PWD'}; chomp(my @files = `ls $dir`); if (-e "$dir/thumbs") { print STDERR "The directory $dir/thumbs already exists. Files inside + may be replaced.\n Do you want to continue ? (y/n)"; chomp(my $choice = <STDIN>); if ($choice =~ /^n/) { print STDERR "Aborted by user.\n"; exit(1); } else { if (!($choice =~ /^y/)) { print "Please enter 'y' or 'n' :"; } } } mkdir "$dir/thumbs" || die "Unable to create directory $dir/thumbs :$! +"; if (!(-e "$dir/index.html")) { open (OUT, ">:utf8", "index.html") || die "Unable to open file $dir/ +index.html : $!" } print OUT <<HERE; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w +3.org/TR/xhtml1/xhtml1-strict.dtd"> <html encoding="utf8"> <head> </head> <body> <h1>Contents of directory $dir</h1> HERE foreach my $file (@files) { if ($file =~ /\.(jpg|jpeg|bmp|gif|png)/) { my $image = Image::Magick->new(); $image->Read($file); $image->Resize('150x150'); $image->Write("thumbs/t_$file"); print OUT "<a href=\"$file\"><img src=\"thumbs/t_$file\"></a>\n"; } } print OUT "\n</body>\n</html>\n"; close OUT;
    Lu.
      very nice. except for the fact that Image::Magick wouldn't let itself installed on my system. I used cpan and I got some errors which I was not able to fix. so that's why I went in the shell scripting phase.

        It's a while since I was using it, but my recollection is that Image Magick's install provided the Perl bindings.


        Perl is environmentally friendly - it saves trees
        as GrandFather said, if you install Image Magick, the Perl bindings will be installed as well.

        cpan didn't work for me either, so I just built Image Magick from source, and now it works very well.

        Lu.
Re: thumbnails generator
by hawtin (Prior) on Apr 21, 2008 at 15:36 UTC

    Here is another Perl implementation, this time using the GD module. I have to say that this is quite slow, at least for my purposes. This runs on Windows and Linux.

    In this code I call a number of support routines, but I think it is clear what they do and so I leave replacement as an exercise for the reader.

    sub thumbnail { my($dir,$src_name) = @_; my($target_width,$target_height,$minratio); # You will have to fetch suitable parameters here # in my software Attribute::get() assigns a value # to the passed variable. You could have (for example) # # $target_width = 100; Attribute::get("$dir/$src_name","thumb_file_width", \$target_width,1); Attribute::get("$dir/$src_name","thumb_file_height", \$target_height,1); Attribute::get("$dir/$src_name","thumb_file_minratio", \$minratio,1); $minratio = 9 if(!defined $minratio || $minratio < 1); my($x_scale,$y_scale); my $gd = GD::Image->new("$dir/$src_name"); if(!defined $gd) { # Again a magic routine, you could replace # with carp() ::add_output("Failed to read image data from $dir/$src_name"); return undef; } my($src_width,$src_height) = $gd->getBounds(); if(!defined $target_width && !defined $target_height) { ::add_output("Resizize must define either width or height"); return undef; } $target_width = int($src_width*$target_height/$src_height) if(!defined $target_width || $target_width <= 0); $target_height = int($src_height*$target_width/$src_width) if(!defined $target_height || $target_height <= 0); if($target_width <= 0 || $target_width >= 16000 || $target_height <= 0 || $target_height >= 16000) { ::add_output("Cannot resize image to $target_width x $target_h +eight"); return undef; } if((($src_width*$src_height)/($target_width*$target_height)) < $mi +nratio) { # The thumbnail image does not save enough space to be worth c +reating return undef; } my $new_gd = GD::Image->new($target_width, $target_height); $new_gd->copyResampled($gd,0,0,0,0, $target_width,$target_height, $src_width,$src_height); # Now lets save it # I should keep a track of all the thumbnails # and allocate new entries # in order, but for the moment I will be a bit cruder my $target_filename = GenName::obtain("$dir/$src_name", "thumb",$dir); return undef if(!defined $target_filename); if(default_type() eq "gif") { my $fh = IO::File->new(">$dir/$target_filename"); binmode $fh; print $fh $new_gd->gif(); $fh->close(); } else { ::add_output("Cannot yet produce thumbnail in ". default_type()." format\n"); return undef; } # We succeeded FileCounts::inc('thumb'); ::set_hidden("$dir/$target_filename") if($::hide_wfolio); return $target_filename; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://681786]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (2)
As of 2022-10-02 11:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My preferred way to holiday/vacation is:











    Results (8 votes). Check out past polls.

    Notices?