Creating thumbnails on the fly under FastCGI
A while ago I wrote about the problems I was having with trying to get Image::Magick to create thumbnails on the fly whilst running under FastCGI. Well, I was right then that the problem lay in the fact that FCGI ties STDOUT whilst Image::Magick also wants to access STDOUT to write to. I spent a couple more hours trying to figure out how to untie STDOUT, do the Image::Magick->Write to STDOUT then re-attach it to FCGI. No luck. The FCGI->Detach method didn't do it. Under hood was too complex for me to understand.
I retreated and looked at GD again. Similar problems, as well as a messier interface. Then I had a gander around seach.cpan.org and picked up on Imager. Thanks to the handy rating stars on the search pages it looked promising. And really, it is a breath of fresh air: well documented, developer-friendly interface, myriad options and ways to play with images (including the scale() method which automatically scales in proportion). And, crucially, you can write() your images to a scalar variable, which means you can then print that scalar and FCGI will scoop it up and print it out like any other print statement.
Job done: I can now make thumbnail images on the fly and send them back to the browser under FastCGI by dropping Image::Magick for the new and very impressive Imager.
I retreated and looked at GD again. Similar problems, as well as a messier interface. Then I had a gander around seach.cpan.org and picked up on Imager. Thanks to the handy rating stars on the search pages it looked promising. And really, it is a breath of fresh air: well documented, developer-friendly interface, myriad options and ways to play with images (including the scale() method which automatically scales in proportion). And, crucially, you can write() your images to a scalar variable, which means you can then print that scalar and FCGI will scoop it up and print it out like any other print statement.
Job done: I can now make thumbnail images on the fly and send them back to the browser under FastCGI by dropping Image::Magick for the new and very impressive Imager.
Here's an example script that would do the job described:
#!/usr/bin/perl
use Imager;
use FCGI;
use strict;
$| = 1;
my $dir = qw(../images/);
my $r = FCGI::Request();
while($r->Accept() >= 0) {
opendir(DIR, $dir);
my @files = grep { ! /^\./ } readdir DIR;
my $file = $files[int(rand($#files+1))];
my $image = Imager->new;
$image->read(file=>$dir.$file) or die $image->errstr;
my $thumb = $image->scale(xpixels=>80) or die $image->errstr;
my $data;
$thumb->write(type => 'png', data => \$data) or die $image->errstr;
print "Content-type: image/png\n\n";
binmode STDOUT;
print $data;
}

Leave a comment