so i need to resize an image within perl. this is for games::risk, a perl implementation of the famous board game (btw, try it and tell me if you like it!). i want the background image to fit the window size on resize events. of course, i want it to be fast - but i also want something maintainable.
looking on cpan, i found 3 modules: gd, image::magick and image::imlib2. using gd to resize a picture is a nightmare, therefore i ditched it for image::resize which is a convenient wrapper around gd.
here are the needed incantations to resize:
- with imlib2
- with image::magick - note that the operation is done inplace, so one needs to clone the image first to compare the same things.
- with image::resize
my $old = Image::Imlib2->load($src);
my $new = $old->create_scaled_image($w, $h);
my $old = Image::Magick->new;
$old->Read($src);
my $new = $old->Clone;
$new->Scale(width=>$w, height=>$h);
my $old = Image::Resize->new($src);
my $new = $old->resize($w, $h);
however, image::imlib2 has a drawback: the only way to get back the new image is to save it to a file, where one can get the new image as a scalar directly:
- image::resize with $img->jpeg
- image::magick with $img->ImageToBlob
therefore, one must also take this into account in the benchmarking! so here's the latest version of the bench:
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use Benchmark qw{ :all };
use Image::Size;
use Image::Resize;
use Image::Imlib2;
use Image::Magick;
my $src = "src.jpg";
my $dst = "dst.jpg";
my ($w, $h) = imgsize($src);
my @sizes = (
[10,10], [100,100], [1000,1000],
[640,400], [840,600], [1024,768],
[$w,$h], [$w/2,$h/2], [$w/4,$h/4],
[$h,$w], [$h/2,$w/2], [$h/4,$w/4],
);
my $imlib2 = Image::Imlib2->load($src);
my $resize = Image::Resize->new($src);
my $magick = Image::Magick->new; $magick->Read($src);
foreach my $s ( @sizes ) {
my ($width, $height) = @$s;
say "-> ${width}x${height}";
local $/;
cmpthese( -3, {
imlib2 => sub {
my $img = $imlib2->create_scaled_image($width, $height);
$img->save($dst);
open my $fh, '<', $dst;
return <$fh>;
},
magick => sub {
my $img = $magick->Clone;
$img->Scale(width=>$width,height=>$height);
return $img->ImageToBlob;
},
resize => sub {
my $img = $resize->resize($width,$height);
return $img->jpeg; # $img->png
},
} );
say '';
}
and i was quite astonished to see that image::imlib2 is still 2 or 3 times faster that image::magick or image::resize!
so, imlib2 may not the best api around, but sure it's fast...