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),
357 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
358 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
359 $hsh{ssample_param}, $hsh{segments});
362 $filters{unsharpmask} =
364 callseq => [ qw(image stddev scale) ],
365 defaults => { stddev=>2.0, scale=>1.0 },
369 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
373 $FORMATGUESS=\&def_guess_type;
383 # NOTE: this might be moved to an import override later on
387 # (look through @_ for special tags, process, and remove them);
389 # print Dumper($pack);
394 m_init_log($_[0],$_[1]);
395 log_entry("Imager $VERSION starting\n", 1);
400 my %parms=(loglevel=>1,@_);
402 init_log($parms{'log'},$parms{'loglevel'});
405 if (exists $parms{'warn_obsolete'}) {
406 $warn_obsolete = $parms{'warn_obsolete'};
409 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
410 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
414 if (exists $parms{'t1log'}) {
415 i_init_fonts($parms{'t1log'});
421 print "shutdown code\n";
422 # for(keys %instances) { $instances{$_}->DESTROY(); }
423 malloc_state(); # how do decide if this should be used? -- store something from the import
424 print "Imager exiting\n";
428 # Load a filter plugin
433 my ($DSO_handle,$str)=DSO_open($filename);
434 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
435 my %funcs=DSO_funclist($DSO_handle);
436 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
438 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
440 $DSOs{$filename}=[$DSO_handle,\%funcs];
443 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
444 $DEBUG && print "eval string:\n",$evstr,"\n";
456 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
457 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
458 for(keys %{$funcref}) {
460 $DEBUG && print "unloading: $_\n";
462 my $rc=DSO_close($DSO_handle);
463 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
467 # take the results of i_error() and make a message out of it
469 return join(": ", map $_->[0], i_errors());
472 # this function tries to DWIM for color parameters
473 # color objects are used as is
474 # simple scalars are simply treated as single parameters to Imager::Color->new
475 # hashrefs are treated as named argument lists to Imager::Color->new
476 # arrayrefs are treated as list arguments to Imager::Color->new iff any
478 # other arrayrefs are treated as list arguments to Imager::Color::Float
482 # perl 5.6.0 seems to do weird things to $arg if we don't make an
483 # explicitly stringified copy
484 # I vaguely remember a bug on this on p5p, but couldn't find it
485 # through bugs.perl.org (I had trouble getting it to find any bugs)
486 my $copy = $arg . "";
490 if (UNIVERSAL::isa($arg, "Imager::Color")
491 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
495 if ($copy =~ /^HASH\(/) {
496 $result = Imager::Color->new(%$arg);
498 elsif ($copy =~ /^ARRAY\(/) {
499 if (grep $_ > 1, @$arg) {
500 $result = Imager::Color->new(@$arg);
503 $result = Imager::Color::Float->new(@$arg);
507 $Imager::ERRSTR = "Not a color";
512 # assume Imager::Color::new knows how to handle it
513 $result = Imager::Color->new($arg);
521 # Methods to be called on objects.
524 # Create a new Imager object takes very few parameters.
525 # usually you call this method and then call open from
526 # the resulting object
533 $self->{IMG}=undef; # Just to indicate what exists
534 $self->{ERRSTR}=undef; #
535 $self->{DEBUG}=$DEBUG;
536 $self->{DEBUG} && print "Initialized Imager\n";
537 if (defined $hsh{xsize} && defined $hsh{ysize}) {
538 unless ($self->img_set(%hsh)) {
539 $Imager::ERRSTR = $self->{ERRSTR};
546 # Copy an entire image with no changes
547 # - if an image has magic the copy of it will not be magical
551 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
553 my $newcopy=Imager->new();
554 $newcopy->{IMG}=i_img_new();
555 i_copy($newcopy->{IMG},$self->{IMG});
563 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
564 my %input=(left=>0, top=>0, @_);
565 unless($input{img}) {
566 $self->{ERRSTR}="no source image";
569 $input{left}=0 if $input{left} <= 0;
570 $input{top}=0 if $input{top} <= 0;
572 my($r,$b)=i_img_info($src->{IMG});
574 i_copyto($self->{IMG}, $src->{IMG},
575 0,0, $r, $b, $input{left}, $input{top});
576 return $self; # What should go here??
579 # Crop an image - i.e. return a new image that is smaller
583 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
588 my ($w, $h, $l, $r, $b, $t) =
589 @hsh{qw(width height left right bottom top)};
591 # work through the various possibilities
596 elsif (!defined $r) {
597 $r = $self->getwidth;
609 $l = int(0.5+($self->getwidth()-$w)/2);
614 $r = $self->getwidth;
620 elsif (!defined $b) {
621 $b = $self->getheight;
633 $t=int(0.5+($self->getheight()-$h)/2);
638 $b = $self->getheight;
641 ($l,$r)=($r,$l) if $l>$r;
642 ($t,$b)=($b,$t) if $t>$b;
645 $r > $self->getwidth and $r = $self->getwidth;
647 $b > $self->getheight and $b = $self->getheight;
649 if ($l == $r || $t == $b) {
650 $self->_set_error("resulting image would have no content");
654 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
656 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
661 my ($self, %opts) = @_;
663 $self->{IMG} or return $self->_set_error("Not a valid image");
665 my $x = $opts{xsize} || $self->getwidth;
666 my $y = $opts{ysize} || $self->getheight;
667 my $channels = $opts{channels} || $self->getchannels;
669 my $out = Imager->new;
670 if ($channels == $self->getchannels) {
671 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
674 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
676 unless ($out->{IMG}) {
677 $self->{ERRSTR} = $self->_error_as_msg;
684 # Sets an image to a certain size and channel number
685 # if there was previously data in the image it is discarded
690 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
692 if (defined($self->{IMG})) {
693 # let IIM_DESTROY destroy it, it's possible this image is
694 # referenced from a virtual image (like masked)
695 #i_img_destroy($self->{IMG});
699 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
700 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
701 $hsh{maxcolors} || 256);
703 elsif ($hsh{bits} eq 'double') {
704 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
706 elsif ($hsh{bits} == 16) {
707 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
710 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
714 unless ($self->{IMG}) {
715 $self->{ERRSTR} = Imager->_error_as_msg();
722 # created a masked version of the current image
726 $self or return undef;
727 my %opts = (left => 0,
729 right => $self->getwidth,
730 bottom => $self->getheight,
732 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
734 my $result = Imager->new;
735 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
736 $opts{top}, $opts{right} - $opts{left},
737 $opts{bottom} - $opts{top});
738 # keep references to the mask and base images so they don't
740 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
745 # convert an RGB image into a paletted image
749 if (@_ != 1 && !ref $_[0]) {
756 my $result = Imager->new;
757 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
759 #print "Type ", i_img_type($result->{IMG}), "\n";
761 if ($result->{IMG}) {
765 $self->{ERRSTR} = $self->_error_as_msg;
770 # convert a paletted (or any image) to an 8-bit/channel RGB images
776 $result = Imager->new;
777 $result->{IMG} = i_img_to_rgb($self->{IMG})
786 my %opts = (colors=>[], @_);
788 @{$opts{colors}} or return undef;
790 $self->{IMG} and i_addcolors($self->{IMG}, @{$opts{colors}});
795 my %opts = (start=>0, colors=>[], @_);
796 @{$opts{colors}} or return undef;
798 $self->{IMG} and i_setcolors($self->{IMG}, $opts{start}, @{$opts{colors}});
804 if (!exists $opts{start} && !exists $opts{count}) {
807 $opts{count} = $self->colorcount;
809 elsif (!exists $opts{count}) {
812 elsif (!exists $opts{start}) {
817 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
821 i_colorcount($_[0]{IMG});
825 i_maxcolors($_[0]{IMG});
831 $opts{color} or return undef;
833 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
838 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
839 if ($bits && $bits == length(pack("d", 1)) * 8) {
848 return i_img_type($self->{IMG}) ? "paletted" : "direct";
854 $self->{IMG} and i_img_virtual($self->{IMG});
858 my ($self, %opts) = @_;
860 $self->{IMG} or return;
862 if (defined $opts{name}) {
866 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
867 push @result, (i_tags_get($self->{IMG}, $found))[1];
870 return wantarray ? @result : $result[0];
872 elsif (defined $opts{code}) {
876 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
877 push @result, (i_tags_get($self->{IMG}, $found))[1];
884 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
887 return i_tags_count($self->{IMG});
896 return -1 unless $self->{IMG};
898 if (defined $opts{value}) {
899 if ($opts{value} =~ /^\d+$/) {
901 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
904 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
907 elsif (defined $opts{data}) {
908 # force addition as a string
909 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
912 $self->{ERRSTR} = "No value supplied";
916 elsif ($opts{code}) {
917 if (defined $opts{value}) {
918 if ($opts{value} =~ /^\d+$/) {
920 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
923 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
926 elsif (defined $opts{data}) {
927 # force addition as a string
928 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
931 $self->{ERRSTR} = "No value supplied";
944 return 0 unless $self->{IMG};
946 if (defined $opts{'index'}) {
947 return i_tags_delete($self->{IMG}, $opts{'index'});
949 elsif (defined $opts{name}) {
950 return i_tags_delbyname($self->{IMG}, $opts{name});
952 elsif (defined $opts{code}) {
953 return i_tags_delbycode($self->{IMG}, $opts{code});
956 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
962 my ($self, %opts) = @_;
965 $self->deltag(name=>$opts{name});
966 return $self->addtag(name=>$opts{name}, value=>$opts{value});
968 elsif (defined $opts{code}) {
969 $self->deltag(code=>$opts{code});
970 return $self->addtag(code=>$opts{code}, value=>$opts{value});
979 my ($self, $input) = @_;
982 return $input->{io}, undef;
984 elsif ($input->{fd}) {
985 return io_new_fd($input->{fd});
987 elsif ($input->{fh}) {
988 my $fd = fileno($input->{fh});
990 $self->_set_error("Handle in fh option not opened");
993 return io_new_fd($fd);
995 elsif ($input->{file}) {
996 my $file = IO::File->new($input->{file}, "r");
998 $self->_set_error("Could not open $input->{file}: $!");
1002 return (io_new_fd(fileno($file)), $file);
1004 elsif ($input->{data}) {
1005 return io_new_buffer($input->{data});
1007 elsif ($input->{callback} || $input->{readcb}) {
1008 if (!$input->{seekcb}) {
1009 $self->_set_error("Need a seekcb parameter");
1011 if ($input->{maxbuffer}) {
1012 return io_new_cb($input->{writecb},
1013 $input->{callback} || $input->{readcb},
1014 $input->{seekcb}, $input->{closecb},
1015 $input->{maxbuffer});
1018 return io_new_cb($input->{writecb},
1019 $input->{callback} || $input->{readcb},
1020 $input->{seekcb}, $input->{closecb});
1024 $self->_set_error("file/fd/fh/data/callback parameter missing");
1029 sub _get_writer_io {
1030 my ($self, $input, $type) = @_;
1033 return io_new_fd($input->{fd});
1035 elsif ($input->{fh}) {
1036 my $fd = fileno($input->{fh});
1038 $self->_set_error("Handle in fh option not opened");
1042 my $oldfh = select($input->{fh});
1043 # flush anything that's buffered, and make sure anything else is flushed
1046 return io_new_fd($fd);
1048 elsif ($input->{file}) {
1049 my $fh = new IO::File($input->{file},"w+");
1051 $self->_set_error("Could not open file $input->{file}: $!");
1054 binmode($fh) or die;
1055 return (io_new_fd(fileno($fh)), $fh);
1057 elsif ($input->{data}) {
1058 return io_new_bufchain();
1060 elsif ($input->{callback} || $input->{writecb}) {
1061 if ($input->{maxbuffer}) {
1062 return io_new_cb($input->{callback} || $input->{writecb},
1064 $input->{seekcb}, $input->{closecb},
1065 $input->{maxbuffer});
1068 return io_new_cb($input->{callback} || $input->{writecb},
1070 $input->{seekcb}, $input->{closecb});
1074 $self->_set_error("file/fd/fh/data/callback parameter missing");
1079 # Read an image from file
1085 if (defined($self->{IMG})) {
1086 # let IIM_DESTROY do the destruction, since the image may be
1087 # referenced from elsewhere
1088 #i_img_destroy($self->{IMG});
1089 undef($self->{IMG});
1092 # FIXME: Find the format here if not specified
1093 # yes the code isn't here yet - next week maybe?
1094 # Next week? Are you high or something? That comment
1095 # has been there for half a year dude.
1096 # Look, i just work here, ok?
1098 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1100 unless ($input{'type'}) {
1101 $input{'type'} = i_test_format_probe($IO, -1);
1104 unless ($input{'type'}) {
1105 $self->_set_error('type parameter missing and not possible to guess from extension');
1110 if ( $input{'type'} eq 'jpeg' ) {
1111 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1112 if ( !defined($self->{IMG}) ) {
1113 $self->{ERRSTR}='unable to read jpeg image'; return undef;
1115 $self->{DEBUG} && print "loading a jpeg file\n";
1119 if ( $input{'type'} eq 'tiff' ) {
1120 $self->{IMG}=i_readtiff_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1121 if ( !defined($self->{IMG}) ) {
1122 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1124 $self->{DEBUG} && print "loading a tiff file\n";
1128 if ( $input{'type'} eq 'pnm' ) {
1129 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1130 if ( !defined($self->{IMG}) ) {
1131 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg(); return undef;
1133 $self->{DEBUG} && print "loading a pnm file\n";
1137 if ( $input{'type'} eq 'png' ) {
1138 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1139 if ( !defined($self->{IMG}) ) {
1140 $self->{ERRSTR}='unable to read png image';
1143 $self->{DEBUG} && print "loading a png file\n";
1146 if ( $input{'type'} eq 'bmp' ) {
1147 $self->{IMG}=i_readbmp_wiol( $IO );
1148 if ( !defined($self->{IMG}) ) {
1149 $self->{ERRSTR}=$self->_error_as_msg();
1152 $self->{DEBUG} && print "loading a bmp file\n";
1155 if ( $input{'type'} eq 'gif' ) {
1156 if ($input{colors} && !ref($input{colors})) {
1157 # must be a reference to a scalar that accepts the colour map
1158 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1161 if ($input{colors}) {
1163 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1165 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1169 $self->{IMG} =i_readgif_wiol( $IO );
1171 if ( !defined($self->{IMG}) ) {
1172 $self->{ERRSTR}=$self->_error_as_msg();
1175 $self->{DEBUG} && print "loading a gif file\n";
1178 if ( $input{'type'} eq 'tga' ) {
1179 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1180 if ( !defined($self->{IMG}) ) {
1181 $self->{ERRSTR}=$self->_error_as_msg();
1184 $self->{DEBUG} && print "loading a tga file\n";
1187 if ( $input{'type'} eq 'rgb' ) {
1188 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1189 if ( !defined($self->{IMG}) ) {
1190 $self->{ERRSTR}=$self->_error_as_msg();
1193 $self->{DEBUG} && print "loading a tga file\n";
1197 if ( $input{'type'} eq 'raw' ) {
1198 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1200 if ( !($params{xsize} && $params{ysize}) ) {
1201 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1205 $self->{IMG} = i_readraw_wiol( $IO,
1208 $params{datachannels},
1209 $params{storechannels},
1210 $params{interleave});
1211 if ( !defined($self->{IMG}) ) {
1212 $self->{ERRSTR}='unable to read raw image';
1215 $self->{DEBUG} && print "loading a raw file\n";
1221 sub _fix_gif_positions {
1222 my ($opts, $opt, $msg, @imgs) = @_;
1224 my $positions = $opts->{'gif_positions'};
1226 for my $pos (@$positions) {
1227 my ($x, $y) = @$pos;
1228 my $img = $imgs[$index++];
1229 $img->settag(name=>'gif_left', value=>$x);
1230 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1232 $$msg .= "replaced with the gif_left and gif_top tags";
1237 gif_each_palette=>'gif_local_map',
1238 interlace => 'gif_interlace',
1239 gif_delays => 'gif_delay',
1240 gif_positions => \&_fix_gif_positions,
1241 gif_loop_count => 'gif_loop',
1245 my ($self, $opts, $prefix, @imgs) = @_;
1247 for my $opt (keys %$opts) {
1249 if ($obsolete_opts{$opt}) {
1250 my $new = $obsolete_opts{$opt};
1251 my $msg = "Obsolete option $opt ";
1253 $new->($opts, $opt, \$msg, @imgs);
1256 $msg .= "replaced with the $new tag ";
1259 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1260 warn $msg if $warn_obsolete && $^W;
1262 next unless $tagname =~ /^\Q$prefix/;
1263 my $value = $opts->{$opt};
1265 if (UNIVERSAL::isa($value, "Imager::Color")) {
1266 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1267 for my $img (@imgs) {
1268 $img->settag(name=>$tagname, value=>$tag);
1271 elsif (ref($value) eq 'ARRAY') {
1272 for my $i (0..$#$value) {
1273 my $val = $value->[$i];
1275 if (UNIVERSAL::isa($val, "Imager::Color")) {
1276 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1278 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1281 $self->_set_error("Unknown reference type " . ref($value) .
1282 " supplied in array for $opt");
1288 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1293 $self->_set_error("Unknown reference type " . ref($value) .
1294 " supplied for $opt");
1299 # set it as a tag for every image
1300 for my $img (@imgs) {
1301 $img->settag(name=>$tagname, value=>$value);
1309 # Write an image to file
1312 my %input=(jpegquality=>75,
1322 $self->_set_opts(\%input, "i_", $self)
1325 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1327 if (!$input{'type'} and $input{file}) {
1328 $input{'type'}=$FORMATGUESS->($input{file});
1330 if (!$input{'type'}) {
1331 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1335 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1337 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1340 if ($input{'type'} eq 'tiff') {
1341 $self->_set_opts(\%input, "tiff_", $self)
1343 $self->_set_opts(\%input, "exif_", $self)
1346 if (defined $input{class} && $input{class} eq 'fax') {
1347 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1348 $self->{ERRSTR}='Could not write to buffer';
1352 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1353 $self->{ERRSTR}='Could not write to buffer';
1357 } elsif ( $input{'type'} eq 'pnm' ) {
1358 $self->_set_opts(\%input, "pnm_", $self)
1360 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1361 $self->{ERRSTR}='unable to write pnm image';
1364 $self->{DEBUG} && print "writing a pnm file\n";
1365 } elsif ( $input{'type'} eq 'raw' ) {
1366 $self->_set_opts(\%input, "raw_", $self)
1368 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1369 $self->{ERRSTR}='unable to write raw image';
1372 $self->{DEBUG} && print "writing a raw file\n";
1373 } elsif ( $input{'type'} eq 'png' ) {
1374 $self->_set_opts(\%input, "png_", $self)
1376 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1377 $self->{ERRSTR}='unable to write png image';
1380 $self->{DEBUG} && print "writing a png file\n";
1381 } elsif ( $input{'type'} eq 'jpeg' ) {
1382 $self->_set_opts(\%input, "jpeg_", $self)
1384 $self->_set_opts(\%input, "exif_", $self)
1386 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1387 $self->{ERRSTR} = $self->_error_as_msg();
1390 $self->{DEBUG} && print "writing a jpeg file\n";
1391 } elsif ( $input{'type'} eq 'bmp' ) {
1392 $self->_set_opts(\%input, "bmp_", $self)
1394 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1395 $self->{ERRSTR}='unable to write bmp image';
1398 $self->{DEBUG} && print "writing a bmp file\n";
1399 } elsif ( $input{'type'} eq 'tga' ) {
1400 $self->_set_opts(\%input, "tga_", $self)
1403 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1404 $self->{ERRSTR}=$self->_error_as_msg();
1407 $self->{DEBUG} && print "writing a tga file\n";
1408 } elsif ( $input{'type'} eq 'gif' ) {
1409 $self->_set_opts(\%input, "gif_", $self)
1411 # compatibility with the old interfaces
1412 if ($input{gifquant} eq 'lm') {
1413 $input{make_colors} = 'addi';
1414 $input{translate} = 'perturb';
1415 $input{perturb} = $input{lmdither};
1416 } elsif ($input{gifquant} eq 'gen') {
1417 # just pass options through
1419 $input{make_colors} = 'webmap'; # ignored
1420 $input{translate} = 'giflib';
1422 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1423 $self->{ERRSTR} = $self->_error_as_msg;
1428 if (exists $input{'data'}) {
1429 my $data = io_slurp($IO);
1431 $self->{ERRSTR}='Could not slurp from buffer';
1434 ${$input{data}} = $data;
1440 my ($class, $opts, @images) = @_;
1442 if (!$opts->{'type'} && $opts->{'file'}) {
1443 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1445 unless ($opts->{'type'}) {
1446 $class->_set_error('type parameter missing and not possible to guess from extension');
1449 # translate to ImgRaw
1450 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1451 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1454 $class->_set_opts($opts, "i_", @images)
1456 my @work = map $_->{IMG}, @images;
1457 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1459 if ($opts->{'type'} eq 'gif') {
1460 $class->_set_opts($opts, "gif_", @images)
1462 my $gif_delays = $opts->{gif_delays};
1463 local $opts->{gif_delays} = $gif_delays;
1464 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1465 # assume the caller wants the same delay for each frame
1466 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1468 my $res = i_writegif_wiol($IO, $opts, @work);
1469 $res or $class->_set_error($class->_error_as_msg());
1472 elsif ($opts->{'type'} eq 'tiff') {
1473 $class->_set_opts($opts, "tiff_", @images)
1475 $class->_set_opts($opts, "exif_", @images)
1478 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1479 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1480 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1483 $res = i_writetiff_multi_wiol($IO, @work);
1485 $res or $class->_set_error($class->_error_as_msg());
1489 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1494 # read multiple images from a file
1496 my ($class, %opts) = @_;
1498 if ($opts{file} && !exists $opts{'type'}) {
1500 my $type = $FORMATGUESS->($opts{file});
1501 $opts{'type'} = $type;
1503 unless ($opts{'type'}) {
1504 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1508 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1510 if ($opts{'type'} eq 'gif') {
1512 @imgs = i_readgif_multi_wiol($IO);
1515 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1519 $ERRSTR = _error_as_msg();
1523 elsif ($opts{'type'} eq 'tiff') {
1524 my @imgs = i_readtiff_multi_wiol($IO, -1);
1527 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1531 $ERRSTR = _error_as_msg();
1536 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1540 # Destroy an Imager object
1544 # delete $instances{$self};
1545 if (defined($self->{IMG})) {
1546 # the following is now handled by the XS DESTROY method for
1547 # Imager::ImgRaw object
1548 # Re-enabling this will break virtual images
1549 # tested for in t/t020masked.t
1550 # i_img_destroy($self->{IMG});
1551 undef($self->{IMG});
1553 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1557 # Perform an inplace filter of an image
1558 # that is the image will be overwritten with the data
1564 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1566 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1568 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1569 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1572 if ($filters{$input{'type'}}{names}) {
1573 my $names = $filters{$input{'type'}}{names};
1574 for my $name (keys %$names) {
1575 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1576 $input{$name} = $names->{$name}{$input{$name}};
1580 if (defined($filters{$input{'type'}}{defaults})) {
1581 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1583 %hsh=('image',$self->{IMG},%input);
1586 my @cs=@{$filters{$input{'type'}}{callseq}};
1589 if (!defined($hsh{$_})) {
1590 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1594 &{$filters{$input{'type'}}{callsub}}(%hsh);
1598 $self->{DEBUG} && print "callseq is: @cs\n";
1599 $self->{DEBUG} && print "matching callseq is: @b\n";
1604 # Scale an image to requested size and return the scaled version
1608 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1609 my $img = Imager->new();
1610 my $tmp = Imager->new();
1612 unless (defined wantarray) {
1613 my @caller = caller;
1614 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1618 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1620 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1621 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1622 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1623 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1624 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1625 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1627 if ($opts{qtype} eq 'normal') {
1628 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1629 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1630 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1631 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1634 if ($opts{'qtype'} eq 'preview') {
1635 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1636 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1639 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1642 # Scales only along the X axis
1646 my %opts=(scalefactor=>0.5,@_);
1648 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1650 my $img = Imager->new();
1652 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1654 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1655 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1657 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1661 # Scales only along the Y axis
1665 my %opts=(scalefactor=>0.5,@_);
1667 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1669 my $img = Imager->new();
1671 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1673 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1674 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1676 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1681 # Transform returns a spatial transformation of the input image
1682 # this moves pixels to a new location in the returned image.
1683 # NOTE - should make a utility function to check transforms for
1688 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1690 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1692 # print Dumper(\%opts);
1695 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1697 eval ("use Affix::Infix2Postfix;");
1700 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1703 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1704 {op=>'-',trans=>'Sub'},
1705 {op=>'*',trans=>'Mult'},
1706 {op=>'/',trans=>'Div'},
1707 {op=>'-','type'=>'unary',trans=>'u-'},
1709 {op=>'func','type'=>'unary'}],
1710 'grouping'=>[qw( \( \) )],
1711 'func'=>[qw( sin cos )],
1716 @xt=$I2P->translate($opts{'xexpr'});
1717 @yt=$I2P->translate($opts{'yexpr'});
1719 $numre=$I2P->{'numre'};
1722 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1723 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1724 @{$opts{'parm'}}=@pt;
1727 # print Dumper(\%opts);
1729 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1730 $self->{ERRSTR}='transform: no xopcodes given.';
1734 @op=@{$opts{'xopcodes'}};
1736 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1737 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1740 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1746 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1747 $self->{ERRSTR}='transform: no yopcodes given.';
1751 @op=@{$opts{'yopcodes'}};
1753 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1754 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1757 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1762 if ( !exists $opts{'parm'}) {
1763 $self->{ERRSTR}='transform: no parameter arg given.';
1767 # print Dumper(\@ropx);
1768 # print Dumper(\@ropy);
1769 # print Dumper(\@ropy);
1771 my $img = Imager->new();
1772 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1773 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1779 my ($opts, @imgs) = @_;
1781 require "Imager/Expr.pm";
1783 $opts->{variables} = [ qw(x y) ];
1784 my ($width, $height) = @{$opts}{qw(width height)};
1786 $width ||= $imgs[0]->getwidth();
1787 $height ||= $imgs[0]->getheight();
1789 for my $img (@imgs) {
1790 $opts->{constants}{"w$img_num"} = $img->getwidth();
1791 $opts->{constants}{"h$img_num"} = $img->getheight();
1792 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1793 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1798 $opts->{constants}{w} = $width;
1799 $opts->{constants}{cx} = $width/2;
1802 $Imager::ERRSTR = "No width supplied";
1806 $opts->{constants}{h} = $height;
1807 $opts->{constants}{cy} = $height/2;
1810 $Imager::ERRSTR = "No height supplied";
1813 my $code = Imager::Expr->new($opts);
1815 $Imager::ERRSTR = Imager::Expr::error();
1818 my $channels = $opts->{channels} || 3;
1819 unless ($channels >= 1 && $channels <= 4) {
1820 return Imager->_set_error("channels must be an integer between 1 and 4");
1823 my $img = Imager->new();
1824 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1825 $channels, $code->code(),
1826 $code->nregs(), $code->cregs(),
1827 [ map { $_->{IMG} } @imgs ]);
1828 if (!defined $img->{IMG}) {
1829 $Imager::ERRSTR = Imager->_error_as_msg();
1838 my %opts=(tx => 0,ty => 0, @_);
1840 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1841 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1843 %opts = (src_minx => 0,
1845 src_maxx => $opts{src}->getwidth(),
1846 src_maxy => $opts{src}->getheight(),
1849 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1850 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1851 $self->{ERRSTR} = $self->_error_as_msg();
1861 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
1863 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
1864 $dir = $xlate{$opts{'dir'}};
1865 return $self if i_flipxy($self->{IMG}, $dir);
1872 if (defined $opts{right}) {
1873 my $degrees = $opts{right};
1875 $degrees += 360 * int(((-$degrees)+360)/360);
1877 $degrees = $degrees % 360;
1878 if ($degrees == 0) {
1879 return $self->copy();
1881 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
1882 my $result = Imager->new();
1883 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
1887 $self->{ERRSTR} = $self->_error_as_msg();
1892 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
1896 elsif (defined $opts{radians} || defined $opts{degrees}) {
1897 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
1899 my $result = Imager->new;
1901 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
1904 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
1906 if ($result->{IMG}) {
1910 $self->{ERRSTR} = $self->_error_as_msg();
1915 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
1920 sub matrix_transform {
1924 if ($opts{matrix}) {
1925 my $xsize = $opts{xsize} || $self->getwidth;
1926 my $ysize = $opts{ysize} || $self->getheight;
1928 my $result = Imager->new;
1930 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1931 $opts{matrix}, $opts{back})
1935 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1943 $self->{ERRSTR} = "matrix parameter required";
1949 *yatf = \&matrix_transform;
1951 # These two are supported for legacy code only
1954 return Imager::Color->new(@_);
1958 return Imager::Color::set(@_);
1961 # Draws a box between the specified corner points.
1964 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1965 my $dflcl=i_color_new(255,255,255,255);
1966 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
1968 if (exists $opts{'box'}) {
1969 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
1970 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
1971 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
1972 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
1975 if ($opts{filled}) {
1976 my $color = _color($opts{'color'});
1978 $self->{ERRSTR} = $Imager::ERRSTR;
1981 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
1982 $opts{ymax}, $color);
1984 elsif ($opts{fill}) {
1985 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
1986 # assume it's a hash ref
1987 require 'Imager/Fill.pm';
1988 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
1989 $self->{ERRSTR} = $Imager::ERRSTR;
1993 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
1994 $opts{ymax},$opts{fill}{fill});
1997 my $color = _color($opts{'color'});
1999 $self->{ERRSTR} = $Imager::ERRSTR;
2002 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2008 # Draws an arc - this routine SUCKS and is buggy - it sometimes doesn't work when the arc is a convex polygon
2012 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2013 my $dflcl=i_color_new(255,255,255,255);
2014 my %opts=(color=>$dflcl,
2015 'r'=>min($self->getwidth(),$self->getheight())/3,
2016 'x'=>$self->getwidth()/2,
2017 'y'=>$self->getheight()/2,
2018 'd1'=>0, 'd2'=>361, @_);
2020 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2021 # assume it's a hash ref
2022 require 'Imager/Fill.pm';
2023 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2024 $self->{ERRSTR} = $Imager::ERRSTR;
2028 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2029 $opts{'d2'}, $opts{fill}{fill});
2032 my $color = _color($opts{'color'});
2034 $self->{ERRSTR} = $Imager::ERRSTR;
2037 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2038 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2042 if ($opts{'d1'} <= $opts{'d2'}) {
2043 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2044 $opts{'d1'}, $opts{'d2'}, $color);
2047 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2048 $opts{'d1'}, 361, $color);
2049 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2050 0, $opts{'d2'}, $color);
2058 # Draws a line from one point to the other
2059 # the endpoint is set if the endp parameter is set which it is by default.
2060 # to turn of the endpoint being set use endp=>0 when calling line.
2064 my $dflcl=i_color_new(0,0,0,0);
2065 my %opts=(color=>$dflcl,
2068 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2070 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2071 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2073 my $color = _color($opts{'color'});
2075 $self->{ERRSTR} = $Imager::ERRSTR;
2079 $opts{antialias} = $opts{aa} if defined $opts{aa};
2080 if ($opts{antialias}) {
2081 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2082 $color, $opts{endp});
2084 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2085 $color, $opts{endp});
2090 # Draws a line between an ordered set of points - It more or less just transforms this
2091 # into a list of lines.
2095 my ($pt,$ls,@points);
2096 my $dflcl=i_color_new(0,0,0,0);
2097 my %opts=(color=>$dflcl,@_);
2099 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2101 if (exists($opts{points})) { @points=@{$opts{points}}; }
2102 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2103 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2106 # print Dumper(\@points);
2108 my $color = _color($opts{'color'});
2110 $self->{ERRSTR} = $Imager::ERRSTR;
2113 $opts{antialias} = $opts{aa} if defined $opts{aa};
2114 if ($opts{antialias}) {
2117 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2124 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2134 my ($pt,$ls,@points);
2135 my $dflcl = i_color_new(0,0,0,0);
2136 my %opts = (color=>$dflcl, @_);
2138 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2140 if (exists($opts{points})) {
2141 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2142 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2145 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2146 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2149 if ($opts{'fill'}) {
2150 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2151 # assume it's a hash ref
2152 require 'Imager/Fill.pm';
2153 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2154 $self->{ERRSTR} = $Imager::ERRSTR;
2158 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2159 $opts{'fill'}{'fill'});
2162 my $color = _color($opts{'color'});
2164 $self->{ERRSTR} = $Imager::ERRSTR;
2167 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2174 # this the multipoint bezier curve
2175 # this is here more for testing that actual usage since
2176 # this is not a good algorithm. Usually the curve would be
2177 # broken into smaller segments and each done individually.
2181 my ($pt,$ls,@points);
2182 my $dflcl=i_color_new(0,0,0,0);
2183 my %opts=(color=>$dflcl,@_);
2185 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2187 if (exists $opts{points}) {
2188 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2189 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2192 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2193 $self->{ERRSTR}='Missing or invalid points.';
2197 my $color = _color($opts{'color'});
2199 $self->{ERRSTR} = $Imager::ERRSTR;
2202 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2208 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2211 unless (exists $opts{'x'} && exists $opts{'y'}) {
2212 $self->{ERRSTR} = "missing seed x and y parameters";
2217 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2218 # assume it's a hash ref
2219 require 'Imager/Fill.pm';
2220 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2221 $self->{ERRSTR} = $Imager::ERRSTR;
2225 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2228 my $color = _color($opts{'color'});
2230 $self->{ERRSTR} = $Imager::ERRSTR;
2233 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2235 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2241 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2243 unless (exists $opts{'x'} && exists $opts{'y'}) {
2244 $self->{ERRSTR} = 'missing x and y parameters';
2250 my $color = _color($opts{color})
2252 if (ref $x && ref $y) {
2253 unless (@$x == @$y) {
2254 $self->{ERRSTR} = 'length of x and y mismatch';
2257 if ($color->isa('Imager::Color')) {
2258 for my $i (0..$#{$opts{'x'}}) {
2259 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2263 for my $i (0..$#{$opts{'x'}}) {
2264 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2269 if ($color->isa('Imager::Color')) {
2270 i_ppix($self->{IMG}, $x, $y, $color);
2273 i_ppixf($self->{IMG}, $x, $y, $color);
2283 my %opts = ( "type"=>'8bit', @_);
2285 unless (exists $opts{'x'} && exists $opts{'y'}) {
2286 $self->{ERRSTR} = 'missing x and y parameters';
2292 if (ref $x && ref $y) {
2293 unless (@$x == @$y) {
2294 $self->{ERRSTR} = 'length of x and y mismatch';
2298 if ($opts{"type"} eq '8bit') {
2299 for my $i (0..$#{$opts{'x'}}) {
2300 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2304 for my $i (0..$#{$opts{'x'}}) {
2305 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2308 return wantarray ? @result : \@result;
2311 if ($opts{"type"} eq '8bit') {
2312 return i_get_pixel($self->{IMG}, $x, $y);
2315 return i_gpixf($self->{IMG}, $x, $y);
2322 # make an identity matrix of the given size
2326 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2327 for my $c (0 .. ($size-1)) {
2328 $matrix->[$c][$c] = 1;
2333 # general function to convert an image
2335 my ($self, %opts) = @_;
2338 # the user can either specify a matrix or preset
2339 # the matrix overrides the preset
2340 if (!exists($opts{matrix})) {
2341 unless (exists($opts{preset})) {
2342 $self->{ERRSTR} = "convert() needs a matrix or preset";
2346 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2347 # convert to greyscale, keeping the alpha channel if any
2348 if ($self->getchannels == 3) {
2349 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2351 elsif ($self->getchannels == 4) {
2352 # preserve the alpha channel
2353 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2358 $matrix = _identity($self->getchannels);
2361 elsif ($opts{preset} eq 'noalpha') {
2362 # strip the alpha channel
2363 if ($self->getchannels == 2 or $self->getchannels == 4) {
2364 $matrix = _identity($self->getchannels);
2365 pop(@$matrix); # lose the alpha entry
2368 $matrix = _identity($self->getchannels);
2371 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2373 $matrix = [ [ 1 ] ];
2375 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2376 $matrix = [ [ 0, 1 ] ];
2378 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2379 $matrix = [ [ 0, 0, 1 ] ];
2381 elsif ($opts{preset} eq 'alpha') {
2382 if ($self->getchannels == 2 or $self->getchannels == 4) {
2383 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2386 # the alpha is just 1 <shrug>
2387 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2390 elsif ($opts{preset} eq 'rgb') {
2391 if ($self->getchannels == 1) {
2392 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2394 elsif ($self->getchannels == 2) {
2395 # preserve the alpha channel
2396 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2399 $matrix = _identity($self->getchannels);
2402 elsif ($opts{preset} eq 'addalpha') {
2403 if ($self->getchannels == 1) {
2404 $matrix = _identity(2);
2406 elsif ($self->getchannels == 3) {
2407 $matrix = _identity(4);
2410 $matrix = _identity($self->getchannels);
2414 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2420 $matrix = $opts{matrix};
2423 my $new = Imager->new();
2424 $new->{IMG} = i_img_new();
2425 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2426 # most likely a bad matrix
2427 $self->{ERRSTR} = _error_as_msg();
2434 # general function to map an image through lookup tables
2437 my ($self, %opts) = @_;
2438 my @chlist = qw( red green blue alpha );
2440 if (!exists($opts{'maps'})) {
2441 # make maps from channel maps
2443 for $chnum (0..$#chlist) {
2444 if (exists $opts{$chlist[$chnum]}) {
2445 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2446 } elsif (exists $opts{'all'}) {
2447 $opts{'maps'}[$chnum] = $opts{'all'};
2451 if ($opts{'maps'} and $self->{IMG}) {
2452 i_map($self->{IMG}, $opts{'maps'} );
2458 my ($self, %opts) = @_;
2460 defined $opts{mindist} or $opts{mindist} = 0;
2462 defined $opts{other}
2463 or return $self->_set_error("No 'other' parameter supplied");
2464 defined $opts{other}{IMG}
2465 or return $self->_set_error("No image data in 'other' image");
2468 or return $self->_set_error("No image data");
2470 my $result = Imager->new;
2471 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2473 or return $self->_set_error($self->_error_as_msg());
2478 # destructive border - image is shrunk by one pixel all around
2481 my ($self,%opts)=@_;
2482 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2483 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2487 # Get the width of an image
2491 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2492 return (i_img_info($self->{IMG}))[0];
2495 # Get the height of an image
2499 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2500 return (i_img_info($self->{IMG}))[1];
2503 # Get number of channels in an image
2507 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2508 return i_img_getchannels($self->{IMG});
2515 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2516 return i_img_getmask($self->{IMG});
2524 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2525 i_img_setmask( $self->{IMG} , $opts{mask} );
2528 # Get number of colors in an image
2532 my %opts=('maxcolors'=>2**30,@_);
2533 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2534 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2535 return ($rc==-1? undef : $rc);
2538 # draw string to an image
2542 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2544 my %input=('x'=>0, 'y'=>0, @_);
2545 $input{string}||=$input{text};
2547 unless(exists $input{string}) {
2548 $self->{ERRSTR}="missing required parameter 'string'";
2552 unless($input{font}) {
2553 $self->{ERRSTR}="missing required parameter 'font'";
2557 unless ($input{font}->draw(image=>$self, %input)) {
2558 $self->{ERRSTR} = $self->_error_as_msg();
2565 # Shortcuts that can be exported
2567 sub newcolor { Imager::Color->new(@_); }
2568 sub newfont { Imager::Font->new(@_); }
2570 *NC=*newcolour=*newcolor;
2577 #### Utility routines
2580 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2584 my ($self, $msg) = @_;
2587 $self->{ERRSTR} = $msg;
2595 # Default guess for the type of an image from extension
2597 sub def_guess_type {
2600 $ext=($name =~ m/\.([^\.]+)$/)[0];
2601 return 'tiff' if ($ext =~ m/^tiff?$/);
2602 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2603 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2604 return 'png' if ($ext eq "png");
2605 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2606 return 'tga' if ($ext eq "tga");
2607 return 'rgb' if ($ext eq "rgb");
2608 return 'gif' if ($ext eq "gif");
2609 return 'raw' if ($ext eq "raw");
2613 # get the minimum of a list
2617 for(@_) { if ($_<$mx) { $mx=$_; }}
2621 # get the maximum of a list
2625 for(@_) { if ($_>$mx) { $mx=$_; }}
2629 # string stuff for iptc headers
2633 $str = substr($str,3);
2634 $str =~ s/[\n\r]//g;
2641 # A little hack to parse iptc headers.
2646 my($caption,$photogr,$headln,$credit);
2648 my $str=$self->{IPTCRAW};
2652 @ar=split(/8BIM/,$str);
2657 @sar=split(/\034\002/);
2658 foreach $item (@sar) {
2659 if ($item =~ m/^x/) {
2660 $caption=&clean($item);
2663 if ($item =~ m/^P/) {
2664 $photogr=&clean($item);
2667 if ($item =~ m/^i/) {
2668 $headln=&clean($item);
2671 if ($item =~ m/^n/) {
2672 $credit=&clean($item);
2678 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
2681 # Autoload methods go after =cut, and are processed by the autosplit program.
2685 # Below is the stub of documentation for your module. You better edit it!
2689 Imager - Perl extension for Generating 24 bit Images
2699 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
2704 my $img = Imager->new();
2705 # see Imager::Files for information on the open() method
2706 $img->open(file=>$file) or die $img->errstr();
2708 $file =~ s/\.[^.]*$//;
2710 # Create smaller version
2711 # documented in Imager::Transformations
2712 my $thumb = $img->scale(scalefactor=>.3);
2714 # Autostretch individual channels
2715 $thumb->filter(type=>'autolevels');
2717 # try to save in one of these formats
2720 for $format ( qw( png gif jpg tiff ppm ) ) {
2721 # Check if given format is supported
2722 if ($Imager::formats{$format}) {
2723 $file.="_low.$format";
2724 print "Storing image as: $file\n";
2725 # documented in Imager::Files
2726 $thumb->write(file=>$file) or
2734 Imager is a module for creating and altering images. It can read and
2735 write various image formats, draw primitive shapes like lines,and
2736 polygons, blend multiple images together in various ways, scale, crop,
2737 render text and more.
2739 =head2 Overview of documentation
2745 Imager - This document - Synopsis Example, Table of Contents and
2750 L<Imager::ImageTypes> - Basics of constructing image objects with
2751 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
2752 8/16/double bits/channel, color maps, channel masks, image tags, color
2753 quantization. Also discusses basic image information methods.
2757 L<Imager::Files> - IO interaction, reading/writing images, format
2762 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
2767 L<Imager::Color> - Color specification.
2771 L<Imager::Fill> - Fill pattern specification.
2775 L<Imager::Font> - General font rendering, bounding boxes and font
2780 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
2781 blending, pasting, convert and map.
2785 L<Imager::Engines> - Programmable transformations through
2786 C<transform()>, C<transform2()> and C<matrix_transform()>.
2790 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
2795 L<Imager::Expr> - Expressions for evaluation engine used by
2800 L<Imager::Matrix2d> - Helper class for affine transformations.
2804 L<Imager::Fountain> - Helper for making gradient profiles.
2808 =head2 Basic Overview
2810 An Image object is created with C<$img = Imager-E<gt>new()>.
2813 $img=Imager->new(); # create empty image
2814 $img->open(file=>'lena.png',type=>'png') or # read image from file
2815 die $img->errstr(); # give an explanation
2816 # if something failed
2818 or if you want to create an empty image:
2820 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
2822 This example creates a completely black image of width 400 and height
2825 When an operation fails which can be directly associated with an image
2826 the error message is stored can be retrieved with
2827 C<$img-E<gt>errstr()>.
2829 In cases where no image object is associated with an operation
2830 C<$Imager::ERRSTR> is used to report errors not directly associated
2831 with an image object. You can also call C<Imager->errstr> to get this
2834 The C<Imager-E<gt>new> method is described in detail in
2835 L<Imager::ImageTypes>.
2839 Where to find information on methods for Imager class objects.
2841 addcolors() - L<Imager::ImageTypes>
2843 addtag() - L<Imager::ImageTypes> - add image tags
2845 arc() - L<Imager::Draw/arc>
2847 bits() - L<Imager::ImageTypes> - number of bits per sample for the
2850 box() - L<Imager::Draw/box>
2852 circle() - L<Imager::Draw/circle>
2854 convert() - L<Imager::Transformations/"Color transformations"> -
2855 transform the color space
2857 copy() - L<Imager::Transformations/copy>
2859 crop() - L<Imager::Transformations/crop> - extract part of an image
2861 deltag() - L<Imager::ImageTypes> - delete image tags
2863 difference() - L<Imager::Filters/"Image Difference">
2865 errstr() - L<Imager/"Basic Overview">
2867 filter() - L<Imager::Filters>
2869 findcolor() - L<Imager::ImageTypes> - search the image palette, if it
2872 flip() - L<Imager::Transformations/flip>
2874 flood_fill() - L<Imager::Draw/flood_fill>
2876 getchannels() - L<Imager::ImageTypes>
2878 getcolorcount() - L<Imager::ImageTypes>
2880 getcolors() - L<Imager::ImageTypes> - get colors from the image
2881 palette, if it has one
2883 getheight() - L<Imager::ImageTypes>
2885 getpixel() - L<Imager::Draw/setpixel and getpixel>
2887 getwidth() - L<Imager::ImageTypes>
2889 img_set() - L<Imager::ImageTypes>
2891 line() - L<Imager::Draw/line>
2893 map() - L<Imager::Transformations/"Color Mappings"> - remap color
2896 masked() - L<Imager::ImageTypes> - make a masked image
2898 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
2900 new() - L<Imager::ImageTypes>
2902 paste() - L<Imager::Transformations/paste> - draw an image onto an image
2904 polygon() - L<Imager::Draw/polygon>
2906 polyline() - L<Imager::Draw/polyline>
2908 read() - L<Imager::Files>
2910 read_multi() - L<Imager::Files>
2912 rotate() - L<Imager::Transformations/rotate>
2914 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
2915 image and use the alpha channel
2917 scale() - L<Imager::Transformations/scale>
2919 setcolors() - L<Imager::ImageTypes> - set palette colors in a paletted image
2921 setpixel() - L<Imager::Draw/setpixel and getpixel>
2923 string() - L<Imager::Font/string> - draw text on an image
2925 tags() - L<Imager::ImageTypes> - fetch image tags
2927 to_paletted() - L<Imager::ImageTypes>
2929 to_rgb8() - L<Imager::ImageTypes>
2931 transform() - L<Imager::Engines/"transform">
2933 transform2() - L<Imager::Engines/"transform2">
2935 type() - L<Imager::ImageTypes> - type of image (direct vs paletted)
2937 virtual() - L<Imager::ImageTypes> - whether the image has it's own
2940 write() - L<Imager::Files>
2942 write_multi() - L<Imager::Files>
2944 =head1 CONCEPT INDEX
2946 animated GIF - L<Imager::File/"Writing an animated GIF">
2948 aspect ratio - L<Imager::ImageTypes/i_xres>,
2949 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
2951 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
2953 boxes, drawing - L<Imager::Draw/box>
2955 color - L<Imager::Color>
2957 color names - L<Imager::Color>, L<Imager::Color::Table>
2959 combine modes - L<Imager::Fill/combine>
2961 cropping - L<Imager::Transformations/crop>
2963 dpi - L<Imager::ImageTypes/i_xres>
2965 drawing boxes - L<Imager::Draw/box>
2967 drawing lines - L<Imager::Draw/line>
2969 drawing text - L<Imager::Font/string>
2971 error message - L<Imager/"Basic Overview">
2973 files, font - L<Imager::Font>
2975 files, image - L<Imager::Files>
2977 filling, types of fill - L<Imager::Fill>
2979 filling, boxes - L<Imager::Draw/box>
2981 filling, flood fill - L<Imager::Draw/flood_fill>
2983 flood fill - L<Imager::Draw/flood_fill>
2985 fonts - L<Imager::Font>
2987 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
2988 L<Imager::Font::Wrap>
2990 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
2992 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
2994 fountain fill - L<Imager::Fill/"Fountain fills">,
2995 L<Imager::Filters/fountain>, L<Imager::Fountain>,
2996 L<Imager::Filters/gradgen>
2998 gradient fill - L<Imager::Fill/"Fountain fills">,
2999 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3000 L<Imager::Filters/gradgen>
3002 hatch fills - L<Imager::Fill/"Hatched fills">
3004 JPEG - L<Imager::Files/"JPEG">
3006 lines, drawing - L<Imager::Draw/line>
3008 metadata, image - L<Imager::ImageTypes/"Tags">
3010 png - L<Imager::Files/"PNG">
3012 pnm - L<Imager::Files/"PNM (Portable aNy Map">
3014 rectangles, drawing - L<Imager::Draw/box>
3016 resizing an image - L<Imager::Transformations/scale>,
3017 L<Imager::Transformations/crop>
3019 saving an image - L<Imager::Files>
3021 scaling - L<Imager::Transformations/scale>
3023 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3025 size, image - L<Imager::ImageTypes/getwidth>,
3026 L<Imager::ImageTypes/getheight>
3028 size, text - L<Imager::Font/bounding_box>
3030 text, drawing - L<Imager::Font/string>, L<Imager::Font/align>,
3031 L<Imager::Font::Wrap>
3033 text, wrapping text in an area - L<Imager::Font::Wrap>
3035 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3037 writing an image - L<Imager::Files>
3041 You can ask for help, report bugs or express your undying love for
3042 Imager on the Imager-devel mailing list.
3044 To subscribe send a message with C<subscribe> in the body to:
3046 imager-devel+request@molar.is
3050 http://www.molar.is/en/lists/imager-devel/
3051 (annonymous is temporarily off due to spam)
3053 where you can also find the mailing list archive.
3055 If you're into IRC, you can typically find the developers in #Imager
3056 on irc.perl.org. As with any IRC channel, the participants could be
3057 occupied or asleep, so please be patient.
3059 You can report bugs either by sending email to:
3061 bug-Imager@rt.cpan.org
3063 or by pointing your browser at:
3065 https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager
3067 Please remember to include the versions of Imager, perl, supporting
3068 libraries, and any relevant code. If you have specific images that
3069 cause the problems, please include those too.
3073 Bugs are listed individually for relevant pod pages.
3077 Arnar M. Hrafnkelsson (addi@imager.perl.org) and Tony Cook
3078 (tony@imager.perl.org) See the README for a complete list.
3082 perl(1), Imager::ImageTypes(3), Imager::Files(3), Imager::Draw(3),
3083 Imager::Color(3), Imager::Fill(3), Imager::Font(3),
3084 Imager::Transformations(3), Imager::Engines(3), Imager::Filters(3),
3085 Imager::Expr(3), Imager::Matrix2d(3), Imager::Fountain(3)
3087 Affix::Infix2Postfix(3), Parse::RecDescent(3)
3088 http://imager.perl.org/