Imagerでポスタリゼーション

だいぶ暑くって、うまく頭が回らないですが、
ポスタリゼーションに挑戦してみようと思います。

難しいところは、0から255の直線的な配列を階段状にするところ。
要素数が256個を10区間に分割すると、25.6個ずつ・・・暑い。。。

という訳で、分かりやすく8区間でやってみましょう。

use v5.14;
use strict;
use warnings;
use Imager;

if ( (not @ARGV) or (not -e $ARGV[0]) ) {
    say "Usage:
    perl $0 file_path";
    exit( 0 );
}

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

my $n = 8;
my @table = 0..255;

my $st = 0;
foreach my $i (1..$n) {
    my $en = int( ($i * scalar(@table)) / $n );
    my $val = int( 255 * (($i - 1) / ($n - 1)) );
    for (my $j=$st; $j<$en; $j++) {
        $table[$j] = $val;
    }

    printf( "%3d <= x < %3d : %3d\n", $st, $en, $val );

    $st = $en;
}

$img->map( all => \@table );

$img->write( file => $0 . '.jpg', jpegquality => 90 );

すると、こんな感じで階段状になります。
$ perl aaa.pl 20140803-1.jpg
0 <= x < 32 : 0
32 <= x < 64 : 36
64 <= x < 96 : 72
96 <= x < 128 : 109
128 <= x < 160 : 145
160 <= x < 192 : 182
192 <= x < 224 : 218
224 <= x < 256 : 255

あと、21行目を、

my $val = int( 255 * (($i - 1) / ($n - 1)) );

から、

my $val = int( 255 * ((($i - 1) / ($n - 1)) ** .5) );

に変えると、ふわっと明るくなります。

という訳で、元画像とポスタリゼーションはこちら。

20140803-1  20140805-1

あと、ふわっと明るくなった画像。

20140805-2

ちなみに、Imager::Filtersを見ると、ポスタリゼーションが存在するので、
こんな感じで簡単に書けます。

use v5.14;
use strict;
use warnings;
use Imager;

if ( (not @ARGV) or (not -e $ARGV[0]) ) {
    say "Usage:
    perl $0 file_path";
    exit( 0 );
}

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

my $n = 8;
$img->filter( type => 'postlevels', levels => $n )
  or die $img->errstr;

$img->write( file => $0 . '.jpg', jpegquality => 90 );

ちょっと、仕上がりが違うっぽいけどね。

おしまい。

Leave a Comment