File Coverage

blib/lib/Image/Magick/PixelMosaic.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Image::Magick::PixelMosaic;
2              
3 1     1   38185 use strict;
  1         4  
  1         55  
4 1     1   5 use warnings;
  1         3  
  1         395  
5              
6             our $VERSION = '0.03';
7             $VERSION = eval $VERSION; # see L
8              
9 1     1   529 use Image::Magick;
  0            
  0            
10              
11             =head1 NAME
12              
13             Image::Magick::PixelMosaic - Pixelized mosaic filter for Image::Magick.
14              
15             =head1 SYNOPSIS
16              
17             use Image::Magick;
18             use Image::Magick::PixelMosaic;
19              
20             my $img = Image::Magick->new;
21             $img->Read('hoge.jpg');
22             my $pix = Image->Magick::PixelMosaic->new;
23             $pix->src($img);
24              
25             # generates 4x4 pixelized mosaic on area (100,120)-(180,160)
26             $pix->pixelize('80x40+100+120', [4,4]);
27              
28            
29             =head1 DESCRIPTION
30              
31             This module generates pixelized mosaic on parts of images using L.
32              
33             =head1 METHODS
34              
35             =over 3
36              
37             =item new [src => $obj]
38              
39             Creates an C object.
40              
41             Optional C parameter expects C object.
42              
43             my $pix = Image::Magick::PixelMosaic->new(src => $img);
44              
45             is equal to
46              
47             my $pix = Image::Magick::PixelMosaic->new;
48             $pix->src($img);
49              
50             =item src, src($obj)
51              
52             Get or set Image::Magick object.
53              
54             =item pixelize C => I, C => I
55              
56             Generates pixelized mosaic on specified geometry.
57              
58             C must be specified as geometry form I<'WxH+X+Y'>.
59              
60             C must be specified as one of 'WxH', [W,H] or W (height==width).
61              
62             All of W, H, X and Y must be non-negative integer.
63              
64             If geometry exceeds area of source image, it will be automatically cropped.
65              
66             When height/width of image are '20x30' and
67              
68             $pix->pixelize('20x20+1+5', [4,6])
69              
70             is called, efefctive pixelized area will be '16x24+1+5'.
71              
72             =back
73              
74             =head1 SEE ALSO
75              
76             L
77              
78             =head1 TODO
79              
80             accept width/heigh/x/y options.
81              
82             more pixel color decision algorithm (currently use average of pixel area)
83              
84             =head1 AUTHOR
85              
86             KATOU Akira (turugina) Eturugina@cpan.orgE
87              
88             =head1 COPYRIGHT AND LICENSE
89              
90             Copyright (C) 2008 by KATOU Akira (turugina)
91              
92             This library is free software; you can redistribute it and/or modify
93             it under the same terms as Perl itself, either Perl version 5.8.8 or,
94             at your option, any later version of Perl 5 you may have available.
95              
96             =cut
97              
98             sub new
99             {
100             my ($cls,%opt_) = @_;
101              
102             my $self = bless { }, $cls;
103             die $! if !$self;
104              
105             $self->src($opt_{src}) if exists $opt_{src};
106              
107             return $self;
108             }
109              
110             sub src
111             {
112             my ($self, $obj) = @_;
113              
114             if ( $obj ) {
115             if (!$obj->isa('Image::Magick')) {
116             die "specified object is not an Image::Magick";
117             }
118             $self->{src} = $obj;
119             }
120             return $self->{src};
121             }
122              
123             sub pixelize
124             {
125             my ($self, %opt) = @_;
126              
127             if (!$self->{src}) {
128             die q/source Image::Magick object must be set before calling pixelize()/;
129             }
130             my $img = $self->{src};
131              
132             my ($geo,$psize) = @opt{qw/geometry pixelsize/};
133              
134             if (!$geo) {
135             die q/geometry must be specified/;
136             }
137             if (!$psize) {
138             die q/pixel size must be specified/;
139             }
140              
141             $geo =~ /(\d+)x(\d+)\+(\d+)\+(\d+)/ or die q/geometry must be 'WxH+X+Y'/;
142             my ($w,$h,$xorig,$yorig) = ($1,$2,$3,$4);
143              
144             my ($pw,$ph) = do {
145             if ( $psize =~ /^(\d+)x(\d+)$/ ) {
146             ($1,$2);
147             }
148             elsif ( ref($psize) =~ /^ARRAY/ ) {
149             @$psize[0,1];
150             }
151             elsif ( int $psize == $psize ) {
152             ($psize,$psize);
153             }
154             else {
155             die q/pixelsize must be one of 'WxH', [W,H] or W/;
156             }
157             };
158              
159             my $imgw = $img->Get(q/width/);
160             my $imgh = $img->Get(q/height/);
161             my ($xe,$ye) = ($xorig+$w,$yorig+$h);
162              
163             # clip area
164             $xorig = _clip($xorig, 0, $imgw);
165             $yorig = _clip($yorig, 0, $imgh);
166             $xe = _clip($xe, 0, $imgw);
167             $ye = _clip($ye, 0, $imgh);
168              
169             $xe -= $pw;
170             $ye -= $ph;
171              
172             for ( my $x = $xorig; $x <= $xe; $x += $pw ) {
173             for ( my $y = $yorig; $y <= $ye; $y += $ph ) {
174              
175             my @px = $img->GetPixels(
176             x=>$x, y=>$y, width=>$pw, height=>$ph,
177             map=>q/RGB/, normalize=>q/true/ );
178             my $n = scalar(@px) / 3;
179             for my $i ( 1 .. $n-1 ) {
180             $px[0]+=$px[$i*3];
181             $px[1]+=$px[$i*3+1];
182             $px[2]+=$px[$i*3+2];
183             }
184             @px = map { int($_ * 255.0 / $n) } @px[0..2];
185              
186             my $color = sprintf(q/#%02x%02x%02x/, $px[0], $px[1], $px[2]);
187             for my $xx ( $x .. $x+$pw-1 ) {
188             for my $yy ( $y .. $y+$ph-1 ) {
189             $img->Set("pixel[$xx,$yy]" => $color);
190             }
191             }
192             }
193             }
194             $self;
195             }
196              
197             sub _clip
198             {
199             my ( $v, $min, $max ) = @_;
200              
201             return $min if $v < $min;
202             return $max if $v > $max;
203             return $v;
204             }
205              
206             1;
207