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