Graphics.GDを使ってHaskellで画像の切り抜きをやってみた

in

キャプチャした画像を切り取るという頼まれ仕事がきたので、Perl/Image::Magickでやったのですが、フト勉強中のHaskellでも簡単にできるんきゃないかと思ってやってみました。

画像は某動画再生ソフトをPrn+Scrnで丸ごとキャプチャしたもので、Perlの場合、

#!/usr/bin/perl
#
use strict;
use Image::Magick;

my ($x,  $y)  = (540, 60);
my ($rx, $ry) = (105, 380);

my $png   = "Costa.png";
my $image = Image::Magick->new;
$image->Read($png);
my ($ow, $oh) = $image->Get('width', 'height');
$image->Crop(width => $ow - $rx - $x, height => $oh - $y - $ry, x => $x, y => $y);
my ($nw, $nh) = $image->Get('width', 'height');
$image->Set(page => "$nw" . "x" . "$nh+0+0");
$image->Write("pl$png");

こんなカンジ(実際には数百の画像があったのでforeachで回してますがアンコの部文だけ)。切り抜きたい位置も固定なので、最初にGraphicConverterで位置を確認し、そこを切り取って保存してます。ここにもありますが、注意が必要なのは、Widht/Hightを設定し直すことくらいです。こいつをベースにHaskellで書き直して見ました。

まず、Image::Magickの替わりなんですが、HackageDBのGraphicsをざっと見渡して基本っぽいGraphic.GDを選択・インストール。(依存関係でいくつか叱られましたが...)Setがないだけでほぼ同じ。

Perl(Image::Magick) Haskll(Graphic.GD)
new newImage
Read loadPngFile
Get imageSize
Crop copyRegion
Set -
Write savePngFile

ということで、

import Graphics.GD

cpyPoint  :: Point 
cpyRegion :: Size

cpyPoint  = (540,60)
cpyRegion = (105,380)

main = do src  <- loadPngFile "Costa.png"
          size <- imageSize src
          dest <- newImage (newSize size)
          copyRegion cpyPoint (newSize size) src (0,0) dest
          savePngFile "hsCosta.png" dest

newSize :: Size -> Size
newSize os = (w,h)
  where
    w = fst os - (fst cpyPoint) - (fst cpyRegion)
    h = snd os - (snd cpyPoint) - (snd cpyRegion)

ほぼそのままいけました。DropBoxにあったカエルちゃん(元画像はjpgでしたが都合上一度pngに変換しました)を切り抜いたりなんかできます。

こんなカンジです。Image::Magickで切り出した画像とならべてもほぼ同じですが、ファイルサイズが微妙に違うのでなにかが違うのでしょうがそこまで調べてません。GraphicConverterの「情報を見る」ではImage::Magickで切り出した画像は「PNG48ビットから24ビットに減色」となっていたのに対して、GDで切り出した方は特になんの記述もありませんでした。

実際にはImage::Magickの方が多機能だし慣れているので仕事は早く終わるのですが、少しでも機会をみつけてHaskellしないと全然勉強進まないので、他愛のない書き捨てコードだけど勉強には良かったかな。

添付サイズ
Costa.png1.6 MB
imgtrm.hs472 bytes
imgtrm.pl433 bytes