perl で画像処理

ちょっとゴニョゴニョした画像処理をやることになりました。

perl でさらっと出来ないかと思いましたが...

GD
Image::Magick
Imager


正直、アタクシのレベルでは「どれがいいのー!?」

という感じです。

とは言うものの、悩んでいてもしかたないので
まずはベンチです。ベンチ。

要件

 * JPEG 
 * 600px * 800px
 * 48.37 KB

を とりあず端から端までラスタスキャンしてRGB値を取得する。

これを 10 回繰り返す。

環境

cpu:Intel(R) Core(TM)2 Quad CPU Q9400 @ 2.66GHz
mem:3G
os: CentOS 5.2(32bit)


すると以下のような結果に...

Benchmark: timing 10 iterations of GD, IMAGER, MAGICK...
        GD: 16 wallclock secs (16.58 usr +  0.03 sys = 16.61 CPU) @  0.60/s (n=10)
    IMAGER: 57 wallclock secs (56.42 usr +  0.01 sys = 56.43 CPU) @  0.18/s (n=10)
    MAGICK: 11 wallclock secs (11.11 usr +  0.10 sys = 11.21 CPU) @  0.89/s (n=10)
       s/iter IMAGER     GD MAGICK
IMAGER   5.64     --   -71%   -80%
GD       1.66   240%     --   -33%
MAGICK   1.12   403%    48%     --


うーん。こんなに差があった。

って事で今回はperlでやるならImage::Magick を採用。

スクリプト

#!/usr/bin/env perl

use strict;
use warnings;

use Benchmark qw(timethese  cmpthese);
use GD;
use Image::Magick;
use Imager;

=head
/*
 * [ 今回の画像スペック ]
 * JPEG 
 * 600px * 800px
 * 48.37 KB
 *
 */
=cut
use constant ImageFile => 'target.jpg';
use constant Count     => 10;

my $comp = timethese(
    Count,
    {
      GD     => \&_f1,
      MAGICK => \&_f2,
      IMAGER => \&_f3,
    }
);

cmpthese $comp;
exit();

sub _f1 {
  my $im = new GD::Image(ImageFile) || die;
  my ($width,$height) = $im->getBounds();

  for( my $j=0; $j<$height; $j++ ){
    for( my $i=0; $i<$width; $i++ ){

      my ($r,$g,$b) = $im->rgb($im->getPixel($i,$j));

      my %RGB = (
        R => $r,
        G => $g,
        B => $b
      );
    }
  }
  return;
}

sub _f2 {
  my $im = Image::Magick->new();
  $im->Read(ImageFile);
  my ($w, $h) = $im->Get('width', 'height');

  my @color_list = $im->GetPixels(
    width  => $w,
    height => $h,
    x      => 0,
    y      => 0,
    map    => 'RGB'
  );

  while (@color_list > 0) {
    my %RGB = (
      R => int(shift @color_list) / 256,
      G => int(shift @color_list) / 256,
      B => int(shift @color_list) / 256
    );
  }
}

sub _f3 {

  my $im = Imager->new();
  $im->read( file=>ImageFile ) or die $im->errstr;

  for( my $j=0; $j<$im->getheight(); $j++ ){
    for( my $i=0; $i<$im->getwidth(); $i++ ){
      my $color = $im->getpixel( 'x'=>$i, 'y'=>$j );
      my ($r, $g, $b, $a) = $color->rgba();

      my %RGB = (
        R => $r,
        G => $g,
        B => $b
      );
    }
  }
}