実践 Acme::Spinner

techno-cat
2011-12-04

Win32 Trackが懐かしい techno-cat (@techno_neko) デス。

探し求めていたモジュールはAcmeでした

画像データを扱うと、なかなか結果が返って来なくて。それで、プログレスバーみたいなのがあればいいなーって思ってたのですが、そんな大げさじゃなくていいから、動いてるよって教えてくれるモジュールを探してました。

そして、ついに見つけてしまったのです、Acme::Spinnerを。

使い方

use strict;
use Acme::Spinner;

# 時間のかかる処理
my $spinner = Acme::Sipnner->new();
for my $i (0..100) {
	print STDERR $spinner->next . "\r";

	# いろいろやる

}

すると、

|
\
-
/

の順番でアニメーションする。

ちゃんとやる

ちゃんとアニメーションさせるには、

print STDERR $spinner->next . "\r";

が呼ばれるタイミングだったり、回数を制御しなきゃいけなくて、
例えば画像をモノクロに変換する処理の場合はこんな感じ。

use warnings;
use strict;
use Imager;
use Acme::Spinner;

my $img = Imager->new( file=>$ARGV[0] ) or
	die Imager->errstr();

my $spinner = Acme::Spinner->new();
for my $y (0..$img->getheight-1) {

	# ここで出力タイミングを制御
	# この例だと、16の倍数で1回出力
	if ( ($y & 0x0F) == 0 ) {
		print STDERR $spinner->next . "\r";
	}

	my @colors = $img->getscanline( y=>$y );
	my @pixels = ();
	foreach my $color (@colors) {
		my ($red, $green, $blue, $alpha) = $color->rgba;
 
		my $y = $red + $green + $green + $blue;
		$y = int( $y / 4 );
 
		push @pixels, ( $y, $y, $y, $alpha );
	}
	$img->setscanline( y=>$y, pixels=>pack('C*', @pixels) );
}
 
$img->write( file=>'result.jpg' ) or
	die "Cannot write: ",$img->errstr;
 
__END__

注意点としては、
STDERRにprintし過ぎるとアニメーションが急に遅くなる(?)ので、結果を見ながら出力頻度を調整しました。

まとめ

ね、便利でしょ。(棒)

さ〜て、明日はどなたでしょうか???