Fixes to i_map function and map method. Added a testcase for both.
[imager.git] / Imager.pm
CommitLineData
02d1d628
AMH
1package Imager;
2
3
4
5use strict;
6use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR $fontstate %OPCODES $I2P $FORMATGUESS);
7use IO::File;
8
9use Imager::Color;
10use Imager::Font;
11
12@EXPORT_OK = qw(
13 init
14 init_log
15 DSO_open
16 DSO_close
17 DSO_funclist
18 DSO_call
19
20 load_plugin
21 unload_plugin
22
23 i_list_formats
24 i_has_format
25
26 i_color_new
27 i_color_set
28 i_color_info
29
30 i_img_empty
31 i_img_empty_ch
32 i_img_exorcise
33 i_img_destroy
34
35 i_img_info
36
37 i_img_setmask
38 i_img_getmask
39
40 i_draw
41 i_line_aa
42 i_box
43 i_box_filled
44 i_arc
45
46 i_bezier_multi
47 i_poly_aa
48
49 i_copyto
50 i_rubthru
51 i_scaleaxis
52 i_scale_nn
53 i_haar
54 i_count_colors
55
56
57 i_gaussian
58 i_conv
59
f5991c03 60 i_convert
40eba1ea 61 i_map
f5991c03 62
02d1d628
AMH
63 i_img_diff
64
65 i_init_fonts
66 i_t1_new
67 i_t1_destroy
68 i_t1_set_aa
69 i_t1_cp
70 i_t1_text
71 i_t1_bbox
72
73
74 i_tt_set_aa
75 i_tt_cp
76 i_tt_text
77 i_tt_bbox
78
79 i_readjpeg
80 i_writejpeg
81
82 i_readjpeg_wiol
83 i_writejpeg_wiol
84
85 i_readtiff_wiol
86 i_writetiff_wiol
d2dfdcc9 87 i_writetiff_wiol_faxable
02d1d628
AMH
88
89 i_readpng
90 i_writepng
91
92 i_readgif
93 i_readgif_callback
94 i_writegif
95 i_writegifmc
96 i_writegif_gen
97 i_writegif_callback
98
99 i_readpnm_wiol
100 i_writeppm
101
102 i_readraw
103 i_writeraw
104
105 i_contrast
106 i_hardinvert
107 i_noise
108 i_bumpmap
109 i_postlevels
110 i_mosaic
111 i_watermark
112
113 malloc_state
114
115 list_formats
116
117 i_gifquant
118
119 newfont
120 newcolor
121 newcolour
122 NC
123 NF
124
125);
126
127
128
129@EXPORT=qw(
130 init_log
131 i_list_formats
132 i_has_format
133 malloc_state
134 i_color_new
135
136 i_img_empty
137 i_img_empty_ch
138 );
139
140%EXPORT_TAGS=
141 (handy => [qw(
142 newfont
143 newcolor
144 NF
145 NC
146 )],
147 all => [@EXPORT_OK],
148 default => [qw(
149 load_plugin
150 unload_plugin
151 )]);
152
153
154BEGIN {
155 require Exporter;
156 require DynaLoader;
157
158 $VERSION = '0.38pre9';
159 @ISA = qw(Exporter DynaLoader);
160 bootstrap Imager $VERSION;
161}
162
163BEGIN {
164 i_init_fonts(); # Initialize font engines
165 for(i_list_formats()) { $formats{$_}++; }
166
167 if ($formats{'t1'}) {
168 i_t1_set_aa(1);
169 }
170
171 if (!$formats{'t1'} and !$formats{'tt'}) {
172 $fontstate='no font support';
173 }
174
175 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
176
177 $DEBUG=0;
178
179 $filters{contrast}={
180 callseq => ['image','intensity'],
181 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
182 };
183
184 $filters{noise} ={
185 callseq => ['image', 'amount', 'subtype'],
186 defaults => { amount=>3,subtype=>0 },
187 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
188 };
189
190 $filters{hardinvert} ={
191 callseq => ['image'],
192 defaults => { },
193 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
194 };
195
196 $filters{autolevels} ={
197 callseq => ['image','lsat','usat','skew'],
198 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
199 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
200 };
201
202 $filters{turbnoise} ={
203 callseq => ['image'],
204 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
205 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
206 };
207
208 $filters{radnoise} ={
209 callseq => ['image'],
210 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
211 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
212 };
213
214 $filters{conv} ={
215 callseq => ['image', 'coef'],
216 defaults => { },
217 callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
218 };
219
220 $filters{gradgen} ={
221 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
222 defaults => { },
223 callsub => sub { my %hsh=@_; i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, $hsh{colors}, $hsh{dist}); }
224 };
225
226 $filters{nearest_color} ={
227 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
228 defaults => { },
229 callsub => sub { my %hsh=@_; i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, $hsh{colors}, $hsh{dist}); }
230 };
231
232 $FORMATGUESS=\&def_guess_type;
233}
234
235#
236# Non methods
237#
238
239# initlize Imager
240# NOTE: this might be moved to an import override later on
241
242#sub import {
243# my $pack = shift;
244# (look through @_ for special tags, process, and remove them);
245# use Data::Dumper;
246# print Dumper($pack);
247# print Dumper(@_);
248#}
249
250sub init {
251 my %parms=(loglevel=>1,@_);
252 if ($parms{'log'}) {
253 init_log($parms{'log'},$parms{'loglevel'});
254 }
255
256# if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
257# if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
258# i_init_fonts();
259# $fontstate='ok';
260# }
261}
262
263END {
264 if ($DEBUG) {
265 print "shutdown code\n";
266 # for(keys %instances) { $instances{$_}->DESTROY(); }
267 malloc_state(); # how do decide if this should be used? -- store something from the import
268 print "Imager exiting\n";
269 }
270}
271
272# Load a filter plugin
273
274sub load_plugin {
275 my ($filename)=@_;
276 my $i;
277 my ($DSO_handle,$str)=DSO_open($filename);
278 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
279 my %funcs=DSO_funclist($DSO_handle);
280 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
281 $i=0;
282 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
283
284 $DSOs{$filename}=[$DSO_handle,\%funcs];
285
286 for(keys %funcs) {
287 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
288 $DEBUG && print "eval string:\n",$evstr,"\n";
289 eval $evstr;
290 print $@ if $@;
291 }
292 return 1;
293}
294
295# Unload a plugin
296
297sub unload_plugin {
298 my ($filename)=@_;
299
300 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
301 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
302 for(keys %{$funcref}) {
303 delete $filters{$_};
304 $DEBUG && print "unloading: $_\n";
305 }
306 my $rc=DSO_close($DSO_handle);
307 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
308 return 1;
309}
310
64606cc7
TC
311# take the results of i_error() and make a message out of it
312sub _error_as_msg {
313 return join(": ", map $_->[0], i_errors());
314}
315
02d1d628
AMH
316
317#
318# Methods to be called on objects.
319#
320
321# Create a new Imager object takes very few parameters.
322# usually you call this method and then call open from
323# the resulting object
324
325sub new {
326 my $class = shift;
327 my $self ={};
328 my %hsh=@_;
329 bless $self,$class;
330 $self->{IMG}=undef; # Just to indicate what exists
331 $self->{ERRSTR}=undef; #
332 $self->{DEBUG}=$DEBUG;
333 $self->{DEBUG} && print "Initialized Imager\n";
334 if ($hsh{xsize} && $hsh{ysize}) { $self->img_set(%hsh); }
335 return $self;
336}
337
338
339# Copy an entire image with no changes
340# - if an image has magic the copy of it will not be magical
341
342sub copy {
343 my $self = shift;
344 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
345
346 my $newcopy=Imager->new();
347 $newcopy->{IMG}=i_img_new();
348 i_copy($newcopy->{IMG},$self->{IMG});
349 return $newcopy;
350}
351
352# Paste a region
353
354sub paste {
355 my $self = shift;
356 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
357 my %input=(left=>0, top=>0, @_);
358 unless($input{img}) {
359 $self->{ERRSTR}="no source image";
360 return;
361 }
362 $input{left}=0 if $input{left} <= 0;
363 $input{top}=0 if $input{top} <= 0;
364 my $src=$input{img};
365 my($r,$b)=i_img_info($src->{IMG});
366
367 i_copyto($self->{IMG}, $src->{IMG},
368 0,0, $r, $b, $input{left}, $input{top});
369 return $self; # What should go here??
370}
371
372# Crop an image - i.e. return a new image that is smaller
373
374sub crop {
375 my $self=shift;
376 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
377 my %hsh=(left=>0,right=>0,top=>0,bottom=>0,@_);
378
379 my ($w,$h,$l,$r,$b,$t)=($self->getwidth(),$self->getheight(),
380 @hsh{qw(left right bottom top)});
381 $l=0 if not defined $l;
382 $t=0 if not defined $t;
299a3866
AMH
383
384 $r||=$l+delete $hsh{'width'} if defined $l and exists $hsh{'width'};
385 $b||=$t+delete $hsh{'height'} if defined $t and exists $hsh{'height'};
386 $l||=$r-delete $hsh{'width'} if defined $r and exists $hsh{'width'};
387 $t||=$b-delete $hsh{'height'} if defined $b and exists $hsh{'height'};
388
02d1d628
AMH
389 $r=$self->getwidth if not defined $r;
390 $b=$self->getheight if not defined $b;
391
392 ($l,$r)=($r,$l) if $l>$r;
393 ($t,$b)=($b,$t) if $t>$b;
394
299a3866
AMH
395 if ($hsh{'width'}) {
396 $l=int(0.5+($w-$hsh{'width'})/2);
397 $r=$l+$hsh{'width'};
02d1d628
AMH
398 } else {
399 $hsh{'width'}=$r-$l;
400 }
299a3866
AMH
401 if ($hsh{'height'}) {
402 $b=int(0.5+($h-$hsh{'height'})/2);
403 $t=$h+$hsh{'height'};
02d1d628
AMH
404 } else {
405 $hsh{'height'}=$b-$t;
406 }
407
408# print "l=$l, r=$r, h=$hsh{'width'}\n";
409# print "t=$t, b=$b, w=$hsh{'height'}\n";
410
299a3866 411 my $dst=Imager->new(xsize=>$hsh{'width'}, ysize=>$hsh{'height'}, channels=>$self->getchannels());
02d1d628
AMH
412
413 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
414 return $dst;
415}
416
417# Sets an image to a certain size and channel number
418# if there was previously data in the image it is discarded
419
420sub img_set {
421 my $self=shift;
422
423 my %hsh=(xsize=>100,ysize=>100,channels=>3,@_);
424
425 if (defined($self->{IMG})) {
426 i_img_destroy($self->{IMG});
427 undef($self->{IMG});
428 }
429
430 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'},$hsh{'ysize'},$hsh{'channels'});
431}
432
433# Read an image from file
434
435sub read {
436 my $self = shift;
437 my %input=@_;
438 my ($fh, $fd, $IO);
439
440 if (defined($self->{IMG})) {
441 i_img_destroy($self->{IMG});
442 undef($self->{IMG});
443 }
444
445 if (!$input{fd} and !$input{file} and !$input{data}) { $self->{ERRSTR}='no file, fd or data parameter'; return undef; }
446 if ($input{file}) {
447 $fh = new IO::File($input{file},"r");
448 if (!defined $fh) { $self->{ERRSTR}='Could not open file'; return undef; }
449 binmode($fh);
450 $fd = $fh->fileno();
451 }
452 if ($input{fd}) { $fd=$input{fd} };
453
454 # FIXME: Find the format here if not specified
455 # yes the code isn't here yet - next week maybe?
456
457 if (!$input{type} and $input{file}) { $input{type}=$FORMATGUESS->($input{file}); }
458 if (!$formats{$input{type}}) { $self->{ERRSTR}='format not supported'; return undef; }
459
460 my %iolready=(jpeg=>1, tiff=>1, pnm=>1);
461
462 if ($iolready{$input{type}}) {
463 # Setup data source
464 $IO = io_new_fd($fd); # sort of simple for now eh?
465
466 if ( $input{type} eq 'jpeg' ) {
467 ($self->{IMG},$self->{IPTCRAW})=i_readjpeg_wiol( $IO );
468 if ( !defined($self->{IMG}) ) { $self->{ERRSTR}='unable to read jpeg image'; return undef; }
469 $self->{DEBUG} && print "loading a jpeg file\n";
470 return $self;
471 }
472
473 if ( $input{type} eq 'tiff' ) {
474 $self->{IMG}=i_readtiff_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
475 if ( !defined($self->{IMG}) ) { $self->{ERRSTR}='unable to read tiff image'; return undef; }
476 $self->{DEBUG} && print "loading a tiff file\n";
477 return $self;
478 }
479
480 if ( $input{type} eq 'pnm' ) {
481 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
64606cc7 482 if ( !defined($self->{IMG}) ) { $self->{ERRSTR}='unable to read pnm image: '._error_as_msg(); return undef; }
02d1d628
AMH
483 $self->{DEBUG} && print "loading a pnm file\n";
484 return $self;
485 }
486
487 } else {
488
489 # Old code for reference while changing the new stuff
490
491
492 if (!$input{type} and $input{file}) { $input{type}=$FORMATGUESS->($input{file}); }
493 if (!$input{type}) { $self->{ERRSTR}='type parameter missing and not possible to guess from extension'; return undef; }
494
495 if (!$formats{$input{type}}) { $self->{ERRSTR}='format not supported'; return undef; }
496
497 if ($input{file}) {
498 $fh = new IO::File($input{file},"r");
499 if (!defined $fh) { $self->{ERRSTR}='Could not open file'; return undef; }
500 binmode($fh);
501 $fd = $fh->fileno();
502 }
503 if ($input{fd}) { $fd=$input{fd} };
504
505 if ( $input{type} eq 'gif' ) {
e72d3bb1 506 my $colors;
a59ffd27
TC
507 if ($input{colors} && !ref($input{colors})) {
508 # must be a reference to a scalar that accepts the colour map
509 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
510 return undef;
511 }
512 if (exists $input{data}) {
513 if ($input{colors}) {
e72d3bb1 514 ($self->{IMG}, $colors) = i_readgif_scalar($input{data});
a59ffd27
TC
515 }
516 else {
517 $self->{IMG}=i_readgif_scalar($input{data});
518 }
519 }
520 else {
521 if ($input{colors}) {
e72d3bb1 522 ($self->{IMG}, $colors) = i_readgif( $fd );
a59ffd27
TC
523 }
524 else {
525 $self->{IMG} = i_readgif( $fd )
526 }
527 }
e72d3bb1
TC
528 if ($colors) {
529 # we may or may not change i_readgif to return blessed objects...
530 ${$input{colors}} = [ map { NC(@$_) } @$colors ];
531 }
a59ffd27
TC
532 if ( !defined($self->{IMG}) ) {
533 $self->{ERRSTR}= 'reading GIF:'._error_as_msg(); return undef;
534 }
02d1d628
AMH
535 $self->{DEBUG} && print "loading a gif file\n";
536 } elsif ( $input{type} eq 'jpeg' ) {
537 if (exists $input{data}) { ($self->{IMG},$self->{IPTCRAW})=i_readjpeg_scalar($input{data}); }
538 else { ($self->{IMG},$self->{IPTCRAW})=i_readjpeg( $fd ); }
539 if ( !defined($self->{IMG}) ) { $self->{ERRSTR}='unable to read jpeg image'; return undef; }
540 $self->{DEBUG} && print "loading a jpeg file\n";
541 } elsif ( $input{type} eq 'png' ) {
542 if (exists $input{data}) { $self->{IMG}=i_readpng_scalar($input{data}); }
543 else { $self->{IMG}=i_readpng( $fd ); }
544 if ( !defined($self->{IMG}) ) { $self->{ERRSTR}='unable to read png image'; return undef; }
545 $self->{DEBUG} && print "loading a png file\n";
546 } elsif ( $input{type} eq 'raw' ) {
547 my %params=(datachannels=>3,storechannels=>3,interleave=>1);
548 for(keys(%input)) { $params{$_}=$input{$_}; }
549
550 if ( !($params{xsize} && $params{ysize}) ) { $self->{ERRSTR}='missing xsize or ysize parameter for raw'; return undef; }
551 $self->{IMG}=i_readraw( $fd, $params{xsize}, $params{ysize},
552 $params{datachannels}, $params{storechannels}, $params{interleave});
553 if ( !defined($self->{IMG}) ) { $self->{ERRSTR}='unable to read raw image'; return undef; }
554 $self->{DEBUG} && print "loading a raw file\n";
555 }
556 return $self;
557 }
558}
559
560
561# Write an image to file
562
563sub write {
564 my $self = shift;
4c2d6970
TC
565 my %input=(jpegquality=>75, gifquant=>'mc', lmdither=>6.0, lmfixed=>[],
566 fax_fine=>1, @_);
02d1d628
AMH
567 my ($fh, $rc, $fd, $IO);
568
569 my %iolready=( tiff=>1 ); # this will be SO MUCH BETTER once they are all in there
570
571 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
572
573 if (!$input{file} and !$input{'fd'} and !$input{'data'}) { $self->{ERRSTR}='file/fd/data parameter missing'; return undef; }
4c2d6970 574 if (!$input{type} and $input{file}) { $input{type}=$FORMATGUESS->($input{file}); }
02d1d628
AMH
575 if (!$input{type}) { $self->{ERRSTR}='type parameter missing and not possible to guess from extension'; return undef; }
576
577 if (!$formats{$input{type}}) { $self->{ERRSTR}='format not supported'; return undef; }
578
579 if (exists $input{'fd'}) {
580 $fd=$input{'fd'};
581 } elsif (exists $input{'data'}) {
582 $IO = Imager::io_new_bufchain();
583 } else {
584 $fh = new IO::File($input{file},"w+");
585 if (!defined $fh) { $self->{ERRSTR}='Could not open file'; return undef; }
586 binmode($fh);
587 $fd = $fh->fileno();
588 }
589
590
591
592 if ($iolready{$input{type}}) {
4c2d6970 593 if (defined $fd) {
02d1d628
AMH
594 $IO = io_new_fd($fd);
595 }
596
597 if ($input{type} eq 'tiff') {
4c2d6970
TC
598 if (defined $input{class} && $input{class} eq 'fax') {
599 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
d2dfdcc9
TC
600 $self->{ERRSTR}='Could not write to buffer';
601 return undef;
602 }
603 }
604 else {
930c67c8
AMH
605 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
606 $self->{ERRSTR}='Could not write to buffer';
607 return undef;
d2dfdcc9
TC
608 }
609 }
02d1d628
AMH
610 }
611
930c67c8
AMH
612 if (exists $input{'data'}) {
613 my $data = io_slurp($IO);
614 if (!$data) {
615 $self->{ERRSTR}='Could not slurp from buffer';
616 return undef;
617 }
618 ${$input{data}} = $data;
619 }
02d1d628
AMH
620 return $self;
621 } else {
622
623 if ( $input{type} eq 'gif' ) {
624 if (not $input{gifplanes}) {
625 my $gp;
626 my $count=i_count_colors($self->{IMG}, 256);
627 $gp=8 if $count == -1;
628 $gp=1 if not $gp and $count <= 2;
629 $gp=2 if not $gp and $count <= 4;
630 $gp=3 if not $gp and $count <= 8;
631 $gp=4 if not $gp and $count <= 16;
632 $gp=5 if not $gp and $count <= 32;
633 $gp=6 if not $gp and $count <= 64;
634 $gp=7 if not $gp and $count <= 128;
635 $input{gifplanes} = $gp || 8;
636 }
637
638 if ($input{gifplanes}>8) {
639 $input{gifplanes}=8;
640 }
641 if ($input{gifquant} eq 'gen' || $input{callback}) {
642
643
644 if ($input{gifquant} eq 'lm') {
645
646 $input{make_colors} = 'addi';
647 $input{translate} = 'perturb';
648 $input{perturb} = $input{lmdither};
649 } elsif ($input{gifquant} eq 'gen') {
650 # just pass options through
651 } else {
652 $input{make_colors} = 'webmap'; # ignored
653 $input{translate} = 'giflib';
654 }
655
656 if ($input{callback}) {
657 defined $input{maxbuffer} or $input{maxbuffer} = -1;
658 $rc = i_writegif_callback($input{callback}, $input{maxbuffer},
659 \%input, $self->{IMG});
660 } else {
661 $rc = i_writegif_gen($fd, \%input, $self->{IMG});
662 }
663
664
665
666 } elsif ($input{gifquant} eq 'lm') {
667 $rc=i_writegif($self->{IMG},$fd,$input{gifplanes},$input{lmdither},$input{lmfixed});
668 } else {
669 $rc=i_writegifmc($self->{IMG},$fd,$input{gifplanes});
670 }
671 if ( !defined($rc) ) {
3827fae0 672 $self->{ERRSTR} = "Writing GIF file: "._error_as_msg(); return undef;
02d1d628
AMH
673 }
674 $self->{DEBUG} && print "writing a gif file\n";
675
676 } elsif ( $input{type} eq 'jpeg' ) {
677 $rc=i_writejpeg($self->{IMG},$fd,$input{jpegquality});
678 if ( !defined($rc) ) {
679 $self->{ERRSTR}='unable to write jpeg image'; return undef;
680 }
681 $self->{DEBUG} && print "writing a jpeg file\n";
682 } elsif ( $input{type} eq 'png' ) {
683 $rc=i_writepng($self->{IMG},$fd);
684 if ( !defined($rc) ) {
685 $self->{ERRSTR}='unable to write png image'; return undef;
686 }
687 $self->{DEBUG} && print "writing a png file\n";
688 } elsif ( $input{type} eq 'pnm' ) {
689 $rc=i_writeppm($self->{IMG},$fd);
690 if ( !defined($rc) ) {
691 $self->{ERRSTR}='unable to write pnm image'; return undef;
692 }
693 $self->{DEBUG} && print "writing a pnm file\n";
694 } elsif ( $input{type} eq 'raw' ) {
695 $rc=i_writeraw($self->{IMG},$fd);
696 if ( !defined($rc) ) {
697 $self->{ERRSTR}='unable to write raw image'; return undef;
698 }
699 $self->{DEBUG} && print "writing a raw file\n";
02d1d628
AMH
700 }
701
702 }
703 return $self;
704}
705
706sub write_multi {
707 my ($class, $opts, @images) = @_;
708
709 if ($opts->{type} eq 'gif') {
ed88b092
TC
710 my $gif_delays = $opts->{gif_delays};
711 local $opts->{gif_delays} = $gif_delays;
712 unless (ref $opts->{gif_delays}) {
713 # assume the caller wants the same delay for each frame
714 $opts->{gif_delays} = [ ($gif_delays) x @images ];
715 }
02d1d628
AMH
716 # translate to ImgRaw
717 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
718 $ERRSTR = "Usage: Imager->write_multi({ options }, @images)";
719 return 0;
720 }
721 my @work = map $_->{IMG}, @images;
722 if ($opts->{callback}) {
723 # Note: you may need to fix giflib for this one to work
724 my $maxbuffer = $opts->{maxbuffer};
725 defined $maxbuffer or $maxbuffer = -1; # max by default
726 return i_writegif_callback($opts->{callback}, $maxbuffer,
727 $opts, @work);
728 }
729 if ($opts->{fd}) {
730 return i_writegif_gen($opts->{fd}, $opts, @work);
731 }
732 else {
733 my $fh = IO::File->new($opts->{file}, "w+");
734 unless ($fh) {
735 $ERRSTR = "Error creating $opts->{file}: $!";
736 return 0;
737 }
738 binmode($fh);
739 return i_writegif_gen(fileno($fh), $opts, @work);
740 }
741 }
742 else {
743 $ERRSTR = "Sorry, write_multi doesn't support $opts->{type} yet";
744 return 0;
745 }
746}
747
748# Destroy an Imager object
749
750sub DESTROY {
751 my $self=shift;
752 # delete $instances{$self};
753 if (defined($self->{IMG})) {
754 i_img_destroy($self->{IMG});
755 undef($self->{IMG});
756 } else {
757# print "Destroy Called on an empty image!\n"; # why did I put this here??
758 }
759}
760
761# Perform an inplace filter of an image
762# that is the image will be overwritten with the data
763
764sub filter {
765 my $self=shift;
766 my %input=@_;
767 my %hsh;
768 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
769
770 if (!$input{type}) { $self->{ERRSTR}='type parameter missing'; return undef; }
771
772 if ( (grep { $_ eq $input{type} } keys %filters) != 1) {
773 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
774 }
775
776 if (defined($filters{$input{type}}{defaults})) {
777 %hsh=('image',$self->{IMG},%{$filters{$input{type}}{defaults}},%input);
778 } else {
779 %hsh=('image',$self->{IMG},%input);
780 }
781
782 my @cs=@{$filters{$input{type}}{callseq}};
783
784 for(@cs) {
785 if (!defined($hsh{$_})) {
786 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{type}; return undef;
787 }
788 }
789
790 &{$filters{$input{type}}{callsub}}(%hsh);
791
792 my @b=keys %hsh;
793
794 $self->{DEBUG} && print "callseq is: @cs\n";
795 $self->{DEBUG} && print "matching callseq is: @b\n";
796
797 return $self;
798}
799
800# Scale an image to requested size and return the scaled version
801
802sub scale {
803 my $self=shift;
804 my %opts=(scalefactor=>0.5,type=>'max',qtype=>'normal',@_);
805 my $img = Imager->new();
806 my $tmp = Imager->new();
807
808 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
809
810 if ($opts{xpixels} and $opts{ypixels} and $opts{type}) {
811 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
812 if ($opts{type} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
813 if ($opts{type} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
814 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
815 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
816
817 if ($opts{qtype} eq 'normal') {
818 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
819 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
820 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
821 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
822 return $img;
823 }
824 if ($opts{'qtype'} eq 'preview') {
825 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
826 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
827 return $img;
828 }
829 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
830}
831
832# Scales only along the X axis
833
834sub scaleX {
835 my $self=shift;
836 my %opts=(scalefactor=>0.5,@_);
837
838 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
839
840 my $img = Imager->new();
841
842 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
843
844 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
845 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
846
847 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
848 return $img;
849}
850
851# Scales only along the Y axis
852
853sub scaleY {
854 my $self=shift;
855 my %opts=(scalefactor=>0.5,@_);
856
857 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
858
859 my $img = Imager->new();
860
861 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
862
863 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
864 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
865
866 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
867 return $img;
868}
869
870
871# Transform returns a spatial transformation of the input image
872# this moves pixels to a new location in the returned image.
873# NOTE - should make a utility function to check transforms for
874# stack overruns
875
876sub transform {
877 my $self=shift;
878 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
879 my %opts=@_;
880 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
881
882# print Dumper(\%opts);
883# xopcopdes
884
885 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
886 if (!$I2P) {
887 eval ("use Affix::Infix2Postfix;");
888 print $@;
889 if ( $@ ) {
890 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
891 return undef;
892 }
893 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
894 {op=>'-',trans=>'Sub'},
895 {op=>'*',trans=>'Mult'},
896 {op=>'/',trans=>'Div'},
897 {op=>'-',type=>'unary',trans=>'u-'},
898 {op=>'**'},
899 {op=>'func',type=>'unary'}],
900 'grouping'=>[qw( \( \) )],
901 'func'=>[qw( sin cos )],
902 'vars'=>[qw( x y )]
903 );
904 }
905
906 @xt=$I2P->translate($opts{'xexpr'});
907 @yt=$I2P->translate($opts{'yexpr'});
908
909 $numre=$I2P->{'numre'};
910 @pt=(0,0);
911
912 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
913 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
914 @{$opts{'parm'}}=@pt;
915 }
916
917# print Dumper(\%opts);
918
919 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
920 $self->{ERRSTR}='transform: no xopcodes given.';
921 return undef;
922 }
923
924 @op=@{$opts{'xopcodes'}};
925 for $iop (@op) {
926 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
927 $self->{ERRSTR}="transform: illegal opcode '$_'.";
928 return undef;
929 }
930 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
931 }
932
933
934# yopcopdes
935
936 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
937 $self->{ERRSTR}='transform: no yopcodes given.';
938 return undef;
939 }
940
941 @op=@{$opts{'yopcodes'}};
942 for $iop (@op) {
943 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
944 $self->{ERRSTR}="transform: illegal opcode '$_'.";
945 return undef;
946 }
947 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
948 }
949
950#parameters
951
952 if ( !exists $opts{'parm'}) {
953 $self->{ERRSTR}='transform: no parameter arg given.';
954 return undef;
955 }
956
957# print Dumper(\@ropx);
958# print Dumper(\@ropy);
959# print Dumper(\@ropy);
960
961 my $img = Imager->new();
962 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
963 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
964 return $img;
965}
966
967
968{
969 my $got_expr;
970 sub transform2 {
971 my ($opts, @imgs) = @_;
972
973 if (!$got_expr) {
974 # this is fairly big, delay loading it
975 eval "use Imager::Expr";
976 die $@ if $@;
977 ++$got_expr;
978 }
979
980 $opts->{variables} = [ qw(x y) ];
981 my ($width, $height) = @{$opts}{qw(width height)};
982 if (@imgs) {
983 $width ||= $imgs[0]->getwidth();
984 $height ||= $imgs[0]->getheight();
985 my $img_num = 1;
986 for my $img (@imgs) {
987 $opts->{constants}{"w$img_num"} = $img->getwidth();
988 $opts->{constants}{"h$img_num"} = $img->getheight();
989 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
990 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
991 ++$img_num;
992 }
993 }
994 if ($width) {
995 $opts->{constants}{w} = $width;
996 $opts->{constants}{cx} = $width/2;
997 }
998 else {
999 $Imager::ERRSTR = "No width supplied";
1000 return;
1001 }
1002 if ($height) {
1003 $opts->{constants}{h} = $height;
1004 $opts->{constants}{cy} = $height/2;
1005 }
1006 else {
1007 $Imager::ERRSTR = "No height supplied";
1008 return;
1009 }
1010 my $code = Imager::Expr->new($opts);
1011 if (!$code) {
1012 $Imager::ERRSTR = Imager::Expr::error();
1013 return;
1014 }
1015
1016 my $img = Imager->new();
1017 $img->{IMG} = i_transform2($opts->{width}, $opts->{height}, $code->code(),
1018 $code->nregs(), $code->cregs(),
1019 [ map { $_->{IMG} } @imgs ]);
1020 if (!defined $img->{IMG}) {
1021 $Imager::ERRSTR = "transform2 failed";
1022 return;
1023 }
1024
1025 return $img;
1026 }
1027}
1028
1029
1030
1031
1032
1033
1034
1035
1036sub rubthrough {
1037 my $self=shift;
1038 my %opts=(tx=>0,ty=>0,@_);
1039
1040 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1041 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1042
1043 i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx},$opts{ty});
1044 return $self;
1045}
1046
1047
142c26ff
AMH
1048sub flip {
1049 my $self = shift;
1050 my %opts = @_;
9191e525 1051 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
142c26ff
AMH
1052 my $dir;
1053 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
1054 $dir = $xlate{$opts{'dir'}};
1055 return $self if i_flipxy($self->{IMG}, $dir);
1056 return ();
1057}
1058
1059
02d1d628
AMH
1060
1061# These two are supported for legacy code only
1062
1063sub i_color_new {
1064 return Imager::Color->new($_[0], $_[1], $_[2], $_[3]);
1065}
1066
1067sub i_color_set {
1068 return Imager::Color::set($_[0], $_[1], $_[2], $_[3], $_[4]);
1069}
1070
1071
1072
1073# Draws a box between the specified corner points.
1074
1075sub box {
1076 my $self=shift;
1077 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1078 my $dflcl=i_color_new(255,255,255,255);
1079 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
1080
1081 if (exists $opts{'box'}) {
1082 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
1083 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
1084 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
1085 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
1086 }
1087
1088 if ($opts{filled}) { i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},$opts{color}); }
1089 else { i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},$opts{color}); }
1090 return $self;
1091}
1092
1093# Draws an arc - this routine SUCKS and is buggy - it sometimes doesn't work when the arc is a convex polygon
1094
1095sub arc {
1096 my $self=shift;
1097 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1098 my $dflcl=i_color_new(255,255,255,255);
1099 my %opts=(color=>$dflcl,
1100 'r'=>min($self->getwidth(),$self->getheight())/3,
1101 'x'=>$self->getwidth()/2,
1102 'y'=>$self->getheight()/2,
1103 'd1'=>0, 'd2'=>361, @_);
1104 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},$opts{'d2'},$opts{'color'});
1105 return $self;
1106}
1107
1108# Draws a line from one point to (but not including) the destination point
1109
1110sub line {
1111 my $self=shift;
1112 my $dflcl=i_color_new(0,0,0,0);
1113 my %opts=(color=>$dflcl,@_);
1114 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1115
1116 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
1117 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
1118
1119 if ($opts{antialias}) {
1120 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2}, $opts{color});
1121 } else {
1122 i_draw($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2}, $opts{color});
1123 }
1124 return $self;
1125}
1126
1127# Draws a line between an ordered set of points - It more or less just transforms this
1128# into a list of lines.
1129
1130sub polyline {
1131 my $self=shift;
1132 my ($pt,$ls,@points);
1133 my $dflcl=i_color_new(0,0,0,0);
1134 my %opts=(color=>$dflcl,@_);
1135
1136 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1137
1138 if (exists($opts{points})) { @points=@{$opts{points}}; }
1139 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
1140 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
1141 }
1142
1143# print Dumper(\@points);
1144
1145 if ($opts{antialias}) {
1146 for $pt(@points) {
1147 if (defined($ls)) { i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$opts{color}); }
1148 $ls=$pt;
1149 }
1150 } else {
1151 for $pt(@points) {
1152 if (defined($ls)) { i_draw($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$opts{color}); }
1153 $ls=$pt;
1154 }
1155 }
1156 return $self;
1157}
1158
1159# this the multipoint bezier curve
1160# this is here more for testing that actual usage since
1161# this is not a good algorithm. Usually the curve would be
1162# broken into smaller segments and each done individually.
1163
1164sub polybezier {
1165 my $self=shift;
1166 my ($pt,$ls,@points);
1167 my $dflcl=i_color_new(0,0,0,0);
1168 my %opts=(color=>$dflcl,@_);
1169
1170 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1171
1172 if (exists $opts{points}) {
1173 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
1174 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
1175 }
1176
1177 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
1178 $self->{ERRSTR}='Missing or invalid points.';
1179 return;
1180 }
1181
1182 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$opts{'color'});
1183 return $self;
1184}
1185
f5991c03
TC
1186# make an identity matrix of the given size
1187sub _identity {
1188 my ($size) = @_;
1189
1190 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
1191 for my $c (0 .. ($size-1)) {
1192 $matrix->[$c][$c] = 1;
1193 }
1194 return $matrix;
1195}
1196
1197# general function to convert an image
1198sub convert {
1199 my ($self, %opts) = @_;
1200 my $matrix;
1201
1202 # the user can either specify a matrix or preset
1203 # the matrix overrides the preset
1204 if (!exists($opts{matrix})) {
1205 unless (exists($opts{preset})) {
1206 $self->{ERRSTR} = "convert() needs a matrix or preset";
1207 return;
1208 }
1209 else {
1210 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
1211 # convert to greyscale, keeping the alpha channel if any
1212 if ($self->getchannels == 3) {
1213 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
1214 }
1215 elsif ($self->getchannels == 4) {
1216 # preserve the alpha channel
1217 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
1218 [ 0, 0, 0, 1 ] ];
1219 }
1220 else {
1221 # an identity
1222 $matrix = _identity($self->getchannels);
1223 }
1224 }
1225 elsif ($opts{preset} eq 'noalpha') {
1226 # strip the alpha channel
1227 if ($self->getchannels == 2 or $self->getchannels == 4) {
1228 $matrix = _identity($self->getchannels);
1229 pop(@$matrix); # lose the alpha entry
1230 }
1231 else {
1232 $matrix = _identity($self->getchannels);
1233 }
1234 }
1235 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
1236 # extract channel 0
1237 $matrix = [ [ 1 ] ];
1238 }
1239 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
1240 $matrix = [ [ 0, 1 ] ];
1241 }
1242 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
1243 $matrix = [ [ 0, 0, 1 ] ];
1244 }
1245 elsif ($opts{preset} eq 'alpha') {
1246 if ($self->getchannels == 2 or $self->getchannels == 4) {
1247 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
1248 }
1249 else {
1250 # the alpha is just 1 <shrug>
1251 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
1252 }
1253 }
1254 elsif ($opts{preset} eq 'rgb') {
1255 if ($self->getchannels == 1) {
1256 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
1257 }
1258 elsif ($self->getchannels == 2) {
1259 # preserve the alpha channel
1260 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
1261 }
1262 else {
1263 $matrix = _identity($self->getchannels);
1264 }
1265 }
1266 elsif ($opts{preset} eq 'addalpha') {
1267 if ($self->getchannels == 1) {
1268 $matrix = _identity(2);
1269 }
1270 elsif ($self->getchannels == 3) {
1271 $matrix = _identity(4);
1272 }
1273 else {
1274 $matrix = _identity($self->getchannels);
1275 }
1276 }
1277 else {
1278 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
1279 return undef;
1280 }
1281 }
1282 }
1283 else {
1284 $matrix = $opts{matrix};
1285 }
1286
1287 my $new = Imager->new();
1288 $new->{IMG} = i_img_new();
1289 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
1290 # most likely a bad matrix
1291 $self->{ERRSTR} = _error_as_msg();
1292 return undef;
1293 }
1294 return $new;
1295}
40eba1ea
AMH
1296
1297
1298
1299
1300
1301# general function to map an image through lookup tables
1302sub map {
1303 my ($self, %opts) = @_;
1304 my @chlist = qw( r g b a );
1305
1306 if (!exists($opts{'maps'})) {
1307 # make maps from channel maps
1308 my $chnum;
1309 for $chnum (0..$#chlist) {
1310 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]} if exists $opts{$chlist[$chnum]};
1311 }
1312 }
1313 if ($opts{'maps'} and $self->{IMG}) {
1314 i_map($self->{IMG}, $opts{'maps'} );
1315 }
1316 return $self;
1317}
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
f5991c03 1344
02d1d628
AMH
1345
1346# destructive border - image is shrunk by one pixel all around
1347
1348sub border {
1349 my ($self,%opts)=@_;
1350 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
1351 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
1352}
1353
1354
1355# Get the width of an image
1356
1357sub getwidth {
1358 my $self = shift;
1359 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
1360 return (i_img_info($self->{IMG}))[0];
1361}
1362
1363# Get the height of an image
1364
1365sub getheight {
1366 my $self = shift;
1367 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
1368 return (i_img_info($self->{IMG}))[1];
1369}
1370
1371# Get number of channels in an image
1372
1373sub getchannels {
1374 my $self = shift;
1375 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
1376 return i_img_getchannels($self->{IMG});
1377}
1378
1379# Get channel mask
1380
1381sub getmask {
1382 my $self = shift;
1383 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
1384 return i_img_getmask($self->{IMG});
1385}
1386
1387# Set channel mask
1388
1389sub setmask {
1390 my $self = shift;
1391 my %opts = @_;
1392 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
1393 i_img_setmask( $self->{IMG} , $opts{mask} );
1394}
1395
1396# Get number of colors in an image
1397
1398sub getcolorcount {
1399 my $self=shift;
1400 my %opts=(maxcolors=>2**30,@_);
1401 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
1402 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
1403 return ($rc==-1? undef : $rc);
1404}
1405
1406# draw string to an image
1407
1408sub string {
1409 my $self = shift;
1410 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1411
1412 my %input=('x'=>0, 'y'=>0, @_);
1413 $input{string}||=$input{text};
1414
1415 unless(exists $input{string}) {
1416 $self->{ERRSTR}="missing required parameter 'string'";
1417 return;
1418 }
1419
1420 unless($input{font}) {
1421 $self->{ERRSTR}="missing required parameter 'font'";
1422 return;
1423 }
1424
1425 my $aa=1;
1426 my $font=$input{'font'};
1427 my $align=$font->{'align'} unless exists $input{'align'};
1428 my $color=$input{'color'} || $font->{'color'};
1429 my $size=$input{'size'} || $font->{'size'};
1430
1431 if (!defined($size)) { $self->{ERRSTR}='No size parameter and no default in font'; return undef; }
1432
1433 $aa=$font->{'aa'} if exists $font->{'aa'};
1434 $aa=$input{'aa'} if exists $input{'aa'};
1435
1436
1437
1438# unless($font->can('text')) {
1439# $self->{ERRSTR}="font is unable to do what we need";
1440# return;
1441# }
1442
1443# use Data::Dumper;
1444# warn Dumper($font);
1445
1446# print "Channel=".$input{'channel'}."\n";
1447
1448 if ( $font->{'type'} eq 't1' ) {
1449 if ( exists $input{'channel'} ) {
1450 Imager::Font::t1_set_aa_level($aa);
1451 i_t1_cp($self->{IMG},$input{'x'},$input{'y'},
1452 $input{'channel'},$font->{'id'},$size,
1453 $input{'string'},length($input{'string'}),1);
1454 } else {
1455 Imager::Font::t1_set_aa_level($aa);
1456 i_t1_text($self->{IMG},$input{'x'},$input{'y'},
1457 $color,$font->{'id'},$size,
1458 $input{'string'},length($input{'string'}),1);
1459 }
1460 }
1461
1462 if ( $font->{'type'} eq 'tt' ) {
1463 if ( exists $input{'channel'} ) {
1464 i_tt_cp($font->{'id'},$self->{IMG},$input{'x'},$input{'y'},$input{'channel'},
1465 $size,$input{'string'},length($input{'string'}),$aa);
1466 } else {
1467 i_tt_text($font->{'id'},$self->{IMG},$input{'x'},$input{'y'},$color,$size,
1468 $input{'string'},length($input{'string'}),$aa);
1469 }
1470 }
1471
1472 return $self;
1473}
1474
1475
1476
1477
1478
1479# Shortcuts that can be exported
1480
1481sub newcolor { Imager::Color->new(@_); }
1482sub newfont { Imager::Font->new(@_); }
1483
1484*NC=*newcolour=*newcolor;
1485*NF=*newfont;
1486
1487*open=\&read;
1488*circle=\&arc;
1489
1490
1491#### Utility routines
1492
1493sub errstr { $_[0]->{ERRSTR} }
1494
1495
1496
1497
1498
1499
1500# Default guess for the type of an image from extension
1501
1502sub def_guess_type {
1503 my $name=lc(shift);
1504 my $ext;
1505 $ext=($name =~ m/\.([^\.]+)$/)[0];
1506 return 'tiff' if ($ext =~ m/^tiff?$/);
1507 return 'jpeg' if ($ext =~ m/^jpe?g$/);
1508 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
1509 return 'png' if ($ext eq "png");
1510 return 'gif' if ($ext eq "gif");
1511 return ();
1512}
1513
1514# get the minimum of a list
1515
1516sub min {
1517 my $mx=shift;
1518 for(@_) { if ($_<$mx) { $mx=$_; }}
1519 return $mx;
1520}
1521
1522# get the maximum of a list
1523
1524sub max {
1525 my $mx=shift;
1526 for(@_) { if ($_>$mx) { $mx=$_; }}
1527 return $mx;
1528}
1529
1530# string stuff for iptc headers
1531
1532sub clean {
1533 my($str)=$_[0];
1534 $str = substr($str,3);
1535 $str =~ s/[\n\r]//g;
1536 $str =~ s/\s+/ /g;
1537 $str =~ s/^\s//;
1538 $str =~ s/\s$//;
1539 return $str;
1540}
1541
1542# A little hack to parse iptc headers.
1543
1544sub parseiptc {
1545 my $self=shift;
1546 my(@sar,$item,@ar);
1547 my($caption,$photogr,$headln,$credit);
1548
1549 my $str=$self->{IPTCRAW};
1550
1551 #print $str;
1552
1553 @ar=split(/8BIM/,$str);
1554
1555 my $i=0;
1556 foreach (@ar) {
1557 if (/^\004\004/) {
1558 @sar=split(/\034\002/);
1559 foreach $item (@sar) {
1560 if ($item =~ m/^x/) {
1561 $caption=&clean($item);
1562 $i++;
1563 }
1564 if ($item =~ m/^P/) {
1565 $photogr=&clean($item);
1566 $i++;
1567 }
1568 if ($item =~ m/^i/) {
1569 $headln=&clean($item);
1570 $i++;
1571 }
1572 if ($item =~ m/^n/) {
1573 $credit=&clean($item);
1574 $i++;
1575 }
1576 }
1577 }
1578 }
1579 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
1580}
1581
1582
1583
1584
1585
1586
1587# Autoload methods go after =cut, and are processed by the autosplit program.
1588
15891;
1590__END__
1591# Below is the stub of documentation for your module. You better edit it!
1592
1593=head1 NAME
1594
1595Imager - Perl extension for Generating 24 bit Images
1596
1597=head1 SYNOPSIS
1598
1599 use Imager qw(init);
1600
1601 init();
1602 $img = Imager->new();
1603 $img->open(file=>'image.ppm',type=>'pnm')
1604 || print "failed: ",$img->{ERRSTR},"\n";
1605 $scaled=$img->scale(xpixels=>400,ypixels=>400);
1606 $scaled->write(file=>'sc_image.ppm',type=>'pnm')
1607 || print "failed: ",$scaled->{ERRSTR},"\n";
1608
1609=head1 DESCRIPTION
1610
1611Imager is a module for creating and altering images - It is not meant
1612as a replacement or a competitor to ImageMagick or GD. Both are
1613excellent packages and well supported.
1614
1615=head2 API
1616
1617Almost all functions take the parameters in the hash fashion.
1618Example:
1619
1620 $img->open(file=>'lena.png',type=>'png');
1621
1622or just:
1623
1624 $img->open(file=>'lena.png');
1625
1626=head2 Basic concept
1627
1628An Image object is created with C<$img = Imager-E<gt>new()> Should
1629this fail for some reason an explanation can be found in
1630C<$Imager::ERRSTR> usually error messages are stored in
1631C<$img-E<gt>{ERRSTR}>, but since no object is created this is the only
1632way to give back errors. C<$Imager::ERRSTR> is also used to report
1633all errors not directly associated with an image object. Examples:
1634
1635 $img=Imager->new(); # This is an empty image (size is 0 by 0)
1636 $img->open(file=>'lena.png',type=>'png'); # initializes from file
1637
1638or if you want to create an empty image:
1639
1640 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
1641
1642This example creates a completely black image of width 400 and
1643height 300 and 4 channels.
1644
1645If you have an existing image, use img_set() to change it's dimensions
1646- this will destroy any existing image data:
1647
1648 $img->img_set(xsize=>500, ysize=>500, channels=>4);
1649
1650Color objects are created by calling the Imager::Color->new()
1651method:
1652
1653 $color = Imager::Color->new($red, $green, $blue);
1654 $color = Imager::Color->new($red, $green, $blue, $alpha);
1655 $color = Imager::Color->new("#C0C0FF"); # html color specification
1656
1657This object can then be passed to functions that require a color parameter.
1658
1659Coordinates in Imager have the origin in the upper left corner. The
1660horizontal coordinate increases to the right and the vertical
1661downwards.
1662
1663=head2 Reading and writing images
1664
1665C<$img-E<gt>read()> generally takes two parameters, 'file' and 'type'.
1666If the type of the file can be determined from the suffix of the file
1667it can be omitted. Format dependant parameters are: For images of
1668type 'raw' two extra parameters are needed 'xsize' and 'ysize', if the
1669'channel' parameter is omitted for type 'raw' it is assumed to be 3.
1670gif and png images might have a palette are converted to truecolor bit
1671when read. Alpha channel is preserved for png images irregardless of
1672them being in RGB or gray colorspace. Similarly grayscale jpegs are
1673one channel images after reading them. For jpeg images the iptc
1674header information (stored in the APP13 header) is avaliable to some
1675degree. You can get the raw header with C<$img-E<gt>{IPTCRAW}>, but
1676you can also retrieve the most basic information with
d2dfdcc9
TC
1677C<%hsh=$img-E<gt>parseiptc()> as always patches are welcome. pnm has no
1678extra options. Examples:
02d1d628
AMH
1679
1680 $img = Imager->new();
1681 $img->read(file=>"cover.jpg") or die $img->errstr; # gets type from name
1682
1683 $img = Imager->new();
1684 { local(*FH,$/); open(FH,"file.gif") or die $!; $a=<FH>; }
1685 $img->read(data=>$a,type=>'gif') or die $img->errstr;
1686
1687The second example shows how to read an image from a scalar, this is
1688usefull if your data originates from somewhere else than a filesystem
1689such as a database over a DBI connection.
1690
d2dfdcc9
TC
1691When writing to a tiff image file you can also specify the 'class'
1692parameter, which can currently take a single value, "fax". If class
1693is set to fax then a tiff image which should be suitable for faxing
1694will be written. For the best results start with a grayscale image.
4c2d6970
TC
1695By default the image is written at fine resolution you can override
1696this by setting the "fax_fine" parameter to 0.
d2dfdcc9 1697
a59ffd27
TC
1698If you are reading from a gif image file, you can supply a 'colors'
1699parameter which must be a reference to a scalar. The referenced
1700scalar will receive an array reference which contains the colors, each
e72d3bb1 1701represented as an Imager::Color object.
a59ffd27 1702
04516c2b
TC
1703If you already have an open file handle, for example a socket or a
1704pipe, you can specify the 'fd' parameter instead of supplying a
1705filename. Please be aware that you need to use fileno() to retrieve
1706the file descriptor for the file:
1707
1708 $img->read(fd=>fileno(FILE), type=>'gif') or die $img->errstr;
1709
1710For writing using the 'fd' option you will probably want to set $| for
1711that descriptor, since the writes to the file descriptor bypass Perl's
1712(or the C libraries) buffering. Setting $| should avoid out of order
1713output.
1714
02d1d628
AMH
1715*Note that load() is now an alias for read but will be removed later*
1716
1717C<$img-E<gt>write> has the same interface as C<read()>. The earlier
1718comments on C<read()> for autodetecting filetypes apply. For jpegs
1719quality can be adjusted via the 'jpegquality' parameter (0-100). The
1720number of colorplanes in gifs are set with 'gifplanes' and should be
1721between 1 (2 color) and 8 (256 colors). It is also possible to choose
1722between two quantizing methods with the parameter 'gifquant'. If set
1723to mc it uses the mediancut algorithm from either giflibrary. If set
1724to lm it uses a local means algorithm. It is then possible to give
1725some extra settings. lmdither is the dither deviation amount in pixels
1726(manhattan distance). lmfixed can be an array ref who holds an array
1727of Imager::Color objects. Note that the local means algorithm needs
1728much more cpu time but also gives considerable better results than the
1729median cut algorithm.
1730
1731Currently just for gif files, you can specify various options for the
1732conversion from Imager's internal RGB format to the target's indexed
1733file format. If you set the gifquant option to 'gen', you can use the
1734options specified under L<Quantization options>.
1735
1736To see what Imager is compiled to support the following code snippet
1737is sufficient:
1738
1739 use Imager;
1740 print "@{[keys %Imager::formats]}";
1741
7febf116
TC
1742When reading raw images you need to supply the width and height of the
1743image in the xsize and ysize options:
1744
1745 $img->read(file=>'foo.raw', xsize=>100, ysize=>100)
1746 or die "Cannot read raw image\n";
1747
1748If your input file has more channels than you want, or (as is common),
1749junk in the fourth channel, you can use the datachannels and
1750storechannels options to control the number of channels in your input
1751file and the resulting channels in your image. For example, if your
1752input image uses 32-bits per pixel with red, green, blue and junk
1753values for each pixel you could do:
1754
1755 $img->read(file=>'foo.raw', xsize=>100, ysize=>100, datachannels=>4,
1756 storechannels=>3)
1757 or die "Cannot read raw image\n";
1758
d04ee244
TC
1759Normally the raw image is expected to have the value for channel 1
1760immediately following channel 0 and channel 2 immediately following
1761channel 1 for each pixel. If your input image has all the channel 0
1762values for the first line of the image, followed by all the channel 1
1763values for the first line and so on, you can use the interleave option:
1764
1765 $img->read(file=>'foo.raw', xsize=100, ysize=>100, interleave=>1)
1766 or die "Cannot read raw image\n";
1767
02d1d628
AMH
1768=head2 Multi-image files
1769
1770Currently just for gif files, you can create files that contain more
1771than one image.
1772
1773To do this:
1774
1775 Imager->write_multi(\%opts, @images)
1776
b9029e27 1777Where %opts describes 4 possible types of outputs:
02d1d628 1778
b9029e27
AMH
1779=over 5
1780
1781=item type
1782
1783This is C<gif> for gif animations.
02d1d628
AMH
1784
1785=item callback
1786
1787A code reference which is called with a single parameter, the data to
1788be written. You can also specify $opts{maxbuffer} which is the
1789maximum amount of data buffered. Note that there can be larger writes
1790than this if the file library writes larger blocks. A smaller value
1791maybe useful for writing to a socket for incremental display.
1792
1793=item fd
1794
1795The file descriptor to save the images to.
1796
1797=item file
1798
1799The name of the file to write to.
1800
1801%opts may also include the keys from L<Gif options> and L<Quantization
1802options>.
1803
1804=back
1805
f5991c03
TC
1806You must also specify the file format using the 'type' option.
1807
02d1d628
AMH
1808The current aim is to support other multiple image formats in the
1809future, such as TIFF, and to support reading multiple images from a
1810single file.
1811
1812A simple example:
1813
1814 my @images;
1815 # ... code to put images in @images
1816 Imager->write_multi({type=>'gif',
1817 file=>'anim.gif',
f5991c03 1818 gif_delays=>[ (10) x @images ] },
02d1d628
AMH
1819 @images)
1820 or die "Oh dear!";
1821
1822=head2 Gif options
1823
1824These options can be specified when calling write_multi() for gif
1825files, when writing a single image with the gifquant option set to
1826'gen', or for direct calls to i_writegif_gen and i_writegif_callback.
1827
1828Note that some viewers will ignore some of these options
1829(gif_user_input in particular).
1830
1831=over 4
1832
1833=item gif_each_palette
1834
1835Each image in the gif file has it's own palette if this is non-zero.
1836All but the first image has a local colour table (the first uses the
1837global colour table.
1838
1839=item interlace
1840
1841The images are written interlaced if this is non-zero.
1842
1843=item gif_delays
1844
1845A reference to an array containing the delays between images, in 1/100
1846seconds.
1847
ed88b092
TC
1848If you want the same delay for every frame you can simply set this to
1849the delay in 1/100 seconds.
1850
02d1d628
AMH
1851=item gif_user_input
1852
1853A reference to an array contains user input flags. If the given flag
1854is non-zero the image viewer should wait for input before displaying
1855the next image.
1856
1857=item gif_disposal
1858
1859A reference to an array of image disposal methods. These define what
1860should be done to the image before displaying the next one. These are
1861integers, where 0 means unspecified, 1 means the image should be left
1862in place, 2 means restore to background colour and 3 means restore to
1863the previous value.
1864
1865=item gif_tran_color
1866
1867A reference to an Imager::Color object, which is the colour to use for
ae235ea6
TC
1868the palette entry used to represent transparency in the palette. You
1869need to set the transp option (see L<Quantization options>) for this
1870value to be used.
02d1d628
AMH
1871
1872=item gif_positions
1873
1874A reference to an array of references to arrays which represent screen
1875positions for each image.
1876
1877=item gif_loop_count
1878
1879If this is non-zero the Netscape loop extension block is generated,
1880which makes the animation of the images repeat.
1881
1882This is currently unimplemented due to some limitations in giflib.
1883
1884=back
1885
1886=head2 Quantization options
1887
1888These options can be specified when calling write_multi() for gif
1889files, when writing a single image with the gifquant option set to
1890'gen', or for direct calls to i_writegif_gen and i_writegif_callback.
1891
1892=over 4
1893
1894=item colors
1895
1896A arrayref of colors that are fixed. Note that some color generators
1897will ignore this.
1898
1899=item transp
1900
1901The type of transparency processing to perform for images with an
1902alpha channel where the output format does not have a proper alpha
1903channel (eg. gif). This can be any of:
1904
1905=over 4
1906
1907=item none
1908
1909No transparency processing is done. (default)
1910
1911=item threshold
1912
1913Pixels more transparent that tr_threshold are rendered as transparent.
1914
1915=item errdiff
1916
1917An error diffusion dither is done on the alpha channel. Note that
1918this is independent of the translation performed on the colour
1919channels, so some combinations may cause undesired artifacts.
1920
1921=item ordered
1922
1923The ordered dither specified by tr_orddith is performed on the alpha
1924channel.
1925
1926=back
1927
ae235ea6
TC
1928This will only be used if the image has an alpha channel, and if there
1929is space in the palette for a transparency colour.
1930
02d1d628
AMH
1931=item tr_threshold
1932
1933The highest alpha value at which a pixel will be made transparent when
1934transp is 'threshold'. (0-255, default 127)
1935
1936=item tr_errdiff
1937
1938The type of error diffusion to perform on the alpha channel when
1939transp is 'errdiff'. This can be any defined error diffusion type
1940except for custom (see errdiff below).
1941
626cabcc 1942=item tr_orddith
02d1d628
AMH
1943
1944The type of ordered dither to perform on the alpha channel when transp
626cabcc 1945is 'ordered'. Possible values are:
02d1d628
AMH
1946
1947=over 4
1948
1949=item random
1950
529ef1f3 1951A semi-random map is used. The map is the same each time.
02d1d628
AMH
1952
1953=item dot8
1954
19558x8 dot dither.
1956
1957=item dot4
1958
19594x4 dot dither
1960
1961=item hline
1962
1963horizontal line dither.
1964
1965=item vline
1966
1967vertical line dither.
1968
1969=item "/line"
1970
1971=item slashline
1972
1973diagonal line dither
1974
1975=item '\line'
1976
1977=item backline
1978
1979diagonal line dither
1980
529ef1f3
TC
1981=item tiny
1982
1983dot matrix dither (currently the default). This is probably the best
1984for displays (like web pages).
1985
02d1d628
AMH
1986=item custom
1987
1988A custom dither matrix is used - see tr_map
1989
1990=back
1991
1992=item tr_map
1993
1994When tr_orddith is custom this defines an 8 x 8 matrix of integers
1995representing the transparency threshold for pixels corresponding to
1996each position. This should be a 64 element array where the first 8
1997entries correspond to the first row of the matrix. Values should be
1998betweern 0 and 255.
1999
2000=item make_colors
2001
2002Defines how the quantization engine will build the palette(s).
2003Currently this is ignored if 'translate' is 'giflib', but that may
2004change. Possible values are:
2005
2006=over 4
2007
2008=item none
2009
2010Only colors supplied in 'colors' are used.
2011
2012=item webmap
2013
2014The web color map is used (need url here.)
2015
2016=item addi
2017
2018The original code for generating the color map (Addi's code) is used.
2019
2020=back
2021
2022Other methods may be added in the future.
2023
2024=item colors
2025
2026A arrayref containing Imager::Color objects, which represents the
2027starting set of colors to use in translating the images. webmap will
2028ignore this. The final colors used are copied back into this array
2029(which is expanded if necessary.)
2030
2031=item max_colors
2032
2033The maximum number of colors to use in the image.
2034
2035=item translate
2036
2037The method used to translate the RGB values in the source image into
2038the colors selected by make_colors. Note that make_colors is ignored
2039whene translate is 'giflib'.
2040
2041Possible values are:
2042
2043=over 4
2044
2045=item giflib
2046
2047The giflib native quantization function is used.
2048
2049=item closest
2050
2051The closest color available is used.
2052
2053=item perturb
2054
2055The pixel color is modified by perturb, and the closest color is chosen.
2056
2057=item errdiff
2058
2059An error diffusion dither is performed.
2060
2061=back
2062
2063It's possible other transate values will be added.
2064
2065=item errdiff
2066
2067The type of error diffusion dither to perform. These values (except
2068for custom) can also be used in tr_errdif.
2069
2070=over 4
2071
2072=item floyd
2073
2074Floyd-Steinberg dither
2075
2076=item jarvis
2077
2078Jarvis, Judice and Ninke dither
2079
2080=item stucki
2081
2082Stucki dither
2083
2084=item custom
2085
2086Custom. If you use this you must also set errdiff_width,
2087errdiff_height and errdiff_map.
2088
2089=back
2090
2091=item errdiff_width
2092
2093=item errdiff_height
2094
2095=item errdiff_orig
2096
2097=item errdiff_map
2098
2099When translate is 'errdiff' and errdiff is 'custom' these define a
2100custom error diffusion map. errdiff_width and errdiff_height define
2101the size of the map in the arrayref in errdiff_map. errdiff_orig is
2102an integer which indicates the current pixel position in the top row
2103of the map.
2104
2105=item perturb
2106
2107When translate is 'perturb' this is the magnitude of the random bias
2108applied to each channel of the pixel before it is looked up in the
2109color table.
2110
2111=back
2112
2113=head2 Obtaining/setting attributes of images
2114
2115To get the size of an image in pixels the C<$img-E<gt>getwidth()> and
2116C<$img-E<gt>getheight()> are used.
2117
2118To get the number of channels in
2119an image C<$img-E<gt>getchannels()> is used. $img-E<gt>getmask() and
2120$img-E<gt>setmask() are used to get/set the channel mask of the image.
2121
2122 $mask=$img->getmask();
2123 $img->setmask(mask=>1+2); # modify red and green only
2124 $img->setmask(mask=>8); # modify alpha only
2125 $img->setmask(mask=>$mask); # restore previous mask
2126
2127The mask of an image describes which channels are updated when some
2128operation is performed on an image. Naturally it is not possible to
2129apply masks to operations like scaling that alter the dimensions of
2130images.
2131
2132It is possible to have Imager find the number of colors in an image
2133by using C<$img-E<gt>getcolorcount()>. It requires memory proportionally
2134to the number of colors in the image so it is possible to have it
2135stop sooner if you only need to know if there are more than a certain number
2136of colors in the image. If there are more colors than asked for
2137the function return undef. Examples:
2138
2139 if (!defined($img->getcolorcount(maxcolors=>512)) {
2140 print "Less than 512 colors in image\n";
2141 }
2142
2143=head2 Drawing Methods
2144
2145IMPLEMENTATION MORE OR LESS DONE CHECK THE TESTS
02d1d628
AMH
2146DOCUMENTATION OF THIS SECTION OUT OF SYNC
2147
2148It is possible to draw with graphics primitives onto images. Such
2149primitives include boxes, arcs, circles and lines. A reference
2150oriented list follows.
2151
2152Box:
2153 $img->box(color=>$blue,xmin=>10,ymin=>30,xmax=>200,ymax=>300,filled=>1);
2154
2155The above example calls the C<box> method for the image and the box
2156covers the pixels with in the rectangle specified. If C<filled> is
2157ommited it is drawn as an outline. If any of the edges of the box are
2158ommited it will snap to the outer edge of the image in that direction.
2159Also if a color is omitted a color with (255,255,255,255) is used
2160instead.
2161
2162Arc:
2163 $img->arc(color=>$red, r=20, x=>200, y=>100, d1=>10, d2=>20 );
2164
2165This creates a filled red arc with a 'center' at (200, 100) and spans
216610 degrees and the slice has a radius of 20. SEE section on BUGS.
2167
2168Circle:
2169 $img->circle(color=>$green, r=50, x=>200, y=>100);
2170
2171This creates a green circle with its center at (200, 100) and has a
2172radius of 20.
2173
2174Line:
2175 $img->line(color=>$green, x1=10, x2=>100,
2176 y1=>20, y2=>50, antialias=>1 );
2177
2178That draws an antialiased line from (10,100) to (20,50).
2179
2180Polyline:
2181 $img->polyline(points=>[[$x0,$y0],[$x1,$y1],[$x2,$y2]],color=>$red);
2182 $img->polyline(x=>[$x0,$x1,$x2], y=>[$y0,$y1,$y2], antialias=>1);
2183
2184Polyline is used to draw multilple lines between a series of points.
2185The point set can either be specified as an arrayref to an array of
2186array references (where each such array represents a point). The
2187other way is to specify two array references.
2188
2189=head2 Text rendering
2190
2191Text rendering is described in the Imager::Font manpage.
2192
2193=head2 Image resizing
2194
2195To scale an image so porportions are maintained use the
2196C<$img-E<gt>scale()> method. if you give either a xpixels or ypixels
2197parameter they will determine the width or height respectively. If
2198both are given the one resulting in a larger image is used. example:
2199C<$img> is 700 pixels wide and 500 pixels tall.
2200
2201 $img->scale(xpixels=>400); # 400x285
2202 $img->scale(ypixels=>400); # 560x400
2203
2204 $img->scale(xpixels=>400,ypixels=>400); # 560x400
2205 $img->scale(xpixels=>400,ypixels=>400,type=>min); # 400x285
2206
2207 $img->scale(scalefactor=>0.25); 175x125 $img->scale(); # 350x250
2208
2209if you want to create low quality previews of images you can pass
2210C<qtype=E<gt>'preview'> to scale and it will use nearest neighbor
2211sampling instead of filtering. It is much faster but also generates
2212worse looking images - especially if the original has a lot of sharp
2213variations and the scaled image is by more than 3-5 times smaller than
2214the original.
2215
2216If you need to scale images per axis it is best to do it simply by
2217calling scaleX and scaleY. You can pass either 'scalefactor' or
2218'pixels' to both functions.
2219
2220Another way to resize an image size is to crop it. The parameters
2221to crop are the edges of the area that you want in the returned image.
2222If a parameter is omited a default is used instead.
2223
2224 $newimg = $img->crop(left=>50, right=>100, top=>10, bottom=>100);
2225 $newimg = $img->crop(left=>50, top=>10, width=>50, height=>90);
2226 $newimg = $img->crop(left=>50, right=>100); # top
2227
2228You can also specify width and height parameters which will produce a
2229new image cropped from the center of the input image, with the given
2230width and height.
2231
2232 $newimg = $img->crop(width=>50, height=>50);
2233
2234The width and height parameters take precedence over the left/right
2235and top/bottom parameters respectively.
2236
2237=head2 Copying images
2238
2239To create a copy of an image use the C<copy()> method. This is usefull
2240if you want to keep an original after doing something that changes the image
2241inplace like writing text.
2242
2243 $img=$orig->copy();
2244
2245To copy an image to onto another image use the C<paste()> method.
2246
2247 $dest->paste(left=>40,top=>20,img=>$logo);
2248
2249That copies the entire C<$logo> image onto the C<$dest> image so that the
2250upper left corner of the C<$logo> image is at (40,20).
2251
142c26ff
AMH
2252
2253=head2 Flipping images
2254
2255An inplace horizontal or vertical flip is possible by calling the
9191e525
AMH
2256C<flip()> method. If the original is to be preserved it's possible to
2257make a copy first. The only parameter it takes is the C<dir>
2258parameter which can take the values C<h>, C<v>, C<vh> and C<hv>.
142c26ff 2259
9191e525
AMH
2260 $img->flip(dir=>"h"); # horizontal flip
2261 $img->flip(dir=>"vh"); # vertical and horizontal flip
2262 $nimg = $img->copy->flip(dir=>"v"); # make a copy and flip it vertically
142c26ff 2263
9191e525 2264=head2 Blending Images
142c26ff 2265
9191e525 2266To put an image or a part of an image directly
142c26ff
AMH
2267into another it is best to call the C<paste()> method on the image you
2268want to add to.
02d1d628
AMH
2269
2270 $img->paste(img=>$srcimage,left=>30,top=>50);
2271
2272That will take paste C<$srcimage> into C<$img> with the upper
2273left corner at (30,50). If no values are given for C<left>
2274or C<top> they will default to 0.
2275
2276A more complicated way of blending images is where one image is
2277put 'over' the other with a certain amount of opaqueness. The
2278method that does this is rubthrough.
2279
2280 $img->rubthrough(src=>$srcimage,tx=>30,ty=>50);
2281
2282That will take the image C<$srcimage> and overlay it with the
2283upper left corner at (30,50). The C<$srcimage> must be a 4 channel
2284image. The last channel is used as an alpha channel.
2285
2286
2287=head2 Filters
2288
2289A special image method is the filter method. An example is:
2290
2291 $img->filter(type=>'autolevels');
2292
2293This will call the autolevels filter. Here is a list of the filters
2294that are always avaliable in Imager. This list can be obtained by
2295running the C<filterlist.perl> script that comes with the module
2296source.
2297
2298 Filter Arguments
2299 turbnoise
2300 autolevels lsat(0.1) usat(0.1) skew(0)
2301 radnoise
2302 noise amount(3) subtype(0)
2303 contrast intensity
2304 hardinvert
2305 gradgen xo yo colors dist
2306
2307The default values are in parenthesis. All parameters must have some
2308value but if a parameter has a default value it may be omitted when
2309calling the filter function.
2310
2311FIXME: make a seperate pod for filters?
2312
f5991c03
TC
2313=head2 Color transformations
2314
2315You can use the convert method to transform the color space of an
2316image using a matrix. For ease of use some presets are provided.
2317
2318The convert method can be used to:
2319
2320=over 4
2321
2322=item *
2323
2324convert an RGB or RGBA image to grayscale.
2325
2326=item *
2327
2328convert a grayscale image to RGB.
2329
2330=item *
2331
2332extract a single channel from an image.
2333
2334=item *
2335
2336set a given channel to a particular value (or from another channel)
2337
2338=back
2339
2340The currently defined presets are:
2341
2342=over
2343
2344=item gray
2345
2346=item grey
2347
2348converts an RGBA image into a grayscale image with alpha channel, or
2349an RGB image into a grayscale image without an alpha channel.
2350
2351This weights the RGB channels at 22.2%, 70.7% and 7.1% respectively.
2352
2353=item noalpha
2354
2355removes the alpha channel from a 2 or 4 channel image. An identity
2356for other images.
2357
2358=item red
2359
2360=item channel0
2361
2362extracts the first channel of the image into a single channel image
2363
2364=item green
2365
2366=item channel1
2367
2368extracts the second channel of the image into a single channel image
2369
2370=item blue
2371
2372=item channel2
2373
2374extracts the third channel of the image into a single channel image
2375
2376=item alpha
2377
2378extracts the alpha channel of the image into a single channel image.
2379
2380If the image has 1 or 3 channels (assumed to be grayscale of RGB) then
2381the resulting image will be all white.
2382
2383=item rgb
2384
2385converts a grayscale image to RGB, preserving the alpha channel if any
2386
2387=item addalpha
2388
2389adds an alpha channel to a grayscale or RGB image. Preserves an
2390existing alpha channel for a 2 or 4 channel image.
2391
2392=back
2393
2394For example, to convert an RGB image into a greyscale image:
2395
2396 $new = $img->convert(preset=>'grey'); # or gray
2397
2398or to convert a grayscale image to an RGB image:
2399
2400 $new = $img->convert(preset=>'rgb');
2401
2402The presets aren't necessary simple constants in the code, some are
2403generated based on the number of channels in the input image.
2404
2405If you want to perform some other colour transformation, you can use
2406the 'matrix' parameter.
2407
2408For each output pixel the following matrix multiplication is done:
2409
2410 channel[0] [ [ $c00, $c01, ... ] inchannel[0]
2411 [ ... ] = ... x [ ... ]
2412 channel[n-1] [ $cn0, ..., $cnn ] ] inchannel[max]
2413 1
2414
2415So if you want to swap the red and green channels on a 3 channel image:
2416
2417 $new = $img->convert(matrix=>[ [ 0, 1, 0 ],
2418 [ 1, 0, 0 ],
2419 [ 0, 0, 1 ] ]);
2420
2421or to convert a 3 channel image to greyscale using equal weightings:
2422
2423 $new = $img->convert(matrix=>[ [ 0.333, 0.333, 0.334 ] ])
2424
02d1d628
AMH
2425=head2 Transformations
2426
2427Another special image method is transform. It can be used to generate
2428warps and rotations and such features. It can be given the operations
2429in postfix notation or the module Affix::Infix2Postfix can be used.
2430Look in the test case t/t55trans.t for an example.
2431
2432transform() needs expressions (or opcodes) that determine the source
2433pixel for each target pixel. Source expressions are infix expressions
2434using any of the +, -, *, / or ** binary operators, the - unary
2435operator, ( and ) for grouping and the sin() and cos() functions. The
2436target pixel is input as the variables x and y.
2437
2438You specify the x and y expressions as xexpr and yexpr respectively.
2439You can also specify opcodes directly, but that's magic deep enough
2440that you can look at the source code.
2441
2442You can still use the transform() function, but the transform2()
2443function is just as fast and is more likely to be enhanced and
2444maintained.
2445
2446Later versions of Imager also support a transform2() class method
2447which allows you perform a more general set of operations, rather than
2448just specifying a spatial transformation as with the transform()
2449method, you can also perform colour transformations, image synthesis
2450and image combinations.
2451
2452transform2() takes an reference to an options hash, and a list of
2453images to operate one (this list may be empty):
2454
2455 my %opts;
2456 my @imgs;
2457 ...
2458 my $img = Imager::transform2(\%opts, @imgs)
2459 or die "transform2 failed: $Imager::ERRSTR";
2460
2461The options hash may define a transformation function, and optionally:
2462
2463=over 4
2464
2465=item *
2466
2467width - the width of the image in pixels. If this isn't supplied the
2468width of the first input image is used. If there are no input images
2469an error occurs.
2470
2471=item *
2472
2473height - the height of the image in pixels. If this isn't supplied
2474the height of the first input image is used. If there are no input
2475images an error occurs.
2476
2477=item *
2478
2479constants - a reference to hash of constants to define for the
2480expression engine. Some extra constants are defined by Imager
2481
2482=back
2483
2484The tranformation function is specified using either the expr or
2485rpnexpr member of the options.
2486
2487=over 4
2488
2489=item Infix expressions
2490
2491You can supply infix expressions to transform 2 with the expr keyword.
2492
2493$opts{expr} = 'return getp1(w-x, h-y)'
2494
2495The 'expression' supplied follows this general grammar:
2496
2497 ( identifier '=' expr ';' )* 'return' expr
2498
2499This allows you to simplify your expressions using variables.
2500
2501A more complex example might be:
2502
2503$opts{expr} = 'pix = getp1(x,y); return if(value(pix)>0.8,pix*0.8,pix)'
2504
2505Currently to use infix expressions you must have the Parse::RecDescent
2506module installed (available from CPAN). There is also what might be a
2507significant delay the first time you run the infix expression parser
2508due to the compilation of the expression grammar.
2509
2510=item Postfix expressions
2511
2512You can supply postfix or reverse-polish notation expressions to
2513transform2() through the rpnexpr keyword.
2514
2515The parser for rpnexpr emulates a stack machine, so operators will
2516expect to see their parameters on top of the stack. A stack machine
2517isn't actually used during the image transformation itself.
2518
2519You can store the value at the top of the stack in a variable called
2520foo using !foo and retrieve that value again using @foo. The !foo
2521notation will pop the value from the stack.
2522
2523An example equivalent to the infix expression above:
2524
2525 $opts{rpnexpr} = 'x y getp1 !pix @pix value 0.8 gt @pix 0.8 * @pix ifp'
2526
2527=back
2528
2529transform2() has a fairly rich range of operators.
2530
2531=over 4
2532
2533=item +, *, -, /, %, **
2534
2535multiplication, addition, subtraction, division, remainder and
2536exponentiation. Multiplication, addition and subtraction can be used
2537on colour values too - though you need to be careful - adding 2 white
2538values together and multiplying by 0.5 will give you grey, not white.
2539
2540Division by zero (or a small number) just results in a large number.
2541Modulo zero (or a small number) results in zero.
2542
2543=item sin(N), cos(N), atan2(y,x)
2544
2545Some basic trig functions. They work in radians, so you can't just
2546use the hue values.
2547
2548=item distance(x1, y1, x2, y2)
2549
2550Find the distance between two points. This is handy (along with
2551atan2()) for producing circular effects.
2552
2553=item sqrt(n)
2554
2555Find the square root. I haven't had much use for this since adding
2556the distance() function.
2557
2558=item abs(n)
2559
2560Find the absolute value.
2561
2562=item getp1(x,y), getp2(x,y), getp3(x, y)
2563
2564Get the pixel at position (x,y) from the first, second or third image
2565respectively. I may add a getpn() function at some point, but this
2566prevents static checking of the instructions against the number of
2567images actually passed in.
2568
2569=item value(c), hue(c), sat(c), hsv(h,s,v)
2570
2571Separates a colour value into it's value (brightness), hue (colour)
2572and saturation elements. Use hsv() to put them back together (after
2573suitable manipulation).
2574
2575=item red(c), green(c), blue(c), rgb(r,g,b)
2576
2577Separates a colour value into it's red, green and blue colours. Use
2578rgb(r,g,b) to put it back together.
2579
2580=item int(n)
2581
2582Convert a value to an integer. Uses a C int cast, so it may break on
2583large values.
2584
2585=item if(cond,ntrue,nfalse), if(cond,ctrue,cfalse)
2586
2587A simple (and inefficient) if function.
2588
2589=item <=,<,==,>=,>,!=
2590
2591Relational operators (typically used with if()). Since we're working
2592with floating point values the equalities are 'near equalities' - an
2593epsilon value is used.
2594
2595=item &&, ||, not(n)
2596
2597Basic logical operators.
2598
2599=back
2600
2601A few examples:
2602
2603=over 4
2604
2605=item rpnexpr=>'x 25 % 15 * y 35 % 10 * getp1 !pat x y getp1 !pix @pix sat 0.7 gt @pat @pix ifp'
2606
2607tiles a smaller version of the input image over itself where the colour has a saturation over 0.7.
2608
2609=item rpnexpr=>'x 25 % 15 * y 35 % 10 * getp1 !pat y 360 / !rat x y getp1 1 @rat - pmult @pat @rat pmult padd'
2610
2611tiles the input image over itself so that at the top of the image the
2612full-size image is at full strength and at the bottom the tiling is
2613most visible.
2614
2615=item rpnexpr=>'x y getp1 !pix @pix value 0.96 gt @pix sat 0.1 lt and 128 128 255 rgb @pix ifp'
2616
2617replace pixels that are white or almost white with a palish blue
2618
2619=item rpnexpr=>'x 35 % 10 * y 45 % 8 * getp1 !pat x y getp1 !pix @pix sat 0.2 lt @pix value 0.9 gt and @pix @pat @pix value 2 / 0.5 + pmult ifp'
2620
2621Tiles the input image overitself where the image isn't white or almost
2622white.
2623
2624=item rpnexpr=>'x y 160 180 distance !d y 180 - x 160 - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a2 180 * 3.1416 / 1 @a2 sin 1 + 2 / hsv'
2625
2626Produces a spiral.
2627
2628=item rpnexpr=>'x y 160 180 distance !d y 180 - x 160 - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a 180 * 3.1416 / 1 @a2 sin 1 + 2 / hsv'
2629
2630A spiral built on top of a colour wheel.
2631
2632=back
2633
2634For details on expression parsing see L<Imager::Expr>. For details on
2635the virtual machine used to transform the images, see
2636L<Imager::regmach.pod>.
2637
2638=head2 Plugins
2639
2640It is possible to add filters to the module without recompiling the
2641module itself. This is done by using DSOs (Dynamic shared object)
2642avaliable on most systems. This way you can maintain our own filters
2643and not have to get me to add it, or worse patch every new version of
2644the Module. Modules can be loaded AND UNLOADED at runtime. This
2645means that you can have a server/daemon thingy that can do something
2646like:
2647
2648 load_plugin("dynfilt/dyntest.so") || die "unable to load plugin\n";
2649 %hsh=(a=>35,b=>200,type=>lin_stretch);
2650 $img->filter(%hsh);
2651 unload_plugin("dynfilt/dyntest.so") || die "unable to load plugin\n";
2652 $img->write(type=>'pnm',file=>'testout/t60.jpg')
2653 || die "error in write()\n";
2654
2655Someone decides that the filter is not working as it should -
2656dyntest.c modified and recompiled.
2657
2658 load_plugin("dynfilt/dyntest.so") || die "unable to load plugin\n";
2659 $img->filter(%hsh);
2660
2661An example plugin comes with the module - Please send feedback to
2662addi@umich.edu if you test this.
2663
2664Note: This seems to test ok on the following systems:
2665Linux, Solaris, HPUX, OpenBSD, FreeBSD, TRU64/OSF1, AIX.
2666If you test this on other systems please let me know.
2667
2668=head1 BUGS
2669
2670box, arc, circle do not support antialiasing yet. arc, is only filled
2671as of yet. Some routines do not return $self where they should. This
2672affects code like this, C<$img-E<gt>box()-E<gt>arc()> where an object
2673is expected.
2674
2675When saving Gif images the program does NOT try to shave of extra
2676colors if it is possible. If you specify 128 colors and there are
2677only 2 colors used - it will have a 128 colortable anyway.
2678
2679=head1 AUTHOR
2680
2681Arnar M. Hrafnkelsson, addi@umich.edu
2682And a great deal of help from others - see the README for a complete
2683list.
2684=head1 SEE ALSO
2685
2686perl(1), Imager::Color(3), Affix::Infix2Postfix(3), Parse::RecDescent(3)
2687http://www.eecs.umich.edu/~addi/perl/Imager/
2688
2689
2690=cut