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
150 $VERSION = '0.43_02';
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}); }
225 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
227 callsub => sub { my %hsh=@_; i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, $hsh{colors}, $hsh{dist}); }
230 $filters{nearest_color} ={
231 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
233 callsub => sub { my %hsh=@_; i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, $hsh{colors}, $hsh{dist}); }
235 $filters{gaussian} = {
236 callseq => [ 'image', 'stddev' ],
238 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
242 callseq => [ qw(image size) ],
243 defaults => { size => 20 },
244 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
248 callseq => [ qw(image bump elevation lightx lighty st) ],
249 defaults => { elevation=>0, st=> 2 },
252 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
253 $hsh{lightx}, $hsh{lighty}, $hsh{st});
256 $filters{bumpmap_complex} =
258 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
269 Ia => Imager::Color->new(rgb=>[0,0,0]),
270 Il => Imager::Color->new(rgb=>[255,255,255]),
271 Is => Imager::Color->new(rgb=>[255,255,255]),
275 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
276 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
277 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
281 $filters{postlevels} =
283 callseq => [ qw(image levels) ],
284 defaults => { levels => 10 },
285 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
287 $filters{watermark} =
289 callseq => [ qw(image wmark tx ty pixdiff) ],
290 defaults => { pixdiff=>10, tx=>0, ty=>0 },
294 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
300 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
302 ftype => { linear => 0,
308 repeat => { none => 0,
323 multiply => 2, mult => 2,
326 subtract => 5, 'sub' => 5,
336 defaults => { ftype => 0, repeat => 0, combine => 0,
337 super_sample => 0, ssample_param => 4,
340 Imager::Color->new(0,0,0),
341 Imager::Color->new(255, 255, 255),
349 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
350 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
351 $hsh{ssample_param}, $hsh{segments});
354 $filters{unsharpmask} =
356 callseq => [ qw(image stddev scale) ],
357 defaults => { stddev=>2.0, scale=>1.0 },
361 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
365 $FORMATGUESS=\&def_guess_type;
375 # NOTE: this might be moved to an import override later on
379 # (look through @_ for special tags, process, and remove them);
381 # print Dumper($pack);
386 m_init_log($_[0],$_[1]);
387 log_entry("Imager $VERSION starting\n", 1);
392 my %parms=(loglevel=>1,@_);
394 init_log($parms{'log'},$parms{'loglevel'});
397 if (exists $parms{'warn_obsolete'}) {
398 $warn_obsolete = $parms{'warn_obsolete'};
401 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
402 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
406 if (exists $parms{'t1log'}) {
407 i_init_fonts($parms{'t1log'});
413 print "shutdown code\n";
414 # for(keys %instances) { $instances{$_}->DESTROY(); }
415 malloc_state(); # how do decide if this should be used? -- store something from the import
416 print "Imager exiting\n";
420 # Load a filter plugin
425 my ($DSO_handle,$str)=DSO_open($filename);
426 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
427 my %funcs=DSO_funclist($DSO_handle);
428 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
430 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
432 $DSOs{$filename}=[$DSO_handle,\%funcs];
435 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
436 $DEBUG && print "eval string:\n",$evstr,"\n";
448 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
449 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
450 for(keys %{$funcref}) {
452 $DEBUG && print "unloading: $_\n";
454 my $rc=DSO_close($DSO_handle);
455 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
459 # take the results of i_error() and make a message out of it
461 return join(": ", map $_->[0], i_errors());
464 # this function tries to DWIM for color parameters
465 # color objects are used as is
466 # simple scalars are simply treated as single parameters to Imager::Color->new
467 # hashrefs are treated as named argument lists to Imager::Color->new
468 # arrayrefs are treated as list arguments to Imager::Color->new iff any
470 # other arrayrefs are treated as list arguments to Imager::Color::Float
474 # perl 5.6.0 seems to do weird things to $arg if we don't make an
475 # explicitly stringified copy
476 # I vaguely remember a bug on this on p5p, but couldn't find it
477 # through bugs.perl.org (I had trouble getting it to find any bugs)
478 my $copy = $arg . "";
482 if (UNIVERSAL::isa($arg, "Imager::Color")
483 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
487 if ($copy =~ /^HASH\(/) {
488 $result = Imager::Color->new(%$arg);
490 elsif ($copy =~ /^ARRAY\(/) {
491 if (grep $_ > 1, @$arg) {
492 $result = Imager::Color->new(@$arg);
495 $result = Imager::Color::Float->new(@$arg);
499 $Imager::ERRSTR = "Not a color";
504 # assume Imager::Color::new knows how to handle it
505 $result = Imager::Color->new($arg);
513 # Methods to be called on objects.
516 # Create a new Imager object takes very few parameters.
517 # usually you call this method and then call open from
518 # the resulting object
525 $self->{IMG}=undef; # Just to indicate what exists
526 $self->{ERRSTR}=undef; #
527 $self->{DEBUG}=$DEBUG;
528 $self->{DEBUG} && print "Initialized Imager\n";
529 if (defined $hsh{xsize} && defined $hsh{ysize}) {
530 unless ($self->img_set(%hsh)) {
531 $Imager::ERRSTR = $self->{ERRSTR};
538 # Copy an entire image with no changes
539 # - if an image has magic the copy of it will not be magical
543 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
545 my $newcopy=Imager->new();
546 $newcopy->{IMG}=i_img_new();
547 i_copy($newcopy->{IMG},$self->{IMG});
555 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
556 my %input=(left=>0, top=>0, @_);
557 unless($input{img}) {
558 $self->{ERRSTR}="no source image";
561 $input{left}=0 if $input{left} <= 0;
562 $input{top}=0 if $input{top} <= 0;
564 my($r,$b)=i_img_info($src->{IMG});
566 i_copyto($self->{IMG}, $src->{IMG},
567 0,0, $r, $b, $input{left}, $input{top});
568 return $self; # What should go here??
571 # Crop an image - i.e. return a new image that is smaller
575 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
580 my ($w, $h, $l, $r, $b, $t) =
581 @hsh{qw(width height left right bottom top)};
583 # work through the various possibilities
588 elsif (!defined $r) {
589 $r = $self->getwidth;
601 $l = int(0.5+($self->getwidth()-$w)/2);
606 $r = $self->getwidth;
612 elsif (!defined $b) {
613 $b = $self->getheight;
625 $t=int(0.5+($self->getheight()-$h)/2);
630 $b = $self->getheight;
633 ($l,$r)=($r,$l) if $l>$r;
634 ($t,$b)=($b,$t) if $t>$b;
637 $r > $self->getwidth and $r = $self->getwidth;
639 $b > $self->getheight and $b = $self->getheight;
641 if ($l == $r || $t == $b) {
642 $self->_set_error("resulting image would have no content");
646 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
648 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
653 my ($self, %opts) = @_;
655 $self->{IMG} or return $self->_set_error("Not a valid image");
657 my $x = $opts{xsize} || $self->getwidth;
658 my $y = $opts{ysize} || $self->getheight;
659 my $channels = $opts{channels} || $self->getchannels;
661 my $out = Imager->new;
662 if ($channels == $self->getchannels) {
663 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
666 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
668 unless ($out->{IMG}) {
669 $self->{ERRSTR} = $self->_error_as_msg;
676 # Sets an image to a certain size and channel number
677 # if there was previously data in the image it is discarded
682 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
684 if (defined($self->{IMG})) {
685 # let IIM_DESTROY destroy it, it's possible this image is
686 # referenced from a virtual image (like masked)
687 #i_img_destroy($self->{IMG});
691 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
692 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
693 $hsh{maxcolors} || 256);
695 elsif ($hsh{bits} eq 'double') {
696 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
698 elsif ($hsh{bits} == 16) {
699 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
702 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
706 unless ($self->{IMG}) {
707 $self->{ERRSTR} = Imager->_error_as_msg();
714 # created a masked version of the current image
718 $self or return undef;
719 my %opts = (left => 0,
721 right => $self->getwidth,
722 bottom => $self->getheight,
724 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
726 my $result = Imager->new;
727 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
728 $opts{top}, $opts{right} - $opts{left},
729 $opts{bottom} - $opts{top});
730 # keep references to the mask and base images so they don't
732 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
737 # convert an RGB image into a paletted image
741 if (@_ != 1 && !ref $_[0]) {
748 my $result = Imager->new;
749 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
751 #print "Type ", i_img_type($result->{IMG}), "\n";
753 if ($result->{IMG}) {
757 $self->{ERRSTR} = $self->_error_as_msg;
762 # convert a paletted (or any image) to an 8-bit/channel RGB images
768 $result = Imager->new;
769 $result->{IMG} = i_img_to_rgb($self->{IMG})
778 my %opts = (colors=>[], @_);
780 @{$opts{colors}} or return undef;
782 $self->{IMG} and i_addcolors($self->{IMG}, @{$opts{colors}});
787 my %opts = (start=>0, colors=>[], @_);
788 @{$opts{colors}} or return undef;
790 $self->{IMG} and i_setcolors($self->{IMG}, $opts{start}, @{$opts{colors}});
796 if (!exists $opts{start} && !exists $opts{count}) {
799 $opts{count} = $self->colorcount;
801 elsif (!exists $opts{count}) {
804 elsif (!exists $opts{start}) {
809 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
813 i_colorcount($_[0]{IMG});
817 i_maxcolors($_[0]{IMG});
823 $opts{color} or return undef;
825 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
830 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
831 if ($bits && $bits == length(pack("d", 1)) * 8) {
840 return i_img_type($self->{IMG}) ? "paletted" : "direct";
846 $self->{IMG} and i_img_virtual($self->{IMG});
850 my ($self, %opts) = @_;
852 $self->{IMG} or return;
854 if (defined $opts{name}) {
858 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
859 push @result, (i_tags_get($self->{IMG}, $found))[1];
862 return wantarray ? @result : $result[0];
864 elsif (defined $opts{code}) {
868 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
869 push @result, (i_tags_get($self->{IMG}, $found))[1];
876 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
879 return i_tags_count($self->{IMG});
888 return -1 unless $self->{IMG};
890 if (defined $opts{value}) {
891 if ($opts{value} =~ /^\d+$/) {
893 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
896 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
899 elsif (defined $opts{data}) {
900 # force addition as a string
901 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
904 $self->{ERRSTR} = "No value supplied";
908 elsif ($opts{code}) {
909 if (defined $opts{value}) {
910 if ($opts{value} =~ /^\d+$/) {
912 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
915 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
918 elsif (defined $opts{data}) {
919 # force addition as a string
920 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
923 $self->{ERRSTR} = "No value supplied";
936 return 0 unless $self->{IMG};
938 if (defined $opts{'index'}) {
939 return i_tags_delete($self->{IMG}, $opts{'index'});
941 elsif (defined $opts{name}) {
942 return i_tags_delbyname($self->{IMG}, $opts{name});
944 elsif (defined $opts{code}) {
945 return i_tags_delbycode($self->{IMG}, $opts{code});
948 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
954 my ($self, %opts) = @_;
957 $self->deltag(name=>$opts{name});
958 return $self->addtag(name=>$opts{name}, value=>$opts{value});
960 elsif (defined $opts{code}) {
961 $self->deltag(code=>$opts{code});
962 return $self->addtag(code=>$opts{code}, value=>$opts{value});
971 my ($self, $input) = @_;
974 return $input->{io}, undef;
976 elsif ($input->{fd}) {
977 return io_new_fd($input->{fd});
979 elsif ($input->{fh}) {
980 my $fd = fileno($input->{fh});
982 $self->_set_error("Handle in fh option not opened");
985 return io_new_fd($fd);
987 elsif ($input->{file}) {
988 my $file = IO::File->new($input->{file}, "r");
990 $self->_set_error("Could not open $input->{file}: $!");
994 return (io_new_fd(fileno($file)), $file);
996 elsif ($input->{data}) {
997 return io_new_buffer($input->{data});
999 elsif ($input->{callback} || $input->{readcb}) {
1000 if (!$input->{seekcb}) {
1001 $self->_set_error("Need a seekcb parameter");
1003 if ($input->{maxbuffer}) {
1004 return io_new_cb($input->{writecb},
1005 $input->{callback} || $input->{readcb},
1006 $input->{seekcb}, $input->{closecb},
1007 $input->{maxbuffer});
1010 return io_new_cb($input->{writecb},
1011 $input->{callback} || $input->{readcb},
1012 $input->{seekcb}, $input->{closecb});
1016 $self->_set_error("file/fd/fh/data/callback parameter missing");
1021 sub _get_writer_io {
1022 my ($self, $input, $type) = @_;
1025 return io_new_fd($input->{fd});
1027 elsif ($input->{fh}) {
1028 my $fd = fileno($input->{fh});
1030 $self->_set_error("Handle in fh option not opened");
1034 my $oldfh = select($input->{fh});
1035 # flush anything that's buffered, and make sure anything else is flushed
1038 return io_new_fd($fd);
1040 elsif ($input->{file}) {
1041 my $fh = new IO::File($input->{file},"w+");
1043 $self->_set_error("Could not open file $input->{file}: $!");
1046 binmode($fh) or die;
1047 return (io_new_fd(fileno($fh)), $fh);
1049 elsif ($input->{data}) {
1050 return io_new_bufchain();
1052 elsif ($input->{callback} || $input->{writecb}) {
1053 if ($input->{maxbuffer}) {
1054 return io_new_cb($input->{callback} || $input->{writecb},
1056 $input->{seekcb}, $input->{closecb},
1057 $input->{maxbuffer});
1060 return io_new_cb($input->{callback} || $input->{writecb},
1062 $input->{seekcb}, $input->{closecb});
1066 $self->_set_error("file/fd/fh/data/callback parameter missing");
1071 # Read an image from file
1077 if (defined($self->{IMG})) {
1078 # let IIM_DESTROY do the destruction, since the image may be
1079 # referenced from elsewhere
1080 #i_img_destroy($self->{IMG});
1081 undef($self->{IMG});
1084 # FIXME: Find the format here if not specified
1085 # yes the code isn't here yet - next week maybe?
1086 # Next week? Are you high or something? That comment
1087 # has been there for half a year dude.
1088 # Look, i just work here, ok?
1090 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1092 unless ($input{'type'}) {
1093 $input{'type'} = i_test_format_probe($IO, -1);
1096 unless ($input{'type'}) {
1097 $self->_set_error('type parameter missing and not possible to guess from extension');
1102 if ( $input{'type'} eq 'jpeg' ) {
1103 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1104 if ( !defined($self->{IMG}) ) {
1105 $self->{ERRSTR}='unable to read jpeg image'; return undef;
1107 $self->{DEBUG} && print "loading a jpeg file\n";
1111 if ( $input{'type'} eq 'tiff' ) {
1112 $self->{IMG}=i_readtiff_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1113 if ( !defined($self->{IMG}) ) {
1114 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1116 $self->{DEBUG} && print "loading a tiff file\n";
1120 if ( $input{'type'} eq 'pnm' ) {
1121 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1122 if ( !defined($self->{IMG}) ) {
1123 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg(); return undef;
1125 $self->{DEBUG} && print "loading a pnm file\n";
1129 if ( $input{'type'} eq 'png' ) {
1130 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1131 if ( !defined($self->{IMG}) ) {
1132 $self->{ERRSTR}='unable to read png image';
1135 $self->{DEBUG} && print "loading a png file\n";
1138 if ( $input{'type'} eq 'bmp' ) {
1139 $self->{IMG}=i_readbmp_wiol( $IO );
1140 if ( !defined($self->{IMG}) ) {
1141 $self->{ERRSTR}=$self->_error_as_msg();
1144 $self->{DEBUG} && print "loading a bmp file\n";
1147 if ( $input{'type'} eq 'gif' ) {
1148 if ($input{colors} && !ref($input{colors})) {
1149 # must be a reference to a scalar that accepts the colour map
1150 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1153 if ($input{colors}) {
1155 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1157 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1161 $self->{IMG} =i_readgif_wiol( $IO );
1163 if ( !defined($self->{IMG}) ) {
1164 $self->{ERRSTR}=$self->_error_as_msg();
1167 $self->{DEBUG} && print "loading a gif file\n";
1170 if ( $input{'type'} eq 'tga' ) {
1171 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1172 if ( !defined($self->{IMG}) ) {
1173 $self->{ERRSTR}=$self->_error_as_msg();
1176 $self->{DEBUG} && print "loading a tga file\n";
1179 if ( $input{'type'} eq 'rgb' ) {
1180 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1181 if ( !defined($self->{IMG}) ) {
1182 $self->{ERRSTR}=$self->_error_as_msg();
1185 $self->{DEBUG} && print "loading a tga file\n";
1189 if ( $input{'type'} eq 'raw' ) {
1190 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1192 if ( !($params{xsize} && $params{ysize}) ) {
1193 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1197 $self->{IMG} = i_readraw_wiol( $IO,
1200 $params{datachannels},
1201 $params{storechannels},
1202 $params{interleave});
1203 if ( !defined($self->{IMG}) ) {
1204 $self->{ERRSTR}='unable to read raw image';
1207 $self->{DEBUG} && print "loading a raw file\n";
1213 sub _fix_gif_positions {
1214 my ($opts, $opt, $msg, @imgs) = @_;
1216 my $positions = $opts->{'gif_positions'};
1218 for my $pos (@$positions) {
1219 my ($x, $y) = @$pos;
1220 my $img = $imgs[$index++];
1221 $img->settag(name=>'gif_left', value=>$x);
1222 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1224 $$msg .= "replaced with the gif_left and gif_top tags";
1229 gif_each_palette=>'gif_local_map',
1230 interlace => 'gif_interlace',
1231 gif_delays => 'gif_delay',
1232 gif_positions => \&_fix_gif_positions,
1233 gif_loop_count => 'gif_loop',
1237 my ($self, $opts, $prefix, @imgs) = @_;
1239 for my $opt (keys %$opts) {
1241 if ($obsolete_opts{$opt}) {
1242 my $new = $obsolete_opts{$opt};
1243 my $msg = "Obsolete option $opt ";
1245 $new->($opts, $opt, \$msg, @imgs);
1248 $msg .= "replaced with the $new tag ";
1251 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1252 warn $msg if $warn_obsolete && $^W;
1254 next unless $tagname =~ /^\Q$prefix/;
1255 my $value = $opts->{$opt};
1257 if (UNIVERSAL::isa($value, "Imager::Color")) {
1258 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1259 for my $img (@imgs) {
1260 $img->settag(name=>$tagname, value=>$tag);
1263 elsif (ref($value) eq 'ARRAY') {
1264 for my $i (0..$#$value) {
1265 my $val = $value->[$i];
1267 if (UNIVERSAL::isa($val, "Imager::Color")) {
1268 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1270 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1273 $self->_set_error("Unknown reference type " . ref($value) .
1274 " supplied in array for $opt");
1280 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1285 $self->_set_error("Unknown reference type " . ref($value) .
1286 " supplied for $opt");
1291 # set it as a tag for every image
1292 for my $img (@imgs) {
1293 $img->settag(name=>$tagname, value=>$value);
1301 # Write an image to file
1304 my %input=(jpegquality=>75,
1314 $self->_set_opts(\%input, "i_", $self)
1317 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1319 if (!$input{'type'} and $input{file}) {
1320 $input{'type'}=$FORMATGUESS->($input{file});
1322 if (!$input{'type'}) {
1323 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1327 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1329 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1332 if ($input{'type'} eq 'tiff') {
1333 $self->_set_opts(\%input, "tiff_", $self)
1335 $self->_set_opts(\%input, "exif_", $self)
1338 if (defined $input{class} && $input{class} eq 'fax') {
1339 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1340 $self->{ERRSTR}='Could not write to buffer';
1344 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1345 $self->{ERRSTR}='Could not write to buffer';
1349 } elsif ( $input{'type'} eq 'pnm' ) {
1350 $self->_set_opts(\%input, "pnm_", $self)
1352 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1353 $self->{ERRSTR}='unable to write pnm image';
1356 $self->{DEBUG} && print "writing a pnm file\n";
1357 } elsif ( $input{'type'} eq 'raw' ) {
1358 $self->_set_opts(\%input, "raw_", $self)
1360 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1361 $self->{ERRSTR}='unable to write raw image';
1364 $self->{DEBUG} && print "writing a raw file\n";
1365 } elsif ( $input{'type'} eq 'png' ) {
1366 $self->_set_opts(\%input, "png_", $self)
1368 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1369 $self->{ERRSTR}='unable to write png image';
1372 $self->{DEBUG} && print "writing a png file\n";
1373 } elsif ( $input{'type'} eq 'jpeg' ) {
1374 $self->_set_opts(\%input, "jpeg_", $self)
1376 $self->_set_opts(\%input, "exif_", $self)
1378 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1379 $self->{ERRSTR} = $self->_error_as_msg();
1382 $self->{DEBUG} && print "writing a jpeg file\n";
1383 } elsif ( $input{'type'} eq 'bmp' ) {
1384 $self->_set_opts(\%input, "bmp_", $self)
1386 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1387 $self->{ERRSTR}='unable to write bmp image';
1390 $self->{DEBUG} && print "writing a bmp file\n";
1391 } elsif ( $input{'type'} eq 'tga' ) {
1392 $self->_set_opts(\%input, "tga_", $self)
1395 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1396 $self->{ERRSTR}=$self->_error_as_msg();
1399 $self->{DEBUG} && print "writing a tga file\n";
1400 } elsif ( $input{'type'} eq 'gif' ) {
1401 $self->_set_opts(\%input, "gif_", $self)
1403 # compatibility with the old interfaces
1404 if ($input{gifquant} eq 'lm') {
1405 $input{make_colors} = 'addi';
1406 $input{translate} = 'perturb';
1407 $input{perturb} = $input{lmdither};
1408 } elsif ($input{gifquant} eq 'gen') {
1409 # just pass options through
1411 $input{make_colors} = 'webmap'; # ignored
1412 $input{translate} = 'giflib';
1414 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1415 $self->{ERRSTR} = $self->_error_as_msg;
1420 if (exists $input{'data'}) {
1421 my $data = io_slurp($IO);
1423 $self->{ERRSTR}='Could not slurp from buffer';
1426 ${$input{data}} = $data;
1432 my ($class, $opts, @images) = @_;
1434 if (!$opts->{'type'} && $opts->{'file'}) {
1435 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1437 unless ($opts->{'type'}) {
1438 $class->_set_error('type parameter missing and not possible to guess from extension');
1441 # translate to ImgRaw
1442 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1443 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1446 $class->_set_opts($opts, "i_", @images)
1448 my @work = map $_->{IMG}, @images;
1449 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1451 if ($opts->{'type'} eq 'gif') {
1452 $class->_set_opts($opts, "gif_", @images)
1454 my $gif_delays = $opts->{gif_delays};
1455 local $opts->{gif_delays} = $gif_delays;
1456 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1457 # assume the caller wants the same delay for each frame
1458 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1460 my $res = i_writegif_wiol($IO, $opts, @work);
1461 $res or $class->_set_error($class->_error_as_msg());
1464 elsif ($opts->{'type'} eq 'tiff') {
1465 $class->_set_opts($opts, "tiff_", @images)
1467 $class->_set_opts($opts, "exif_", @images)
1470 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1471 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1472 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1475 $res = i_writetiff_multi_wiol($IO, @work);
1477 $res or $class->_set_error($class->_error_as_msg());
1481 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1486 # read multiple images from a file
1488 my ($class, %opts) = @_;
1490 if ($opts{file} && !exists $opts{'type'}) {
1492 my $type = $FORMATGUESS->($opts{file});
1493 $opts{'type'} = $type;
1495 unless ($opts{'type'}) {
1496 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1500 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1502 if ($opts{'type'} eq 'gif') {
1504 @imgs = i_readgif_multi_wiol($IO);
1507 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1511 $ERRSTR = _error_as_msg();
1515 elsif ($opts{'type'} eq 'tiff') {
1516 my @imgs = i_readtiff_multi_wiol($IO, -1);
1519 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1523 $ERRSTR = _error_as_msg();
1528 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1532 # Destroy an Imager object
1536 # delete $instances{$self};
1537 if (defined($self->{IMG})) {
1538 # the following is now handled by the XS DESTROY method for
1539 # Imager::ImgRaw object
1540 # Re-enabling this will break virtual images
1541 # tested for in t/t020masked.t
1542 # i_img_destroy($self->{IMG});
1543 undef($self->{IMG});
1545 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1549 # Perform an inplace filter of an image
1550 # that is the image will be overwritten with the data
1556 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1558 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1560 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1561 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1564 if ($filters{$input{'type'}}{names}) {
1565 my $names = $filters{$input{'type'}}{names};
1566 for my $name (keys %$names) {
1567 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1568 $input{$name} = $names->{$name}{$input{$name}};
1572 if (defined($filters{$input{'type'}}{defaults})) {
1573 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1575 %hsh=('image',$self->{IMG},%input);
1578 my @cs=@{$filters{$input{'type'}}{callseq}};
1581 if (!defined($hsh{$_})) {
1582 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1586 &{$filters{$input{'type'}}{callsub}}(%hsh);
1590 $self->{DEBUG} && print "callseq is: @cs\n";
1591 $self->{DEBUG} && print "matching callseq is: @b\n";
1596 # Scale an image to requested size and return the scaled version
1600 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1601 my $img = Imager->new();
1602 my $tmp = Imager->new();
1604 unless (defined wantarray) {
1605 my @caller = caller;
1606 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1610 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1612 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1613 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1614 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1615 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1616 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1617 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1619 if ($opts{qtype} eq 'normal') {
1620 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1621 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1622 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1623 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1626 if ($opts{'qtype'} eq 'preview') {
1627 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1628 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1631 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1634 # Scales only along the X axis
1638 my %opts=(scalefactor=>0.5,@_);
1640 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1642 my $img = Imager->new();
1644 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1646 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1647 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1649 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1653 # Scales only along the Y axis
1657 my %opts=(scalefactor=>0.5,@_);
1659 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1661 my $img = Imager->new();
1663 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1665 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1666 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1668 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1673 # Transform returns a spatial transformation of the input image
1674 # this moves pixels to a new location in the returned image.
1675 # NOTE - should make a utility function to check transforms for
1680 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1682 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1684 # print Dumper(\%opts);
1687 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1689 eval ("use Affix::Infix2Postfix;");
1692 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1695 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1696 {op=>'-',trans=>'Sub'},
1697 {op=>'*',trans=>'Mult'},
1698 {op=>'/',trans=>'Div'},
1699 {op=>'-','type'=>'unary',trans=>'u-'},
1701 {op=>'func','type'=>'unary'}],
1702 'grouping'=>[qw( \( \) )],
1703 'func'=>[qw( sin cos )],
1708 @xt=$I2P->translate($opts{'xexpr'});
1709 @yt=$I2P->translate($opts{'yexpr'});
1711 $numre=$I2P->{'numre'};
1714 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1715 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1716 @{$opts{'parm'}}=@pt;
1719 # print Dumper(\%opts);
1721 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1722 $self->{ERRSTR}='transform: no xopcodes given.';
1726 @op=@{$opts{'xopcodes'}};
1728 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1729 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1732 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1738 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1739 $self->{ERRSTR}='transform: no yopcodes given.';
1743 @op=@{$opts{'yopcodes'}};
1745 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1746 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1749 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1754 if ( !exists $opts{'parm'}) {
1755 $self->{ERRSTR}='transform: no parameter arg given.';
1759 # print Dumper(\@ropx);
1760 # print Dumper(\@ropy);
1761 # print Dumper(\@ropy);
1763 my $img = Imager->new();
1764 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1765 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1771 my ($opts, @imgs) = @_;
1773 require "Imager/Expr.pm";
1775 $opts->{variables} = [ qw(x y) ];
1776 my ($width, $height) = @{$opts}{qw(width height)};
1778 $width ||= $imgs[0]->getwidth();
1779 $height ||= $imgs[0]->getheight();
1781 for my $img (@imgs) {
1782 $opts->{constants}{"w$img_num"} = $img->getwidth();
1783 $opts->{constants}{"h$img_num"} = $img->getheight();
1784 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1785 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1790 $opts->{constants}{w} = $width;
1791 $opts->{constants}{cx} = $width/2;
1794 $Imager::ERRSTR = "No width supplied";
1798 $opts->{constants}{h} = $height;
1799 $opts->{constants}{cy} = $height/2;
1802 $Imager::ERRSTR = "No height supplied";
1805 my $code = Imager::Expr->new($opts);
1807 $Imager::ERRSTR = Imager::Expr::error();
1810 my $channels = $opts->{channels} || 3;
1811 unless ($channels >= 1 && $channels <= 4) {
1812 return Imager->_set_error("channels must be an integer between 1 and 4");
1815 my $img = Imager->new();
1816 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1817 $channels, $code->code(),
1818 $code->nregs(), $code->cregs(),
1819 [ map { $_->{IMG} } @imgs ]);
1820 if (!defined $img->{IMG}) {
1821 $Imager::ERRSTR = Imager->_error_as_msg();
1830 my %opts=(tx => 0,ty => 0, @_);
1832 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1833 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1835 %opts = (src_minx => 0,
1837 src_maxx => $opts{src}->getwidth(),
1838 src_maxy => $opts{src}->getheight(),
1841 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1842 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1843 $self->{ERRSTR} = $self->_error_as_msg();
1853 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
1855 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
1856 $dir = $xlate{$opts{'dir'}};
1857 return $self if i_flipxy($self->{IMG}, $dir);
1864 if (defined $opts{right}) {
1865 my $degrees = $opts{right};
1867 $degrees += 360 * int(((-$degrees)+360)/360);
1869 $degrees = $degrees % 360;
1870 if ($degrees == 0) {
1871 return $self->copy();
1873 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
1874 my $result = Imager->new();
1875 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
1879 $self->{ERRSTR} = $self->_error_as_msg();
1884 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
1888 elsif (defined $opts{radians} || defined $opts{degrees}) {
1889 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
1891 my $result = Imager->new;
1893 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
1896 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
1898 if ($result->{IMG}) {
1902 $self->{ERRSTR} = $self->_error_as_msg();
1907 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
1912 sub matrix_transform {
1916 if ($opts{matrix}) {
1917 my $xsize = $opts{xsize} || $self->getwidth;
1918 my $ysize = $opts{ysize} || $self->getheight;
1920 my $result = Imager->new;
1922 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1923 $opts{matrix}, $opts{back})
1927 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1935 $self->{ERRSTR} = "matrix parameter required";
1941 *yatf = \&matrix_transform;
1943 # These two are supported for legacy code only
1946 return Imager::Color->new(@_);
1950 return Imager::Color::set(@_);
1953 # Draws a box between the specified corner points.
1956 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1957 my $dflcl=i_color_new(255,255,255,255);
1958 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
1960 if (exists $opts{'box'}) {
1961 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
1962 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
1963 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
1964 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
1967 if ($opts{filled}) {
1968 my $color = _color($opts{'color'});
1970 $self->{ERRSTR} = $Imager::ERRSTR;
1973 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
1974 $opts{ymax}, $color);
1976 elsif ($opts{fill}) {
1977 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
1978 # assume it's a hash ref
1979 require 'Imager/Fill.pm';
1980 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
1981 $self->{ERRSTR} = $Imager::ERRSTR;
1985 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
1986 $opts{ymax},$opts{fill}{fill});
1989 my $color = _color($opts{'color'});
1991 $self->{ERRSTR} = $Imager::ERRSTR;
1994 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2000 # Draws an arc - this routine SUCKS and is buggy - it sometimes doesn't work when the arc is a convex polygon
2004 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2005 my $dflcl=i_color_new(255,255,255,255);
2006 my %opts=(color=>$dflcl,
2007 'r'=>min($self->getwidth(),$self->getheight())/3,
2008 'x'=>$self->getwidth()/2,
2009 'y'=>$self->getheight()/2,
2010 'd1'=>0, 'd2'=>361, @_);
2012 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2013 # assume it's a hash ref
2014 require 'Imager/Fill.pm';
2015 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2016 $self->{ERRSTR} = $Imager::ERRSTR;
2020 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2021 $opts{'d2'}, $opts{fill}{fill});
2024 my $color = _color($opts{'color'});
2026 $self->{ERRSTR} = $Imager::ERRSTR;
2029 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2030 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2034 if ($opts{'d1'} <= $opts{'d2'}) {
2035 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2036 $opts{'d1'}, $opts{'d2'}, $color);
2039 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2040 $opts{'d1'}, 361, $color);
2041 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2042 0, $opts{'d2'}, $color);
2050 # Draws a line from one point to the other
2051 # the endpoint is set if the endp parameter is set which it is by default.
2052 # to turn of the endpoint being set use endp=>0 when calling line.
2056 my $dflcl=i_color_new(0,0,0,0);
2057 my %opts=(color=>$dflcl,
2060 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2062 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2063 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2065 my $color = _color($opts{'color'});
2067 $self->{ERRSTR} = $Imager::ERRSTR;
2071 $opts{antialias} = $opts{aa} if defined $opts{aa};
2072 if ($opts{antialias}) {
2073 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2074 $color, $opts{endp});
2076 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2077 $color, $opts{endp});
2082 # Draws a line between an ordered set of points - It more or less just transforms this
2083 # into a list of lines.
2087 my ($pt,$ls,@points);
2088 my $dflcl=i_color_new(0,0,0,0);
2089 my %opts=(color=>$dflcl,@_);
2091 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2093 if (exists($opts{points})) { @points=@{$opts{points}}; }
2094 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2095 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2098 # print Dumper(\@points);
2100 my $color = _color($opts{'color'});
2102 $self->{ERRSTR} = $Imager::ERRSTR;
2105 $opts{antialias} = $opts{aa} if defined $opts{aa};
2106 if ($opts{antialias}) {
2109 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2116 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2126 my ($pt,$ls,@points);
2127 my $dflcl = i_color_new(0,0,0,0);
2128 my %opts = (color=>$dflcl, @_);
2130 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2132 if (exists($opts{points})) {
2133 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2134 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2137 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2138 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2141 if ($opts{'fill'}) {
2142 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2143 # assume it's a hash ref
2144 require 'Imager/Fill.pm';
2145 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2146 $self->{ERRSTR} = $Imager::ERRSTR;
2150 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2151 $opts{'fill'}{'fill'});
2154 my $color = _color($opts{'color'});
2156 $self->{ERRSTR} = $Imager::ERRSTR;
2159 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2166 # this the multipoint bezier curve
2167 # this is here more for testing that actual usage since
2168 # this is not a good algorithm. Usually the curve would be
2169 # broken into smaller segments and each done individually.
2173 my ($pt,$ls,@points);
2174 my $dflcl=i_color_new(0,0,0,0);
2175 my %opts=(color=>$dflcl,@_);
2177 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2179 if (exists $opts{points}) {
2180 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2181 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2184 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2185 $self->{ERRSTR}='Missing or invalid points.';
2189 my $color = _color($opts{'color'});
2191 $self->{ERRSTR} = $Imager::ERRSTR;
2194 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2200 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2203 unless (exists $opts{'x'} && exists $opts{'y'}) {
2204 $self->{ERRSTR} = "missing seed x and y parameters";
2209 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2210 # assume it's a hash ref
2211 require 'Imager/Fill.pm';
2212 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2213 $self->{ERRSTR} = $Imager::ERRSTR;
2217 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2220 my $color = _color($opts{'color'});
2222 $self->{ERRSTR} = $Imager::ERRSTR;
2225 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2227 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2233 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2235 unless (exists $opts{'x'} && exists $opts{'y'}) {
2236 $self->{ERRSTR} = 'missing x and y parameters';
2242 my $color = _color($opts{color})
2244 if (ref $x && ref $y) {
2245 unless (@$x == @$y) {
2246 $self->{ERRSTR} = 'length of x and y mismatch';
2249 if ($color->isa('Imager::Color')) {
2250 for my $i (0..$#{$opts{'x'}}) {
2251 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2255 for my $i (0..$#{$opts{'x'}}) {
2256 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2261 if ($color->isa('Imager::Color')) {
2262 i_ppix($self->{IMG}, $x, $y, $color);
2265 i_ppixf($self->{IMG}, $x, $y, $color);
2275 my %opts = ( "type"=>'8bit', @_);
2277 unless (exists $opts{'x'} && exists $opts{'y'}) {
2278 $self->{ERRSTR} = 'missing x and y parameters';
2284 if (ref $x && ref $y) {
2285 unless (@$x == @$y) {
2286 $self->{ERRSTR} = 'length of x and y mismatch';
2290 if ($opts{"type"} eq '8bit') {
2291 for my $i (0..$#{$opts{'x'}}) {
2292 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2296 for my $i (0..$#{$opts{'x'}}) {
2297 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2300 return wantarray ? @result : \@result;
2303 if ($opts{"type"} eq '8bit') {
2304 return i_get_pixel($self->{IMG}, $x, $y);
2307 return i_gpixf($self->{IMG}, $x, $y);
2314 # make an identity matrix of the given size
2318 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2319 for my $c (0 .. ($size-1)) {
2320 $matrix->[$c][$c] = 1;
2325 # general function to convert an image
2327 my ($self, %opts) = @_;
2330 # the user can either specify a matrix or preset
2331 # the matrix overrides the preset
2332 if (!exists($opts{matrix})) {
2333 unless (exists($opts{preset})) {
2334 $self->{ERRSTR} = "convert() needs a matrix or preset";
2338 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2339 # convert to greyscale, keeping the alpha channel if any
2340 if ($self->getchannels == 3) {
2341 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2343 elsif ($self->getchannels == 4) {
2344 # preserve the alpha channel
2345 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2350 $matrix = _identity($self->getchannels);
2353 elsif ($opts{preset} eq 'noalpha') {
2354 # strip the alpha channel
2355 if ($self->getchannels == 2 or $self->getchannels == 4) {
2356 $matrix = _identity($self->getchannels);
2357 pop(@$matrix); # lose the alpha entry
2360 $matrix = _identity($self->getchannels);
2363 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2365 $matrix = [ [ 1 ] ];
2367 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2368 $matrix = [ [ 0, 1 ] ];
2370 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2371 $matrix = [ [ 0, 0, 1 ] ];
2373 elsif ($opts{preset} eq 'alpha') {
2374 if ($self->getchannels == 2 or $self->getchannels == 4) {
2375 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2378 # the alpha is just 1 <shrug>
2379 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2382 elsif ($opts{preset} eq 'rgb') {
2383 if ($self->getchannels == 1) {
2384 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2386 elsif ($self->getchannels == 2) {
2387 # preserve the alpha channel
2388 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2391 $matrix = _identity($self->getchannels);
2394 elsif ($opts{preset} eq 'addalpha') {
2395 if ($self->getchannels == 1) {
2396 $matrix = _identity(2);
2398 elsif ($self->getchannels == 3) {
2399 $matrix = _identity(4);
2402 $matrix = _identity($self->getchannels);
2406 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2412 $matrix = $opts{matrix};
2415 my $new = Imager->new();
2416 $new->{IMG} = i_img_new();
2417 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2418 # most likely a bad matrix
2419 $self->{ERRSTR} = _error_as_msg();
2426 # general function to map an image through lookup tables
2429 my ($self, %opts) = @_;
2430 my @chlist = qw( red green blue alpha );
2432 if (!exists($opts{'maps'})) {
2433 # make maps from channel maps
2435 for $chnum (0..$#chlist) {
2436 if (exists $opts{$chlist[$chnum]}) {
2437 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2438 } elsif (exists $opts{'all'}) {
2439 $opts{'maps'}[$chnum] = $opts{'all'};
2443 if ($opts{'maps'} and $self->{IMG}) {
2444 i_map($self->{IMG}, $opts{'maps'} );
2450 my ($self, %opts) = @_;
2452 defined $opts{mindist} or $opts{mindist} = 0;
2454 defined $opts{other}
2455 or return $self->_set_error("No 'other' parameter supplied");
2456 defined $opts{other}{IMG}
2457 or return $self->_set_error("No image data in 'other' image");
2460 or return $self->_set_error("No image data");
2462 my $result = Imager->new;
2463 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2465 or return $self->_set_error($self->_error_as_msg());
2470 # destructive border - image is shrunk by one pixel all around
2473 my ($self,%opts)=@_;
2474 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2475 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2479 # Get the width of an image
2483 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2484 return (i_img_info($self->{IMG}))[0];
2487 # Get the height of an image
2491 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2492 return (i_img_info($self->{IMG}))[1];
2495 # Get number of channels in an image
2499 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2500 return i_img_getchannels($self->{IMG});
2507 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2508 return i_img_getmask($self->{IMG});
2516 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2517 i_img_setmask( $self->{IMG} , $opts{mask} );
2520 # Get number of colors in an image
2524 my %opts=('maxcolors'=>2**30,@_);
2525 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2526 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2527 return ($rc==-1? undef : $rc);
2530 # draw string to an image
2534 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2536 my %input=('x'=>0, 'y'=>0, @_);
2537 $input{string}||=$input{text};
2539 unless(exists $input{string}) {
2540 $self->{ERRSTR}="missing required parameter 'string'";
2544 unless($input{font}) {
2545 $self->{ERRSTR}="missing required parameter 'font'";
2549 unless ($input{font}->draw(image=>$self, %input)) {
2550 $self->{ERRSTR} = $self->_error_as_msg();
2557 # Shortcuts that can be exported
2559 sub newcolor { Imager::Color->new(@_); }
2560 sub newfont { Imager::Font->new(@_); }
2562 *NC=*newcolour=*newcolor;
2569 #### Utility routines
2572 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2576 my ($self, $msg) = @_;
2579 $self->{ERRSTR} = $msg;
2587 # Default guess for the type of an image from extension
2589 sub def_guess_type {
2592 $ext=($name =~ m/\.([^\.]+)$/)[0];
2593 return 'tiff' if ($ext =~ m/^tiff?$/);
2594 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2595 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2596 return 'png' if ($ext eq "png");
2597 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2598 return 'tga' if ($ext eq "tga");
2599 return 'rgb' if ($ext eq "rgb");
2600 return 'gif' if ($ext eq "gif");
2601 return 'raw' if ($ext eq "raw");
2605 # get the minimum of a list
2609 for(@_) { if ($_<$mx) { $mx=$_; }}
2613 # get the maximum of a list
2617 for(@_) { if ($_>$mx) { $mx=$_; }}
2621 # string stuff for iptc headers
2625 $str = substr($str,3);
2626 $str =~ s/[\n\r]//g;
2633 # A little hack to parse iptc headers.
2638 my($caption,$photogr,$headln,$credit);
2640 my $str=$self->{IPTCRAW};
2644 @ar=split(/8BIM/,$str);
2649 @sar=split(/\034\002/);
2650 foreach $item (@sar) {
2651 if ($item =~ m/^x/) {
2652 $caption=&clean($item);
2655 if ($item =~ m/^P/) {
2656 $photogr=&clean($item);
2659 if ($item =~ m/^i/) {
2660 $headln=&clean($item);
2663 if ($item =~ m/^n/) {
2664 $credit=&clean($item);
2670 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
2673 # Autoload methods go after =cut, and are processed by the autosplit program.
2677 # Below is the stub of documentation for your module. You better edit it!
2681 Imager - Perl extension for Generating 24 bit Images
2691 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
2696 my $img = Imager->new();
2697 # see Imager::Files for information on the open() method
2698 $img->open(file=>$file) or die $img->errstr();
2700 $file =~ s/\.[^.]*$//;
2702 # Create smaller version
2703 # documented in Imager::Transformations
2704 my $thumb = $img->scale(scalefactor=>.3);
2706 # Autostretch individual channels
2707 $thumb->filter(type=>'autolevels');
2709 # try to save in one of these formats
2712 for $format ( qw( png gif jpg tiff ppm ) ) {
2713 # Check if given format is supported
2714 if ($Imager::formats{$format}) {
2715 $file.="_low.$format";
2716 print "Storing image as: $file\n";
2717 # documented in Imager::Files
2718 $thumb->write(file=>$file) or
2726 Imager is a module for creating and altering images. It can read and
2727 write various image formats, draw primitive shapes like lines,and
2728 polygons, blend multiple images together in various ways, scale, crop,
2729 render text and more.
2731 =head2 Overview of documentation
2737 Imager - This document - Synopsis Example, Table of Contents and
2742 L<Imager::ImageTypes> - Basics of constructing image objects with
2743 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
2744 8/16/double bits/channel, color maps, channel masks, image tags, color
2745 quantization. Also discusses basic image information methods.
2749 L<Imager::Files> - IO interaction, reading/writing images, format
2754 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
2759 L<Imager::Color> - Color specification.
2763 L<Imager::Fill> - Fill pattern specification.
2767 L<Imager::Font> - General font rendering, bounding boxes and font
2772 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
2773 blending, pasting, convert and map.
2777 L<Imager::Engines> - Programmable transformations through
2778 C<transform()>, C<transform2()> and C<matrix_transform()>.
2782 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
2787 L<Imager::Expr> - Expressions for evaluation engine used by
2792 L<Imager::Matrix2d> - Helper class for affine transformations.
2796 L<Imager::Fountain> - Helper for making gradient profiles.
2800 =head2 Basic Overview
2802 An Image object is created with C<$img = Imager-E<gt>new()>.
2805 $img=Imager->new(); # create empty image
2806 $img->open(file=>'lena.png',type=>'png') or # read image from file
2807 die $img->errstr(); # give an explanation
2808 # if something failed
2810 or if you want to create an empty image:
2812 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
2814 This example creates a completely black image of width 400 and height
2817 When an operation fails which can be directly associated with an image
2818 the error message is stored can be retrieved with
2819 C<$img-E<gt>errstr()>.
2821 In cases where no image object is associated with an operation
2822 C<$Imager::ERRSTR> is used to report errors not directly associated
2823 with an image object.
2825 The C<Imager-E<gt>new> method is described in detail in
2826 L<Imager::ImageTypes>.
2830 Where to find information on methods for Imager class objects.
2832 addcolors() - L<Imager::ImageTypes>
2834 addtag() - L<Imager::ImageTypes> - add image tags
2836 arc() - L<Imager::Draw/arc>
2838 bits() - L<Imager::ImageTypes> - number of bits per sample for the
2841 box() - L<Imager::Draw/box>
2843 circle() - L<Imager::Draw/circle>
2845 convert() - L<Imager::Transformations/"Color transformations"> -
2846 transform the color space
2848 copy() - L<Imager::Transformations/copy>
2850 crop() - L<Imager::Transformations/crop> - extract part of an image
2852 deltag() - L<Imager::ImageTypes> - delete image tags
2854 difference() - L<Imager::Filters/"Image Difference">
2856 filter() - L<Imager::Filters>
2858 findcolor() - L<Imager::ImageTypes> - search the image palette, if it
2861 flip() - L<Imager::Transformations/flip>
2863 flood_fill() - L<Imager::Draw/flood_fill>
2865 getchannels() - L<Imager::ImageTypes>
2867 getcolorcount() - L<Imager::ImageTypes>
2869 getcolors() - L<Imager::ImageTypes> - get colors from the image
2870 palette, if it has one
2872 getheight() - L<Imager::ImageTypes>
2874 getpixel() - L<Imager::Draw/setpixel and getpixel>
2876 getwidth() - L<Imager::ImageTypes>
2878 img_set() - L<Imager::ImageTypes>
2880 line() - L<Imager::Draw/line>
2882 map() - L<Imager::Transformations/"Color Mappings"> - remap color
2885 masked() - L<Imager::ImageTypes> - make a masked image
2887 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
2889 new() - L<Imager::ImageTypes>
2891 paste() - L<Imager::Transformations/paste> - draw an image onto an image
2893 polygon() - L<Imager::Draw/polygon>
2895 polyline() - L<Imager::Draw/polyline>
2897 read() - L<Imager::Files>
2899 read_multi() - L<Imager::Files>
2901 rotate() - L<Imager::Transformations/rotate>
2903 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
2904 image and use the alpha channel
2906 scale() - L<Imager::Transformations/scale>
2908 setcolors() - L<Imager::ImageTypes> - set palette colors in a paletted image
2910 setpixel() - L<Imager::Draw/setpixel and getpixel>
2912 string() - L<Imager::Font/string> - draw text on an image
2914 tags() - L<Imager::ImageTypes> - fetch image tags
2916 to_paletted() - L<Imager::ImageTypes>
2918 to_rgb8() - L<Imager::ImageTypes>
2920 transform() - L<Imager::Engines/"transform">
2922 transform2() - L<Imager::Engines/"transform2">
2924 type() - L<Imager::ImageTypes> - type of image (direct vs paletted)
2926 virtual() - L<Imager::ImageTypes> - whether the image has it's own
2929 write() - L<Imager::Files>
2931 write_multi() - L<Imager::Files>
2935 You can ask for help, report bugs or express your undying love for
2936 Imager on the Imager-devel mailing list.
2938 To subscribe send a message with C<subscribe> in the body to:
2940 imager-devel+request@molar.is
2944 http://www.molar.is/en/lists/imager-devel/
2945 (annonymous is temporarily off due to spam)
2947 where you can also find the mailing list archive.
2949 If you're into IRC, you can typically find the developers in #Imager
2950 on irc.rhizomatic.net. As with any IRC channel, the participants
2951 could be occupied or asleep, so please be patient.
2955 Bugs are listed individually for relevant pod pages.
2959 Arnar M. Hrafnkelsson (addi@imager.perl.org) and Tony Cook
2960 (tony@imager.perl.org) See the README for a complete list.
2964 perl(1), Imager::ImageTypes(3), Imager::Files(3), Imager::Draw(3),
2965 Imager::Color(3), Imager::Fill(3), Imager::Font(3),
2966 Imager::Transformations(3), Imager::Engines(3), Imager::Filters(3),
2967 Imager::Expr(3), Imager::Matrix2d(3), Imager::Fountain(3)
2969 Affix::Infix2Postfix(3), Parse::RecDescent(3)
2970 http://imager.perl.org/~addi/perl/Imager/