4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR $fontstate %OPCODES $I2P $FORMATGUESS $warn_obsolete);
82 i_writetiff_wiol_faxable
151 @ISA = qw(Exporter DynaLoader);
152 bootstrap Imager $VERSION;
156 i_init_fonts(); # Initialize font engines
157 Imager::Font::__init();
158 for(i_list_formats()) { $formats{$_}++; }
160 if ($formats{'t1'}) {
164 if (!$formats{'t1'} and !$formats{'tt'}
165 && !$formats{'ft2'} && !$formats{'w32'}) {
166 $fontstate='no font support';
169 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
173 # the members of the subhashes under %filters are:
174 # callseq - a list of the parameters to the underlying filter in the
175 # order they are passed
176 # callsub - a code ref that takes a named parameter list and calls the
178 # defaults - a hash of default values
179 # names - defines names for value of given parameters so if the names
180 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
181 # foo parameter, the filter will receive 1 for the foo
184 callseq => ['image','intensity'],
185 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
189 callseq => ['image', 'amount', 'subtype'],
190 defaults => { amount=>3,subtype=>0 },
191 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
194 $filters{hardinvert} ={
195 callseq => ['image'],
197 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
200 $filters{autolevels} ={
201 callseq => ['image','lsat','usat','skew'],
202 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
203 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
206 $filters{turbnoise} ={
207 callseq => ['image'],
208 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
209 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
212 $filters{radnoise} ={
213 callseq => ['image'],
214 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
215 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
219 callseq => ['image', 'coef'],
221 callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
226 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
227 defaults => { dist => 0 },
231 my @colors = @{$hsh{colors}};
234 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
238 $filters{nearest_color} ={
239 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
241 callsub => sub { my %hsh=@_; i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, $hsh{colors}, $hsh{dist}); }
243 $filters{gaussian} = {
244 callseq => [ 'image', 'stddev' ],
246 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
250 callseq => [ qw(image size) ],
251 defaults => { size => 20 },
252 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
256 callseq => [ qw(image bump elevation lightx lighty st) ],
257 defaults => { elevation=>0, st=> 2 },
260 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
261 $hsh{lightx}, $hsh{lighty}, $hsh{st});
264 $filters{bumpmap_complex} =
266 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
277 Ia => Imager::Color->new(rgb=>[0,0,0]),
278 Il => Imager::Color->new(rgb=>[255,255,255]),
279 Is => Imager::Color->new(rgb=>[255,255,255]),
283 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
284 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
285 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
289 $filters{postlevels} =
291 callseq => [ qw(image levels) ],
292 defaults => { levels => 10 },
293 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
295 $filters{watermark} =
297 callseq => [ qw(image wmark tx ty pixdiff) ],
298 defaults => { pixdiff=>10, tx=>0, ty=>0 },
302 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
308 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
310 ftype => { linear => 0,
316 repeat => { none => 0,
331 multiply => 2, mult => 2,
334 subtract => 5, 'sub' => 5,
344 defaults => { ftype => 0, repeat => 0, combine => 0,
345 super_sample => 0, ssample_param => 4,
348 Imager::Color->new(0,0,0),
349 Imager::Color->new(255, 255, 255),
358 # make sure the segments are specified with colors
360 for my $segment (@{$hsh{segments}}) {
361 my @new_segment = @$segment;
363 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
364 push @segments, \@new_segment;
367 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
368 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
369 $hsh{ssample_param}, \@segments);
372 $filters{unsharpmask} =
374 callseq => [ qw(image stddev scale) ],
375 defaults => { stddev=>2.0, scale=>1.0 },
379 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
383 $FORMATGUESS=\&def_guess_type;
393 # NOTE: this might be moved to an import override later on
397 # (look through @_ for special tags, process, and remove them);
399 # print Dumper($pack);
404 m_init_log($_[0],$_[1]);
405 log_entry("Imager $VERSION starting\n", 1);
410 my %parms=(loglevel=>1,@_);
412 init_log($parms{'log'},$parms{'loglevel'});
415 if (exists $parms{'warn_obsolete'}) {
416 $warn_obsolete = $parms{'warn_obsolete'};
419 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
420 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
424 if (exists $parms{'t1log'}) {
425 i_init_fonts($parms{'t1log'});
431 print "shutdown code\n";
432 # for(keys %instances) { $instances{$_}->DESTROY(); }
433 malloc_state(); # how do decide if this should be used? -- store something from the import
434 print "Imager exiting\n";
438 # Load a filter plugin
443 my ($DSO_handle,$str)=DSO_open($filename);
444 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
445 my %funcs=DSO_funclist($DSO_handle);
446 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
448 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
450 $DSOs{$filename}=[$DSO_handle,\%funcs];
453 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
454 $DEBUG && print "eval string:\n",$evstr,"\n";
466 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
467 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
468 for(keys %{$funcref}) {
470 $DEBUG && print "unloading: $_\n";
472 my $rc=DSO_close($DSO_handle);
473 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
477 # take the results of i_error() and make a message out of it
479 return join(": ", map $_->[0], i_errors());
482 # this function tries to DWIM for color parameters
483 # color objects are used as is
484 # simple scalars are simply treated as single parameters to Imager::Color->new
485 # hashrefs are treated as named argument lists to Imager::Color->new
486 # arrayrefs are treated as list arguments to Imager::Color->new iff any
488 # other arrayrefs are treated as list arguments to Imager::Color::Float
492 # perl 5.6.0 seems to do weird things to $arg if we don't make an
493 # explicitly stringified copy
494 # I vaguely remember a bug on this on p5p, but couldn't find it
495 # through bugs.perl.org (I had trouble getting it to find any bugs)
496 my $copy = $arg . "";
500 if (UNIVERSAL::isa($arg, "Imager::Color")
501 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
505 if ($copy =~ /^HASH\(/) {
506 $result = Imager::Color->new(%$arg);
508 elsif ($copy =~ /^ARRAY\(/) {
509 if (grep $_ > 1, @$arg) {
510 $result = Imager::Color->new(@$arg);
513 $result = Imager::Color::Float->new(@$arg);
517 $Imager::ERRSTR = "Not a color";
522 # assume Imager::Color::new knows how to handle it
523 $result = Imager::Color->new($arg);
531 # Methods to be called on objects.
534 # Create a new Imager object takes very few parameters.
535 # usually you call this method and then call open from
536 # the resulting object
543 $self->{IMG}=undef; # Just to indicate what exists
544 $self->{ERRSTR}=undef; #
545 $self->{DEBUG}=$DEBUG;
546 $self->{DEBUG} && print "Initialized Imager\n";
547 if (defined $hsh{xsize} && defined $hsh{ysize}) {
548 unless ($self->img_set(%hsh)) {
549 $Imager::ERRSTR = $self->{ERRSTR};
556 # Copy an entire image with no changes
557 # - if an image has magic the copy of it will not be magical
561 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
563 unless (defined wantarray) {
565 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
569 my $newcopy=Imager->new();
570 $newcopy->{IMG}=i_img_new();
571 i_copy($newcopy->{IMG},$self->{IMG});
579 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
580 my %input=(left=>0, top=>0, @_);
581 unless($input{img}) {
582 $self->{ERRSTR}="no source image";
585 $input{left}=0 if $input{left} <= 0;
586 $input{top}=0 if $input{top} <= 0;
588 my($r,$b)=i_img_info($src->{IMG});
590 i_copyto($self->{IMG}, $src->{IMG},
591 0,0, $r, $b, $input{left}, $input{top});
592 return $self; # What should go here??
595 # Crop an image - i.e. return a new image that is smaller
599 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
601 unless (defined wantarray) {
603 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
609 my ($w, $h, $l, $r, $b, $t) =
610 @hsh{qw(width height left right bottom top)};
612 # work through the various possibilities
617 elsif (!defined $r) {
618 $r = $self->getwidth;
630 $l = int(0.5+($self->getwidth()-$w)/2);
635 $r = $self->getwidth;
641 elsif (!defined $b) {
642 $b = $self->getheight;
654 $t=int(0.5+($self->getheight()-$h)/2);
659 $b = $self->getheight;
662 ($l,$r)=($r,$l) if $l>$r;
663 ($t,$b)=($b,$t) if $t>$b;
666 $r > $self->getwidth and $r = $self->getwidth;
668 $b > $self->getheight and $b = $self->getheight;
670 if ($l == $r || $t == $b) {
671 $self->_set_error("resulting image would have no content");
675 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
677 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
682 my ($self, %opts) = @_;
684 $self->{IMG} or return $self->_set_error("Not a valid image");
686 my $x = $opts{xsize} || $self->getwidth;
687 my $y = $opts{ysize} || $self->getheight;
688 my $channels = $opts{channels} || $self->getchannels;
690 my $out = Imager->new;
691 if ($channels == $self->getchannels) {
692 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
695 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
697 unless ($out->{IMG}) {
698 $self->{ERRSTR} = $self->_error_as_msg;
705 # Sets an image to a certain size and channel number
706 # if there was previously data in the image it is discarded
711 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
713 if (defined($self->{IMG})) {
714 # let IIM_DESTROY destroy it, it's possible this image is
715 # referenced from a virtual image (like masked)
716 #i_img_destroy($self->{IMG});
720 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
721 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
722 $hsh{maxcolors} || 256);
724 elsif ($hsh{bits} eq 'double') {
725 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
727 elsif ($hsh{bits} == 16) {
728 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
731 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
735 unless ($self->{IMG}) {
736 $self->{ERRSTR} = Imager->_error_as_msg();
743 # created a masked version of the current image
747 $self or return undef;
748 my %opts = (left => 0,
750 right => $self->getwidth,
751 bottom => $self->getheight,
753 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
755 my $result = Imager->new;
756 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
757 $opts{top}, $opts{right} - $opts{left},
758 $opts{bottom} - $opts{top});
759 # keep references to the mask and base images so they don't
761 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
766 # convert an RGB image into a paletted image
770 if (@_ != 1 && !ref $_[0]) {
777 unless (defined wantarray) {
779 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
783 my $result = Imager->new;
784 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
786 #print "Type ", i_img_type($result->{IMG}), "\n";
788 if ($result->{IMG}) {
792 $self->{ERRSTR} = $self->_error_as_msg;
797 # convert a paletted (or any image) to an 8-bit/channel RGB images
802 unless (defined wantarray) {
804 warn "to_rgb8() called in void context - to_rgb8() returns the cropped image at $caller[1] line $caller[2]\n";
809 $result = Imager->new;
810 $result->{IMG} = i_img_to_rgb($self->{IMG})
819 my %opts = (colors=>[], @_);
821 @{$opts{colors}} or return undef;
823 $self->{IMG} and i_addcolors($self->{IMG}, @{$opts{colors}});
828 my %opts = (start=>0, colors=>[], @_);
829 @{$opts{colors}} or return undef;
831 $self->{IMG} and i_setcolors($self->{IMG}, $opts{start}, @{$opts{colors}});
837 if (!exists $opts{start} && !exists $opts{count}) {
840 $opts{count} = $self->colorcount;
842 elsif (!exists $opts{count}) {
845 elsif (!exists $opts{start}) {
850 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
854 i_colorcount($_[0]{IMG});
858 i_maxcolors($_[0]{IMG});
864 $opts{color} or return undef;
866 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
871 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
872 if ($bits && $bits == length(pack("d", 1)) * 8) {
881 return i_img_type($self->{IMG}) ? "paletted" : "direct";
887 $self->{IMG} and i_img_virtual($self->{IMG});
891 my ($self, %opts) = @_;
893 $self->{IMG} or return;
895 if (defined $opts{name}) {
899 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
900 push @result, (i_tags_get($self->{IMG}, $found))[1];
903 return wantarray ? @result : $result[0];
905 elsif (defined $opts{code}) {
909 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
910 push @result, (i_tags_get($self->{IMG}, $found))[1];
917 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
920 return i_tags_count($self->{IMG});
929 return -1 unless $self->{IMG};
931 if (defined $opts{value}) {
932 if ($opts{value} =~ /^\d+$/) {
934 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
937 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
940 elsif (defined $opts{data}) {
941 # force addition as a string
942 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
945 $self->{ERRSTR} = "No value supplied";
949 elsif ($opts{code}) {
950 if (defined $opts{value}) {
951 if ($opts{value} =~ /^\d+$/) {
953 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
956 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
959 elsif (defined $opts{data}) {
960 # force addition as a string
961 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
964 $self->{ERRSTR} = "No value supplied";
977 return 0 unless $self->{IMG};
979 if (defined $opts{'index'}) {
980 return i_tags_delete($self->{IMG}, $opts{'index'});
982 elsif (defined $opts{name}) {
983 return i_tags_delbyname($self->{IMG}, $opts{name});
985 elsif (defined $opts{code}) {
986 return i_tags_delbycode($self->{IMG}, $opts{code});
989 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
995 my ($self, %opts) = @_;
998 $self->deltag(name=>$opts{name});
999 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1001 elsif (defined $opts{code}) {
1002 $self->deltag(code=>$opts{code});
1003 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1011 sub _get_reader_io {
1012 my ($self, $input) = @_;
1015 return $input->{io}, undef;
1017 elsif ($input->{fd}) {
1018 return io_new_fd($input->{fd});
1020 elsif ($input->{fh}) {
1021 my $fd = fileno($input->{fh});
1023 $self->_set_error("Handle in fh option not opened");
1026 return io_new_fd($fd);
1028 elsif ($input->{file}) {
1029 my $file = IO::File->new($input->{file}, "r");
1031 $self->_set_error("Could not open $input->{file}: $!");
1035 return (io_new_fd(fileno($file)), $file);
1037 elsif ($input->{data}) {
1038 return io_new_buffer($input->{data});
1040 elsif ($input->{callback} || $input->{readcb}) {
1041 if (!$input->{seekcb}) {
1042 $self->_set_error("Need a seekcb parameter");
1044 if ($input->{maxbuffer}) {
1045 return io_new_cb($input->{writecb},
1046 $input->{callback} || $input->{readcb},
1047 $input->{seekcb}, $input->{closecb},
1048 $input->{maxbuffer});
1051 return io_new_cb($input->{writecb},
1052 $input->{callback} || $input->{readcb},
1053 $input->{seekcb}, $input->{closecb});
1057 $self->_set_error("file/fd/fh/data/callback parameter missing");
1062 sub _get_writer_io {
1063 my ($self, $input, $type) = @_;
1066 return io_new_fd($input->{fd});
1068 elsif ($input->{fh}) {
1069 my $fd = fileno($input->{fh});
1071 $self->_set_error("Handle in fh option not opened");
1075 my $oldfh = select($input->{fh});
1076 # flush anything that's buffered, and make sure anything else is flushed
1079 return io_new_fd($fd);
1081 elsif ($input->{file}) {
1082 my $fh = new IO::File($input->{file},"w+");
1084 $self->_set_error("Could not open file $input->{file}: $!");
1087 binmode($fh) or die;
1088 return (io_new_fd(fileno($fh)), $fh);
1090 elsif ($input->{data}) {
1091 return io_new_bufchain();
1093 elsif ($input->{callback} || $input->{writecb}) {
1094 if ($input->{maxbuffer}) {
1095 return io_new_cb($input->{callback} || $input->{writecb},
1097 $input->{seekcb}, $input->{closecb},
1098 $input->{maxbuffer});
1101 return io_new_cb($input->{callback} || $input->{writecb},
1103 $input->{seekcb}, $input->{closecb});
1107 $self->_set_error("file/fd/fh/data/callback parameter missing");
1112 # Read an image from file
1118 if (defined($self->{IMG})) {
1119 # let IIM_DESTROY do the destruction, since the image may be
1120 # referenced from elsewhere
1121 #i_img_destroy($self->{IMG});
1122 undef($self->{IMG});
1125 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1127 unless ($input{'type'}) {
1128 $input{'type'} = i_test_format_probe($IO, -1);
1131 unless ($input{'type'}) {
1132 $self->_set_error('type parameter missing and not possible to guess from extension');
1136 unless ($formats{$input{'type'}}) {
1137 $self->_set_error("format '$input{'type'}' not supported");
1142 if ( $input{'type'} eq 'jpeg' ) {
1143 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1144 if ( !defined($self->{IMG}) ) {
1145 $self->{ERRSTR}='unable to read jpeg image'; return undef;
1147 $self->{DEBUG} && print "loading a jpeg file\n";
1151 if ( $input{'type'} eq 'tiff' ) {
1152 $self->{IMG}=i_readtiff_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1153 if ( !defined($self->{IMG}) ) {
1154 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1156 $self->{DEBUG} && print "loading a tiff file\n";
1160 if ( $input{'type'} eq 'pnm' ) {
1161 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1162 if ( !defined($self->{IMG}) ) {
1163 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg(); return undef;
1165 $self->{DEBUG} && print "loading a pnm file\n";
1169 if ( $input{'type'} eq 'png' ) {
1170 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1171 if ( !defined($self->{IMG}) ) {
1172 $self->{ERRSTR}='unable to read png image';
1175 $self->{DEBUG} && print "loading a png file\n";
1178 if ( $input{'type'} eq 'bmp' ) {
1179 $self->{IMG}=i_readbmp_wiol( $IO );
1180 if ( !defined($self->{IMG}) ) {
1181 $self->{ERRSTR}=$self->_error_as_msg();
1184 $self->{DEBUG} && print "loading a bmp file\n";
1187 if ( $input{'type'} eq 'gif' ) {
1188 if ($input{colors} && !ref($input{colors})) {
1189 # must be a reference to a scalar that accepts the colour map
1190 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1193 if ($input{colors}) {
1195 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1197 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1201 $self->{IMG} =i_readgif_wiol( $IO );
1203 if ( !defined($self->{IMG}) ) {
1204 $self->{ERRSTR}=$self->_error_as_msg();
1207 $self->{DEBUG} && print "loading a gif file\n";
1210 if ( $input{'type'} eq 'tga' ) {
1211 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1212 if ( !defined($self->{IMG}) ) {
1213 $self->{ERRSTR}=$self->_error_as_msg();
1216 $self->{DEBUG} && print "loading a tga file\n";
1219 if ( $input{'type'} eq 'rgb' ) {
1220 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1221 if ( !defined($self->{IMG}) ) {
1222 $self->{ERRSTR}=$self->_error_as_msg();
1225 $self->{DEBUG} && print "loading a tga file\n";
1229 if ( $input{'type'} eq 'raw' ) {
1230 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1232 if ( !($params{xsize} && $params{ysize}) ) {
1233 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1237 $self->{IMG} = i_readraw_wiol( $IO,
1240 $params{datachannels},
1241 $params{storechannels},
1242 $params{interleave});
1243 if ( !defined($self->{IMG}) ) {
1244 $self->{ERRSTR}='unable to read raw image';
1247 $self->{DEBUG} && print "loading a raw file\n";
1253 sub _fix_gif_positions {
1254 my ($opts, $opt, $msg, @imgs) = @_;
1256 my $positions = $opts->{'gif_positions'};
1258 for my $pos (@$positions) {
1259 my ($x, $y) = @$pos;
1260 my $img = $imgs[$index++];
1261 $img->settag(name=>'gif_left', value=>$x);
1262 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1264 $$msg .= "replaced with the gif_left and gif_top tags";
1269 gif_each_palette=>'gif_local_map',
1270 interlace => 'gif_interlace',
1271 gif_delays => 'gif_delay',
1272 gif_positions => \&_fix_gif_positions,
1273 gif_loop_count => 'gif_loop',
1277 my ($self, $opts, $prefix, @imgs) = @_;
1279 for my $opt (keys %$opts) {
1281 if ($obsolete_opts{$opt}) {
1282 my $new = $obsolete_opts{$opt};
1283 my $msg = "Obsolete option $opt ";
1285 $new->($opts, $opt, \$msg, @imgs);
1288 $msg .= "replaced with the $new tag ";
1291 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1292 warn $msg if $warn_obsolete && $^W;
1294 next unless $tagname =~ /^\Q$prefix/;
1295 my $value = $opts->{$opt};
1297 if (UNIVERSAL::isa($value, "Imager::Color")) {
1298 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1299 for my $img (@imgs) {
1300 $img->settag(name=>$tagname, value=>$tag);
1303 elsif (ref($value) eq 'ARRAY') {
1304 for my $i (0..$#$value) {
1305 my $val = $value->[$i];
1307 if (UNIVERSAL::isa($val, "Imager::Color")) {
1308 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1310 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1313 $self->_set_error("Unknown reference type " . ref($value) .
1314 " supplied in array for $opt");
1320 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1325 $self->_set_error("Unknown reference type " . ref($value) .
1326 " supplied for $opt");
1331 # set it as a tag for every image
1332 for my $img (@imgs) {
1333 $img->settag(name=>$tagname, value=>$value);
1341 # Write an image to file
1344 my %input=(jpegquality=>75,
1354 $self->_set_opts(\%input, "i_", $self)
1357 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1359 if (!$input{'type'} and $input{file}) {
1360 $input{'type'}=$FORMATGUESS->($input{file});
1362 if (!$input{'type'}) {
1363 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1367 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1369 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1372 if ($input{'type'} eq 'tiff') {
1373 $self->_set_opts(\%input, "tiff_", $self)
1375 $self->_set_opts(\%input, "exif_", $self)
1378 if (defined $input{class} && $input{class} eq 'fax') {
1379 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1380 $self->{ERRSTR}='Could not write to buffer';
1384 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1385 $self->{ERRSTR}='Could not write to buffer';
1389 } elsif ( $input{'type'} eq 'pnm' ) {
1390 $self->_set_opts(\%input, "pnm_", $self)
1392 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1393 $self->{ERRSTR}='unable to write pnm image';
1396 $self->{DEBUG} && print "writing a pnm file\n";
1397 } elsif ( $input{'type'} eq 'raw' ) {
1398 $self->_set_opts(\%input, "raw_", $self)
1400 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1401 $self->{ERRSTR}='unable to write raw image';
1404 $self->{DEBUG} && print "writing a raw file\n";
1405 } elsif ( $input{'type'} eq 'png' ) {
1406 $self->_set_opts(\%input, "png_", $self)
1408 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1409 $self->{ERRSTR}='unable to write png image';
1412 $self->{DEBUG} && print "writing a png file\n";
1413 } elsif ( $input{'type'} eq 'jpeg' ) {
1414 $self->_set_opts(\%input, "jpeg_", $self)
1416 $self->_set_opts(\%input, "exif_", $self)
1418 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1419 $self->{ERRSTR} = $self->_error_as_msg();
1422 $self->{DEBUG} && print "writing a jpeg file\n";
1423 } elsif ( $input{'type'} eq 'bmp' ) {
1424 $self->_set_opts(\%input, "bmp_", $self)
1426 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1427 $self->{ERRSTR}='unable to write bmp image';
1430 $self->{DEBUG} && print "writing a bmp file\n";
1431 } elsif ( $input{'type'} eq 'tga' ) {
1432 $self->_set_opts(\%input, "tga_", $self)
1435 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1436 $self->{ERRSTR}=$self->_error_as_msg();
1439 $self->{DEBUG} && print "writing a tga file\n";
1440 } elsif ( $input{'type'} eq 'gif' ) {
1441 $self->_set_opts(\%input, "gif_", $self)
1443 # compatibility with the old interfaces
1444 if ($input{gifquant} eq 'lm') {
1445 $input{make_colors} = 'addi';
1446 $input{translate} = 'perturb';
1447 $input{perturb} = $input{lmdither};
1448 } elsif ($input{gifquant} eq 'gen') {
1449 # just pass options through
1451 $input{make_colors} = 'webmap'; # ignored
1452 $input{translate} = 'giflib';
1454 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1455 $self->{ERRSTR} = $self->_error_as_msg;
1460 if (exists $input{'data'}) {
1461 my $data = io_slurp($IO);
1463 $self->{ERRSTR}='Could not slurp from buffer';
1466 ${$input{data}} = $data;
1472 my ($class, $opts, @images) = @_;
1474 if (!$opts->{'type'} && $opts->{'file'}) {
1475 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1477 unless ($opts->{'type'}) {
1478 $class->_set_error('type parameter missing and not possible to guess from extension');
1481 # translate to ImgRaw
1482 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1483 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1486 $class->_set_opts($opts, "i_", @images)
1488 my @work = map $_->{IMG}, @images;
1489 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1491 if ($opts->{'type'} eq 'gif') {
1492 $class->_set_opts($opts, "gif_", @images)
1494 my $gif_delays = $opts->{gif_delays};
1495 local $opts->{gif_delays} = $gif_delays;
1496 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1497 # assume the caller wants the same delay for each frame
1498 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1500 my $res = i_writegif_wiol($IO, $opts, @work);
1501 $res or $class->_set_error($class->_error_as_msg());
1504 elsif ($opts->{'type'} eq 'tiff') {
1505 $class->_set_opts($opts, "tiff_", @images)
1507 $class->_set_opts($opts, "exif_", @images)
1510 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1511 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1512 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1515 $res = i_writetiff_multi_wiol($IO, @work);
1517 $res or $class->_set_error($class->_error_as_msg());
1521 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1526 # read multiple images from a file
1528 my ($class, %opts) = @_;
1530 if ($opts{file} && !exists $opts{'type'}) {
1532 my $type = $FORMATGUESS->($opts{file});
1533 $opts{'type'} = $type;
1535 unless ($opts{'type'}) {
1536 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1540 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1542 if ($opts{'type'} eq 'gif') {
1544 @imgs = i_readgif_multi_wiol($IO);
1547 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1551 $ERRSTR = _error_as_msg();
1555 elsif ($opts{'type'} eq 'tiff') {
1556 my @imgs = i_readtiff_multi_wiol($IO, -1);
1559 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1563 $ERRSTR = _error_as_msg();
1568 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1572 # Destroy an Imager object
1576 # delete $instances{$self};
1577 if (defined($self->{IMG})) {
1578 # the following is now handled by the XS DESTROY method for
1579 # Imager::ImgRaw object
1580 # Re-enabling this will break virtual images
1581 # tested for in t/t020masked.t
1582 # i_img_destroy($self->{IMG});
1583 undef($self->{IMG});
1585 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1589 # Perform an inplace filter of an image
1590 # that is the image will be overwritten with the data
1596 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1598 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1600 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1601 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1604 if ($filters{$input{'type'}}{names}) {
1605 my $names = $filters{$input{'type'}}{names};
1606 for my $name (keys %$names) {
1607 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1608 $input{$name} = $names->{$name}{$input{$name}};
1612 if (defined($filters{$input{'type'}}{defaults})) {
1613 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1615 %hsh=('image',$self->{IMG},%input);
1618 my @cs=@{$filters{$input{'type'}}{callseq}};
1621 if (!defined($hsh{$_})) {
1622 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1627 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1628 &{$filters{$input{'type'}}{callsub}}(%hsh);
1631 chomp($self->{ERRSTR} = $@);
1637 $self->{DEBUG} && print "callseq is: @cs\n";
1638 $self->{DEBUG} && print "matching callseq is: @b\n";
1643 # Scale an image to requested size and return the scaled version
1647 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1648 my $img = Imager->new();
1649 my $tmp = Imager->new();
1651 unless (defined wantarray) {
1652 my @caller = caller;
1653 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1657 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1659 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1660 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1661 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1662 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1663 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1664 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1666 if ($opts{qtype} eq 'normal') {
1667 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1668 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1669 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1670 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1673 if ($opts{'qtype'} eq 'preview') {
1674 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1675 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1678 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1681 # Scales only along the X axis
1685 my %opts=(scalefactor=>0.5,@_);
1687 unless (defined wantarray) {
1688 my @caller = caller;
1689 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1693 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1695 my $img = Imager->new();
1697 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1699 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1700 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1702 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1706 # Scales only along the Y axis
1710 my %opts=(scalefactor=>0.5,@_);
1712 unless (defined wantarray) {
1713 my @caller = caller;
1714 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1718 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1720 my $img = Imager->new();
1722 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1724 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1725 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1727 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1732 # Transform returns a spatial transformation of the input image
1733 # this moves pixels to a new location in the returned image.
1734 # NOTE - should make a utility function to check transforms for
1739 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1741 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1743 # print Dumper(\%opts);
1746 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1748 eval ("use Affix::Infix2Postfix;");
1751 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1754 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1755 {op=>'-',trans=>'Sub'},
1756 {op=>'*',trans=>'Mult'},
1757 {op=>'/',trans=>'Div'},
1758 {op=>'-','type'=>'unary',trans=>'u-'},
1760 {op=>'func','type'=>'unary'}],
1761 'grouping'=>[qw( \( \) )],
1762 'func'=>[qw( sin cos )],
1767 @xt=$I2P->translate($opts{'xexpr'});
1768 @yt=$I2P->translate($opts{'yexpr'});
1770 $numre=$I2P->{'numre'};
1773 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1774 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1775 @{$opts{'parm'}}=@pt;
1778 # print Dumper(\%opts);
1780 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1781 $self->{ERRSTR}='transform: no xopcodes given.';
1785 @op=@{$opts{'xopcodes'}};
1787 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1788 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1791 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1797 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1798 $self->{ERRSTR}='transform: no yopcodes given.';
1802 @op=@{$opts{'yopcodes'}};
1804 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1805 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1808 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1813 if ( !exists $opts{'parm'}) {
1814 $self->{ERRSTR}='transform: no parameter arg given.';
1818 # print Dumper(\@ropx);
1819 # print Dumper(\@ropy);
1820 # print Dumper(\@ropy);
1822 my $img = Imager->new();
1823 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1824 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1830 my ($opts, @imgs) = @_;
1832 require "Imager/Expr.pm";
1834 $opts->{variables} = [ qw(x y) ];
1835 my ($width, $height) = @{$opts}{qw(width height)};
1837 $width ||= $imgs[0]->getwidth();
1838 $height ||= $imgs[0]->getheight();
1840 for my $img (@imgs) {
1841 $opts->{constants}{"w$img_num"} = $img->getwidth();
1842 $opts->{constants}{"h$img_num"} = $img->getheight();
1843 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1844 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1849 $opts->{constants}{w} = $width;
1850 $opts->{constants}{cx} = $width/2;
1853 $Imager::ERRSTR = "No width supplied";
1857 $opts->{constants}{h} = $height;
1858 $opts->{constants}{cy} = $height/2;
1861 $Imager::ERRSTR = "No height supplied";
1864 my $code = Imager::Expr->new($opts);
1866 $Imager::ERRSTR = Imager::Expr::error();
1869 my $channels = $opts->{channels} || 3;
1870 unless ($channels >= 1 && $channels <= 4) {
1871 return Imager->_set_error("channels must be an integer between 1 and 4");
1874 my $img = Imager->new();
1875 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1876 $channels, $code->code(),
1877 $code->nregs(), $code->cregs(),
1878 [ map { $_->{IMG} } @imgs ]);
1879 if (!defined $img->{IMG}) {
1880 $Imager::ERRSTR = Imager->_error_as_msg();
1889 my %opts=(tx => 0,ty => 0, @_);
1891 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1892 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1894 %opts = (src_minx => 0,
1896 src_maxx => $opts{src}->getwidth(),
1897 src_maxy => $opts{src}->getheight(),
1900 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1901 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1902 $self->{ERRSTR} = $self->_error_as_msg();
1912 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
1914 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
1915 $dir = $xlate{$opts{'dir'}};
1916 return $self if i_flipxy($self->{IMG}, $dir);
1924 unless (defined wantarray) {
1925 my @caller = caller;
1926 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
1930 if (defined $opts{right}) {
1931 my $degrees = $opts{right};
1933 $degrees += 360 * int(((-$degrees)+360)/360);
1935 $degrees = $degrees % 360;
1936 if ($degrees == 0) {
1937 return $self->copy();
1939 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
1940 my $result = Imager->new();
1941 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
1945 $self->{ERRSTR} = $self->_error_as_msg();
1950 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
1954 elsif (defined $opts{radians} || defined $opts{degrees}) {
1955 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
1957 my $result = Imager->new;
1959 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
1962 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
1964 if ($result->{IMG}) {
1968 $self->{ERRSTR} = $self->_error_as_msg();
1973 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
1978 sub matrix_transform {
1982 unless (defined wantarray) {
1983 my @caller = caller;
1984 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
1988 if ($opts{matrix}) {
1989 my $xsize = $opts{xsize} || $self->getwidth;
1990 my $ysize = $opts{ysize} || $self->getheight;
1992 my $result = Imager->new;
1994 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1995 $opts{matrix}, $opts{back})
1999 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2007 $self->{ERRSTR} = "matrix parameter required";
2013 *yatf = \&matrix_transform;
2015 # These two are supported for legacy code only
2018 return Imager::Color->new(@_);
2022 return Imager::Color::set(@_);
2025 # Draws a box between the specified corner points.
2028 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2029 my $dflcl=i_color_new(255,255,255,255);
2030 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2032 if (exists $opts{'box'}) {
2033 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
2034 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
2035 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
2036 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
2039 if ($opts{filled}) {
2040 my $color = _color($opts{'color'});
2042 $self->{ERRSTR} = $Imager::ERRSTR;
2045 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2046 $opts{ymax}, $color);
2048 elsif ($opts{fill}) {
2049 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2050 # assume it's a hash ref
2051 require 'Imager/Fill.pm';
2052 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2053 $self->{ERRSTR} = $Imager::ERRSTR;
2057 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2058 $opts{ymax},$opts{fill}{fill});
2061 my $color = _color($opts{'color'});
2063 $self->{ERRSTR} = $Imager::ERRSTR;
2066 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2072 # Draws an arc - this routine SUCKS and is buggy - it sometimes doesn't work when the arc is a convex polygon
2076 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2077 my $dflcl=i_color_new(255,255,255,255);
2078 my %opts=(color=>$dflcl,
2079 'r'=>min($self->getwidth(),$self->getheight())/3,
2080 'x'=>$self->getwidth()/2,
2081 'y'=>$self->getheight()/2,
2082 'd1'=>0, 'd2'=>361, @_);
2084 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2085 # assume it's a hash ref
2086 require 'Imager/Fill.pm';
2087 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2088 $self->{ERRSTR} = $Imager::ERRSTR;
2092 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2093 $opts{'d2'}, $opts{fill}{fill});
2096 my $color = _color($opts{'color'});
2098 $self->{ERRSTR} = $Imager::ERRSTR;
2101 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2102 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2106 if ($opts{'d1'} <= $opts{'d2'}) {
2107 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2108 $opts{'d1'}, $opts{'d2'}, $color);
2111 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2112 $opts{'d1'}, 361, $color);
2113 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2114 0, $opts{'d2'}, $color);
2122 # Draws a line from one point to the other
2123 # the endpoint is set if the endp parameter is set which it is by default.
2124 # to turn of the endpoint being set use endp=>0 when calling line.
2128 my $dflcl=i_color_new(0,0,0,0);
2129 my %opts=(color=>$dflcl,
2132 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2134 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2135 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2137 my $color = _color($opts{'color'});
2139 $self->{ERRSTR} = $Imager::ERRSTR;
2143 $opts{antialias} = $opts{aa} if defined $opts{aa};
2144 if ($opts{antialias}) {
2145 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2146 $color, $opts{endp});
2148 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2149 $color, $opts{endp});
2154 # Draws a line between an ordered set of points - It more or less just transforms this
2155 # into a list of lines.
2159 my ($pt,$ls,@points);
2160 my $dflcl=i_color_new(0,0,0,0);
2161 my %opts=(color=>$dflcl,@_);
2163 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2165 if (exists($opts{points})) { @points=@{$opts{points}}; }
2166 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2167 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2170 # print Dumper(\@points);
2172 my $color = _color($opts{'color'});
2174 $self->{ERRSTR} = $Imager::ERRSTR;
2177 $opts{antialias} = $opts{aa} if defined $opts{aa};
2178 if ($opts{antialias}) {
2181 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2188 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2198 my ($pt,$ls,@points);
2199 my $dflcl = i_color_new(0,0,0,0);
2200 my %opts = (color=>$dflcl, @_);
2202 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2204 if (exists($opts{points})) {
2205 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2206 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2209 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2210 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2213 if ($opts{'fill'}) {
2214 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2215 # assume it's a hash ref
2216 require 'Imager/Fill.pm';
2217 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2218 $self->{ERRSTR} = $Imager::ERRSTR;
2222 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2223 $opts{'fill'}{'fill'});
2226 my $color = _color($opts{'color'});
2228 $self->{ERRSTR} = $Imager::ERRSTR;
2231 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2238 # this the multipoint bezier curve
2239 # this is here more for testing that actual usage since
2240 # this is not a good algorithm. Usually the curve would be
2241 # broken into smaller segments and each done individually.
2245 my ($pt,$ls,@points);
2246 my $dflcl=i_color_new(0,0,0,0);
2247 my %opts=(color=>$dflcl,@_);
2249 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2251 if (exists $opts{points}) {
2252 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2253 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2256 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2257 $self->{ERRSTR}='Missing or invalid points.';
2261 my $color = _color($opts{'color'});
2263 $self->{ERRSTR} = $Imager::ERRSTR;
2266 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2272 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2275 unless (exists $opts{'x'} && exists $opts{'y'}) {
2276 $self->{ERRSTR} = "missing seed x and y parameters";
2281 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2282 # assume it's a hash ref
2283 require 'Imager/Fill.pm';
2284 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2285 $self->{ERRSTR} = $Imager::ERRSTR;
2289 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2292 my $color = _color($opts{'color'});
2294 $self->{ERRSTR} = $Imager::ERRSTR;
2297 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2299 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2305 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2307 unless (exists $opts{'x'} && exists $opts{'y'}) {
2308 $self->{ERRSTR} = 'missing x and y parameters';
2314 my $color = _color($opts{color})
2316 if (ref $x && ref $y) {
2317 unless (@$x == @$y) {
2318 $self->{ERRSTR} = 'length of x and y mismatch';
2321 if ($color->isa('Imager::Color')) {
2322 for my $i (0..$#{$opts{'x'}}) {
2323 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2327 for my $i (0..$#{$opts{'x'}}) {
2328 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2333 if ($color->isa('Imager::Color')) {
2334 i_ppix($self->{IMG}, $x, $y, $color);
2337 i_ppixf($self->{IMG}, $x, $y, $color);
2347 my %opts = ( "type"=>'8bit', @_);
2349 unless (exists $opts{'x'} && exists $opts{'y'}) {
2350 $self->{ERRSTR} = 'missing x and y parameters';
2356 if (ref $x && ref $y) {
2357 unless (@$x == @$y) {
2358 $self->{ERRSTR} = 'length of x and y mismatch';
2362 if ($opts{"type"} eq '8bit') {
2363 for my $i (0..$#{$opts{'x'}}) {
2364 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2368 for my $i (0..$#{$opts{'x'}}) {
2369 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2372 return wantarray ? @result : \@result;
2375 if ($opts{"type"} eq '8bit') {
2376 return i_get_pixel($self->{IMG}, $x, $y);
2379 return i_gpixf($self->{IMG}, $x, $y);
2386 # make an identity matrix of the given size
2390 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2391 for my $c (0 .. ($size-1)) {
2392 $matrix->[$c][$c] = 1;
2397 # general function to convert an image
2399 my ($self, %opts) = @_;
2402 unless (defined wantarray) {
2403 my @caller = caller;
2404 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2408 # the user can either specify a matrix or preset
2409 # the matrix overrides the preset
2410 if (!exists($opts{matrix})) {
2411 unless (exists($opts{preset})) {
2412 $self->{ERRSTR} = "convert() needs a matrix or preset";
2416 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2417 # convert to greyscale, keeping the alpha channel if any
2418 if ($self->getchannels == 3) {
2419 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2421 elsif ($self->getchannels == 4) {
2422 # preserve the alpha channel
2423 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2428 $matrix = _identity($self->getchannels);
2431 elsif ($opts{preset} eq 'noalpha') {
2432 # strip the alpha channel
2433 if ($self->getchannels == 2 or $self->getchannels == 4) {
2434 $matrix = _identity($self->getchannels);
2435 pop(@$matrix); # lose the alpha entry
2438 $matrix = _identity($self->getchannels);
2441 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2443 $matrix = [ [ 1 ] ];
2445 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2446 $matrix = [ [ 0, 1 ] ];
2448 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2449 $matrix = [ [ 0, 0, 1 ] ];
2451 elsif ($opts{preset} eq 'alpha') {
2452 if ($self->getchannels == 2 or $self->getchannels == 4) {
2453 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2456 # the alpha is just 1 <shrug>
2457 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2460 elsif ($opts{preset} eq 'rgb') {
2461 if ($self->getchannels == 1) {
2462 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2464 elsif ($self->getchannels == 2) {
2465 # preserve the alpha channel
2466 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2469 $matrix = _identity($self->getchannels);
2472 elsif ($opts{preset} eq 'addalpha') {
2473 if ($self->getchannels == 1) {
2474 $matrix = _identity(2);
2476 elsif ($self->getchannels == 3) {
2477 $matrix = _identity(4);
2480 $matrix = _identity($self->getchannels);
2484 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2490 $matrix = $opts{matrix};
2493 my $new = Imager->new();
2494 $new->{IMG} = i_img_new();
2495 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2496 # most likely a bad matrix
2497 $self->{ERRSTR} = _error_as_msg();
2504 # general function to map an image through lookup tables
2507 my ($self, %opts) = @_;
2508 my @chlist = qw( red green blue alpha );
2510 if (!exists($opts{'maps'})) {
2511 # make maps from channel maps
2513 for $chnum (0..$#chlist) {
2514 if (exists $opts{$chlist[$chnum]}) {
2515 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2516 } elsif (exists $opts{'all'}) {
2517 $opts{'maps'}[$chnum] = $opts{'all'};
2521 if ($opts{'maps'} and $self->{IMG}) {
2522 i_map($self->{IMG}, $opts{'maps'} );
2528 my ($self, %opts) = @_;
2530 defined $opts{mindist} or $opts{mindist} = 0;
2532 defined $opts{other}
2533 or return $self->_set_error("No 'other' parameter supplied");
2534 defined $opts{other}{IMG}
2535 or return $self->_set_error("No image data in 'other' image");
2538 or return $self->_set_error("No image data");
2540 my $result = Imager->new;
2541 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2543 or return $self->_set_error($self->_error_as_msg());
2548 # destructive border - image is shrunk by one pixel all around
2551 my ($self,%opts)=@_;
2552 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2553 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2557 # Get the width of an image
2561 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2562 return (i_img_info($self->{IMG}))[0];
2565 # Get the height of an image
2569 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2570 return (i_img_info($self->{IMG}))[1];
2573 # Get number of channels in an image
2577 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2578 return i_img_getchannels($self->{IMG});
2585 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2586 return i_img_getmask($self->{IMG});
2594 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2595 i_img_setmask( $self->{IMG} , $opts{mask} );
2598 # Get number of colors in an image
2602 my %opts=('maxcolors'=>2**30,@_);
2603 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2604 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2605 return ($rc==-1? undef : $rc);
2608 # draw string to an image
2612 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2614 my %input=('x'=>0, 'y'=>0, @_);
2615 $input{string}||=$input{text};
2617 unless(exists $input{string}) {
2618 $self->{ERRSTR}="missing required parameter 'string'";
2622 unless($input{font}) {
2623 $self->{ERRSTR}="missing required parameter 'font'";
2627 unless ($input{font}->draw(image=>$self, %input)) {
2628 $self->{ERRSTR} = $self->_error_as_msg();
2635 # Shortcuts that can be exported
2637 sub newcolor { Imager::Color->new(@_); }
2638 sub newfont { Imager::Font->new(@_); }
2640 *NC=*newcolour=*newcolor;
2647 #### Utility routines
2650 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2654 my ($self, $msg) = @_;
2657 $self->{ERRSTR} = $msg;
2665 # Default guess for the type of an image from extension
2667 sub def_guess_type {
2670 $ext=($name =~ m/\.([^\.]+)$/)[0];
2671 return 'tiff' if ($ext =~ m/^tiff?$/);
2672 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2673 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2674 return 'png' if ($ext eq "png");
2675 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2676 return 'tga' if ($ext eq "tga");
2677 return 'rgb' if ($ext eq "rgb");
2678 return 'gif' if ($ext eq "gif");
2679 return 'raw' if ($ext eq "raw");
2683 # get the minimum of a list
2687 for(@_) { if ($_<$mx) { $mx=$_; }}
2691 # get the maximum of a list
2695 for(@_) { if ($_>$mx) { $mx=$_; }}
2699 # string stuff for iptc headers
2703 $str = substr($str,3);
2704 $str =~ s/[\n\r]//g;
2711 # A little hack to parse iptc headers.
2716 my($caption,$photogr,$headln,$credit);
2718 my $str=$self->{IPTCRAW};
2722 @ar=split(/8BIM/,$str);
2727 @sar=split(/\034\002/);
2728 foreach $item (@sar) {
2729 if ($item =~ m/^x/) {
2730 $caption=&clean($item);
2733 if ($item =~ m/^P/) {
2734 $photogr=&clean($item);
2737 if ($item =~ m/^i/) {
2738 $headln=&clean($item);
2741 if ($item =~ m/^n/) {
2742 $credit=&clean($item);
2748 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
2751 # Autoload methods go after =cut, and are processed by the autosplit program.
2755 # Below is the stub of documentation for your module. You better edit it!
2759 Imager - Perl extension for Generating 24 bit Images
2769 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
2774 my $img = Imager->new();
2775 # see Imager::Files for information on the read() method
2776 $img->read(file=>$file) or die $img->errstr();
2778 $file =~ s/\.[^.]*$//;
2780 # Create smaller version
2781 # documented in Imager::Transformations
2782 my $thumb = $img->scale(scalefactor=>.3);
2784 # Autostretch individual channels
2785 $thumb->filter(type=>'autolevels');
2787 # try to save in one of these formats
2790 for $format ( qw( png gif jpg tiff ppm ) ) {
2791 # Check if given format is supported
2792 if ($Imager::formats{$format}) {
2793 $file.="_low.$format";
2794 print "Storing image as: $file\n";
2795 # documented in Imager::Files
2796 $thumb->write(file=>$file) or
2804 Imager is a module for creating and altering images. It can read and
2805 write various image formats, draw primitive shapes like lines,and
2806 polygons, blend multiple images together in various ways, scale, crop,
2807 render text and more.
2809 =head2 Overview of documentation
2815 Imager - This document - Synopsis Example, Table of Contents and
2820 L<Imager::Cookbook> - how to do various things with Imager.
2824 L<Imager::ImageTypes> - Basics of constructing image objects with
2825 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
2826 8/16/double bits/channel, color maps, channel masks, image tags, color
2827 quantization. Also discusses basic image information methods.
2831 L<Imager::Files> - IO interaction, reading/writing images, format
2836 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
2841 L<Imager::Color> - Color specification.
2845 L<Imager::Fill> - Fill pattern specification.
2849 L<Imager::Font> - General font rendering, bounding boxes and font
2854 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
2855 blending, pasting, convert and map.
2859 L<Imager::Engines> - Programmable transformations through
2860 C<transform()>, C<transform2()> and C<matrix_transform()>.
2864 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
2869 L<Imager::Expr> - Expressions for evaluation engine used by
2874 L<Imager::Matrix2d> - Helper class for affine transformations.
2878 L<Imager::Fountain> - Helper for making gradient profiles.
2882 =head2 Basic Overview
2884 An Image object is created with C<$img = Imager-E<gt>new()>.
2887 $img=Imager->new(); # create empty image
2888 $img->read(file=>'lena.png',type=>'png') or # read image from file
2889 die $img->errstr(); # give an explanation
2890 # if something failed
2892 or if you want to create an empty image:
2894 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
2896 This example creates a completely black image of width 400 and height
2899 When an operation fails which can be directly associated with an image
2900 the error message is stored can be retrieved with
2901 C<$img-E<gt>errstr()>.
2903 In cases where no image object is associated with an operation
2904 C<$Imager::ERRSTR> is used to report errors not directly associated
2905 with an image object. You can also call C<Imager->errstr> to get this
2908 The C<Imager-E<gt>new> method is described in detail in
2909 L<Imager::ImageTypes>.
2913 Where to find information on methods for Imager class objects.
2915 addcolors() - L<Imager::ImageTypes>
2917 addtag() - L<Imager::ImageTypes> - add image tags
2919 arc() - L<Imager::Draw/arc>
2921 bits() - L<Imager::ImageTypes> - number of bits per sample for the
2924 box() - L<Imager::Draw/box>
2926 circle() - L<Imager::Draw/circle>
2928 convert() - L<Imager::Transformations/"Color transformations"> -
2929 transform the color space
2931 copy() - L<Imager::Transformations/copy>
2933 crop() - L<Imager::Transformations/crop> - extract part of an image
2935 deltag() - L<Imager::ImageTypes> - delete image tags
2937 difference() - L<Imager::Filters/"Image Difference">
2939 errstr() - L<Imager/"Basic Overview">
2941 filter() - L<Imager::Filters>
2943 findcolor() - L<Imager::ImageTypes> - search the image palette, if it
2946 flip() - L<Imager::Transformations/flip>
2948 flood_fill() - L<Imager::Draw/flood_fill>
2950 getchannels() - L<Imager::ImageTypes>
2952 getcolorcount() - L<Imager::ImageTypes>
2954 getcolors() - L<Imager::ImageTypes> - get colors from the image
2955 palette, if it has one
2957 getheight() - L<Imager::ImageTypes>
2959 getpixel() - L<Imager::Draw/setpixel and getpixel>
2961 getwidth() - L<Imager::ImageTypes>
2963 img_set() - L<Imager::ImageTypes>
2965 line() - L<Imager::Draw/line>
2967 map() - L<Imager::Transformations/"Color Mappings"> - remap color
2970 masked() - L<Imager::ImageTypes> - make a masked image
2972 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
2974 new() - L<Imager::ImageTypes>
2976 open() - L<Imager::Files> - an alias for read()
2978 paste() - L<Imager::Transformations/paste> - draw an image onto an image
2980 polygon() - L<Imager::Draw/polygon>
2982 polyline() - L<Imager::Draw/polyline>
2984 read() - L<Imager::Files> - read a single image from an image file
2986 read_multi() - L<Imager::Files> - read multiple images from an image
2989 rotate() - L<Imager::Transformations/rotate>
2991 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
2992 image and use the alpha channel
2994 scale() - L<Imager::Transformations/scale>
2996 scaleX() - L<Imager::Transformations/scaleX>
2998 scaleY() - L<Imager::Transformations/scaleY>
3000 setcolors() - L<Imager::ImageTypes> - set palette colors in a paletted image
3002 setpixel() - L<Imager::Draw/setpixel and getpixel>
3004 string() - L<Imager::Font/string> - draw text on an image
3006 tags() - L<Imager::ImageTypes> - fetch image tags
3008 to_paletted() - L<Imager::ImageTypes>
3010 to_rgb8() - L<Imager::ImageTypes>
3012 transform() - L<Imager::Engines/"transform">
3014 transform2() - L<Imager::Engines/"transform2">
3016 type() - L<Imager::ImageTypes> - type of image (direct vs paletted)
3018 virtual() - L<Imager::ImageTypes> - whether the image has it's own
3021 write() - L<Imager::Files> - write an image to a file
3023 write_multi() - L<Imager::Files> - write multiple image to an image
3026 =head1 CONCEPT INDEX
3028 animated GIF - L<Imager::File/"Writing an animated GIF">
3030 aspect ratio - L<Imager::ImageTypes/i_xres>,
3031 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3033 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3035 boxes, drawing - L<Imager::Draw/box>
3037 color - L<Imager::Color>
3039 color names - L<Imager::Color>, L<Imager::Color::Table>
3041 combine modes - L<Imager::Fill/combine>
3043 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3045 convolution - L<Imager::Filter/conv>
3047 cropping - L<Imager::Transformations/crop>
3049 dpi - L<Imager::ImageTypes/i_xres>
3051 drawing boxes - L<Imager::Draw/box>
3053 drawing lines - L<Imager::Draw/line>
3055 drawing text - L<Imager::Font/string>
3057 error message - L<Imager/"Basic Overview">
3059 files, font - L<Imager::Font>
3061 files, image - L<Imager::Files>
3063 filling, types of fill - L<Imager::Fill>
3065 filling, boxes - L<Imager::Draw/box>
3067 filling, flood fill - L<Imager::Draw/flood_fill>
3069 flood fill - L<Imager::Draw/flood_fill>
3071 fonts - L<Imager::Font>
3073 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3074 L<Imager::Font::Wrap>
3076 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3078 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3080 fountain fill - L<Imager::Fill/"Fountain fills">,
3081 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3082 L<Imager::Filters/gradgen>
3084 GIF files - L<Imager::Files/"GIF">
3086 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3088 gradient fill - L<Imager::Fill/"Fountain fills">,
3089 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3090 L<Imager::Filters/gradgen>
3092 guassian blur - L<Imager::Filter/guassian>
3094 hatch fills - L<Imager::Fill/"Hatched fills">
3096 invert image - L<Imager::Filter/hardinvert>
3098 JPEG - L<Imager::Files/"JPEG">
3100 lines, drawing - L<Imager::Draw/line>
3102 matrix - L<Imager::Matrix2d>,
3103 L<Imager::Transformations/"Matrix Transformations">,
3104 L<Imager::Font/transform>
3106 metadata, image - L<Imager::ImageTypes/"Tags">
3108 mosaic - L<Imager::Filter/mosaic>
3110 noise, filter - L<Imager::Filter/noise>
3112 noise, rendered - L<Imager::Filter/turbnoise>,
3113 L<Imager::Filter/radnoise>
3115 posterize - L<Imager::Filter/postlevels>
3117 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3119 pnm - L<Imager::Files/"PNM (Portable aNy Map">
3121 rectangles, drawing - L<Imager::Draw/box>
3123 resizing an image - L<Imager::Transformations/scale>,
3124 L<Imager::Transformations/crop>
3126 saving an image - L<Imager::Files>
3128 scaling - L<Imager::Transformations/scale>
3130 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3132 size, image - L<Imager::ImageTypes/getwidth>,
3133 L<Imager::ImageTypes/getheight>
3135 size, text - L<Imager::Font/bounding_box>
3137 text, drawing - L<Imager::Font/string>, L<Imager::Font/align>,
3138 L<Imager::Font::Wrap>
3140 text, wrapping text in an area - L<Imager::Font::Wrap>
3142 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3144 tiles, color - L<Imager::Filter/mosaic>
3146 unsharp mask - L<Imager::Filter/unsharpmask>
3148 watermark - L<Imager::Filter/watermark>
3150 writing an image - L<Imager::Files>
3154 You can ask for help, report bugs or express your undying love for
3155 Imager on the Imager-devel mailing list.
3157 To subscribe send a message with C<subscribe> in the body to:
3159 imager-devel+request@molar.is
3163 http://www.molar.is/en/lists/imager-devel/
3164 (annonymous is temporarily off due to spam)
3166 where you can also find the mailing list archive.
3168 If you're into IRC, you can typically find the developers in #Imager
3169 on irc.perl.org. As with any IRC channel, the participants could be
3170 occupied or asleep, so please be patient.
3172 You can report bugs either by sending email to:
3174 bug-Imager@rt.cpan.org
3176 or by pointing your browser at:
3178 https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager
3180 Please remember to include the versions of Imager, perl, supporting
3181 libraries, and any relevant code. If you have specific images that
3182 cause the problems, please include those too.
3186 Bugs are listed individually for relevant pod pages.
3190 Arnar M. Hrafnkelsson (addi@imager.perl.org) and Tony Cook
3191 (tony@imager.perl.org) See the README for a complete list.
3195 perl(1), Imager::ImageTypes(3), Imager::Files(3), Imager::Draw(3),
3196 Imager::Color(3), Imager::Fill(3), Imager::Font(3),
3197 Imager::Transformations(3), Imager::Engines(3), Imager::Filters(3),
3198 Imager::Expr(3), Imager::Matrix2d(3), Imager::Fountain(3)
3200 Affix::Infix2Postfix(3), Parse::RecDescent(3)
3201 http://imager.perl.org/