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 unless (defined wantarray) {
555 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
559 my $newcopy=Imager->new();
560 $newcopy->{IMG}=i_img_new();
561 i_copy($newcopy->{IMG},$self->{IMG});
569 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
570 my %input=(left=>0, top=>0, @_);
571 unless($input{img}) {
572 $self->{ERRSTR}="no source image";
575 $input{left}=0 if $input{left} <= 0;
576 $input{top}=0 if $input{top} <= 0;
578 my($r,$b)=i_img_info($src->{IMG});
580 i_copyto($self->{IMG}, $src->{IMG},
581 0,0, $r, $b, $input{left}, $input{top});
582 return $self; # What should go here??
585 # Crop an image - i.e. return a new image that is smaller
589 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
591 unless (defined wantarray) {
593 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
599 my ($w, $h, $l, $r, $b, $t) =
600 @hsh{qw(width height left right bottom top)};
602 # work through the various possibilities
607 elsif (!defined $r) {
608 $r = $self->getwidth;
620 $l = int(0.5+($self->getwidth()-$w)/2);
625 $r = $self->getwidth;
631 elsif (!defined $b) {
632 $b = $self->getheight;
644 $t=int(0.5+($self->getheight()-$h)/2);
649 $b = $self->getheight;
652 ($l,$r)=($r,$l) if $l>$r;
653 ($t,$b)=($b,$t) if $t>$b;
656 $r > $self->getwidth and $r = $self->getwidth;
658 $b > $self->getheight and $b = $self->getheight;
660 if ($l == $r || $t == $b) {
661 $self->_set_error("resulting image would have no content");
665 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
667 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
672 my ($self, %opts) = @_;
674 $self->{IMG} or return $self->_set_error("Not a valid image");
676 my $x = $opts{xsize} || $self->getwidth;
677 my $y = $opts{ysize} || $self->getheight;
678 my $channels = $opts{channels} || $self->getchannels;
680 my $out = Imager->new;
681 if ($channels == $self->getchannels) {
682 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
685 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
687 unless ($out->{IMG}) {
688 $self->{ERRSTR} = $self->_error_as_msg;
695 # Sets an image to a certain size and channel number
696 # if there was previously data in the image it is discarded
701 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
703 if (defined($self->{IMG})) {
704 # let IIM_DESTROY destroy it, it's possible this image is
705 # referenced from a virtual image (like masked)
706 #i_img_destroy($self->{IMG});
710 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
711 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
712 $hsh{maxcolors} || 256);
714 elsif ($hsh{bits} eq 'double') {
715 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
717 elsif ($hsh{bits} == 16) {
718 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
721 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
725 unless ($self->{IMG}) {
726 $self->{ERRSTR} = Imager->_error_as_msg();
733 # created a masked version of the current image
737 $self or return undef;
738 my %opts = (left => 0,
740 right => $self->getwidth,
741 bottom => $self->getheight,
743 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
745 my $result = Imager->new;
746 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
747 $opts{top}, $opts{right} - $opts{left},
748 $opts{bottom} - $opts{top});
749 # keep references to the mask and base images so they don't
751 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
756 # convert an RGB image into a paletted image
760 if (@_ != 1 && !ref $_[0]) {
767 unless (defined wantarray) {
769 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
773 my $result = Imager->new;
774 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
776 #print "Type ", i_img_type($result->{IMG}), "\n";
778 if ($result->{IMG}) {
782 $self->{ERRSTR} = $self->_error_as_msg;
787 # convert a paletted (or any image) to an 8-bit/channel RGB images
792 unless (defined wantarray) {
794 warn "to_rgb8() called in void context - to_rgb8() returns the cropped image at $caller[1] line $caller[2]\n";
799 $result = Imager->new;
800 $result->{IMG} = i_img_to_rgb($self->{IMG})
809 my %opts = (colors=>[], @_);
811 @{$opts{colors}} or return undef;
813 $self->{IMG} and i_addcolors($self->{IMG}, @{$opts{colors}});
818 my %opts = (start=>0, colors=>[], @_);
819 @{$opts{colors}} or return undef;
821 $self->{IMG} and i_setcolors($self->{IMG}, $opts{start}, @{$opts{colors}});
827 if (!exists $opts{start} && !exists $opts{count}) {
830 $opts{count} = $self->colorcount;
832 elsif (!exists $opts{count}) {
835 elsif (!exists $opts{start}) {
840 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
844 i_colorcount($_[0]{IMG});
848 i_maxcolors($_[0]{IMG});
854 $opts{color} or return undef;
856 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
861 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
862 if ($bits && $bits == length(pack("d", 1)) * 8) {
871 return i_img_type($self->{IMG}) ? "paletted" : "direct";
877 $self->{IMG} and i_img_virtual($self->{IMG});
881 my ($self, %opts) = @_;
883 $self->{IMG} or return;
885 if (defined $opts{name}) {
889 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
890 push @result, (i_tags_get($self->{IMG}, $found))[1];
893 return wantarray ? @result : $result[0];
895 elsif (defined $opts{code}) {
899 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
900 push @result, (i_tags_get($self->{IMG}, $found))[1];
907 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
910 return i_tags_count($self->{IMG});
919 return -1 unless $self->{IMG};
921 if (defined $opts{value}) {
922 if ($opts{value} =~ /^\d+$/) {
924 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
927 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
930 elsif (defined $opts{data}) {
931 # force addition as a string
932 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
935 $self->{ERRSTR} = "No value supplied";
939 elsif ($opts{code}) {
940 if (defined $opts{value}) {
941 if ($opts{value} =~ /^\d+$/) {
943 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
946 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
949 elsif (defined $opts{data}) {
950 # force addition as a string
951 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
954 $self->{ERRSTR} = "No value supplied";
967 return 0 unless $self->{IMG};
969 if (defined $opts{'index'}) {
970 return i_tags_delete($self->{IMG}, $opts{'index'});
972 elsif (defined $opts{name}) {
973 return i_tags_delbyname($self->{IMG}, $opts{name});
975 elsif (defined $opts{code}) {
976 return i_tags_delbycode($self->{IMG}, $opts{code});
979 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
985 my ($self, %opts) = @_;
988 $self->deltag(name=>$opts{name});
989 return $self->addtag(name=>$opts{name}, value=>$opts{value});
991 elsif (defined $opts{code}) {
992 $self->deltag(code=>$opts{code});
993 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1001 sub _get_reader_io {
1002 my ($self, $input) = @_;
1005 return $input->{io}, undef;
1007 elsif ($input->{fd}) {
1008 return io_new_fd($input->{fd});
1010 elsif ($input->{fh}) {
1011 my $fd = fileno($input->{fh});
1013 $self->_set_error("Handle in fh option not opened");
1016 return io_new_fd($fd);
1018 elsif ($input->{file}) {
1019 my $file = IO::File->new($input->{file}, "r");
1021 $self->_set_error("Could not open $input->{file}: $!");
1025 return (io_new_fd(fileno($file)), $file);
1027 elsif ($input->{data}) {
1028 return io_new_buffer($input->{data});
1030 elsif ($input->{callback} || $input->{readcb}) {
1031 if (!$input->{seekcb}) {
1032 $self->_set_error("Need a seekcb parameter");
1034 if ($input->{maxbuffer}) {
1035 return io_new_cb($input->{writecb},
1036 $input->{callback} || $input->{readcb},
1037 $input->{seekcb}, $input->{closecb},
1038 $input->{maxbuffer});
1041 return io_new_cb($input->{writecb},
1042 $input->{callback} || $input->{readcb},
1043 $input->{seekcb}, $input->{closecb});
1047 $self->_set_error("file/fd/fh/data/callback parameter missing");
1052 sub _get_writer_io {
1053 my ($self, $input, $type) = @_;
1056 return io_new_fd($input->{fd});
1058 elsif ($input->{fh}) {
1059 my $fd = fileno($input->{fh});
1061 $self->_set_error("Handle in fh option not opened");
1065 my $oldfh = select($input->{fh});
1066 # flush anything that's buffered, and make sure anything else is flushed
1069 return io_new_fd($fd);
1071 elsif ($input->{file}) {
1072 my $fh = new IO::File($input->{file},"w+");
1074 $self->_set_error("Could not open file $input->{file}: $!");
1077 binmode($fh) or die;
1078 return (io_new_fd(fileno($fh)), $fh);
1080 elsif ($input->{data}) {
1081 return io_new_bufchain();
1083 elsif ($input->{callback} || $input->{writecb}) {
1084 if ($input->{maxbuffer}) {
1085 return io_new_cb($input->{callback} || $input->{writecb},
1087 $input->{seekcb}, $input->{closecb},
1088 $input->{maxbuffer});
1091 return io_new_cb($input->{callback} || $input->{writecb},
1093 $input->{seekcb}, $input->{closecb});
1097 $self->_set_error("file/fd/fh/data/callback parameter missing");
1102 # Read an image from file
1108 if (defined($self->{IMG})) {
1109 # let IIM_DESTROY do the destruction, since the image may be
1110 # referenced from elsewhere
1111 #i_img_destroy($self->{IMG});
1112 undef($self->{IMG});
1115 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1117 unless ($input{'type'}) {
1118 $input{'type'} = i_test_format_probe($IO, -1);
1121 unless ($input{'type'}) {
1122 $self->_set_error('type parameter missing and not possible to guess from extension');
1126 unless ($formats{$input{'type'}}) {
1127 $self->_set_error("format '$input{'type'}' not supported");
1132 if ( $input{'type'} eq 'jpeg' ) {
1133 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1134 if ( !defined($self->{IMG}) ) {
1135 $self->{ERRSTR}='unable to read jpeg image'; return undef;
1137 $self->{DEBUG} && print "loading a jpeg file\n";
1141 if ( $input{'type'} eq 'tiff' ) {
1142 $self->{IMG}=i_readtiff_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1143 if ( !defined($self->{IMG}) ) {
1144 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1146 $self->{DEBUG} && print "loading a tiff file\n";
1150 if ( $input{'type'} eq 'pnm' ) {
1151 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1152 if ( !defined($self->{IMG}) ) {
1153 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg(); return undef;
1155 $self->{DEBUG} && print "loading a pnm file\n";
1159 if ( $input{'type'} eq 'png' ) {
1160 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1161 if ( !defined($self->{IMG}) ) {
1162 $self->{ERRSTR}='unable to read png image';
1165 $self->{DEBUG} && print "loading a png file\n";
1168 if ( $input{'type'} eq 'bmp' ) {
1169 $self->{IMG}=i_readbmp_wiol( $IO );
1170 if ( !defined($self->{IMG}) ) {
1171 $self->{ERRSTR}=$self->_error_as_msg();
1174 $self->{DEBUG} && print "loading a bmp file\n";
1177 if ( $input{'type'} eq 'gif' ) {
1178 if ($input{colors} && !ref($input{colors})) {
1179 # must be a reference to a scalar that accepts the colour map
1180 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1183 if ($input{colors}) {
1185 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1187 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1191 $self->{IMG} =i_readgif_wiol( $IO );
1193 if ( !defined($self->{IMG}) ) {
1194 $self->{ERRSTR}=$self->_error_as_msg();
1197 $self->{DEBUG} && print "loading a gif file\n";
1200 if ( $input{'type'} eq 'tga' ) {
1201 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1202 if ( !defined($self->{IMG}) ) {
1203 $self->{ERRSTR}=$self->_error_as_msg();
1206 $self->{DEBUG} && print "loading a tga file\n";
1209 if ( $input{'type'} eq 'rgb' ) {
1210 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1211 if ( !defined($self->{IMG}) ) {
1212 $self->{ERRSTR}=$self->_error_as_msg();
1215 $self->{DEBUG} && print "loading a tga file\n";
1219 if ( $input{'type'} eq 'raw' ) {
1220 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1222 if ( !($params{xsize} && $params{ysize}) ) {
1223 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1227 $self->{IMG} = i_readraw_wiol( $IO,
1230 $params{datachannels},
1231 $params{storechannels},
1232 $params{interleave});
1233 if ( !defined($self->{IMG}) ) {
1234 $self->{ERRSTR}='unable to read raw image';
1237 $self->{DEBUG} && print "loading a raw file\n";
1243 sub _fix_gif_positions {
1244 my ($opts, $opt, $msg, @imgs) = @_;
1246 my $positions = $opts->{'gif_positions'};
1248 for my $pos (@$positions) {
1249 my ($x, $y) = @$pos;
1250 my $img = $imgs[$index++];
1251 $img->settag(name=>'gif_left', value=>$x);
1252 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1254 $$msg .= "replaced with the gif_left and gif_top tags";
1259 gif_each_palette=>'gif_local_map',
1260 interlace => 'gif_interlace',
1261 gif_delays => 'gif_delay',
1262 gif_positions => \&_fix_gif_positions,
1263 gif_loop_count => 'gif_loop',
1267 my ($self, $opts, $prefix, @imgs) = @_;
1269 for my $opt (keys %$opts) {
1271 if ($obsolete_opts{$opt}) {
1272 my $new = $obsolete_opts{$opt};
1273 my $msg = "Obsolete option $opt ";
1275 $new->($opts, $opt, \$msg, @imgs);
1278 $msg .= "replaced with the $new tag ";
1281 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1282 warn $msg if $warn_obsolete && $^W;
1284 next unless $tagname =~ /^\Q$prefix/;
1285 my $value = $opts->{$opt};
1287 if (UNIVERSAL::isa($value, "Imager::Color")) {
1288 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1289 for my $img (@imgs) {
1290 $img->settag(name=>$tagname, value=>$tag);
1293 elsif (ref($value) eq 'ARRAY') {
1294 for my $i (0..$#$value) {
1295 my $val = $value->[$i];
1297 if (UNIVERSAL::isa($val, "Imager::Color")) {
1298 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1300 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1303 $self->_set_error("Unknown reference type " . ref($value) .
1304 " supplied in array for $opt");
1310 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1315 $self->_set_error("Unknown reference type " . ref($value) .
1316 " supplied for $opt");
1321 # set it as a tag for every image
1322 for my $img (@imgs) {
1323 $img->settag(name=>$tagname, value=>$value);
1331 # Write an image to file
1334 my %input=(jpegquality=>75,
1344 $self->_set_opts(\%input, "i_", $self)
1347 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1349 if (!$input{'type'} and $input{file}) {
1350 $input{'type'}=$FORMATGUESS->($input{file});
1352 if (!$input{'type'}) {
1353 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1357 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1359 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1362 if ($input{'type'} eq 'tiff') {
1363 $self->_set_opts(\%input, "tiff_", $self)
1365 $self->_set_opts(\%input, "exif_", $self)
1368 if (defined $input{class} && $input{class} eq 'fax') {
1369 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1370 $self->{ERRSTR}='Could not write to buffer';
1374 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1375 $self->{ERRSTR}='Could not write to buffer';
1379 } elsif ( $input{'type'} eq 'pnm' ) {
1380 $self->_set_opts(\%input, "pnm_", $self)
1382 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1383 $self->{ERRSTR}='unable to write pnm image';
1386 $self->{DEBUG} && print "writing a pnm file\n";
1387 } elsif ( $input{'type'} eq 'raw' ) {
1388 $self->_set_opts(\%input, "raw_", $self)
1390 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1391 $self->{ERRSTR}='unable to write raw image';
1394 $self->{DEBUG} && print "writing a raw file\n";
1395 } elsif ( $input{'type'} eq 'png' ) {
1396 $self->_set_opts(\%input, "png_", $self)
1398 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1399 $self->{ERRSTR}='unable to write png image';
1402 $self->{DEBUG} && print "writing a png file\n";
1403 } elsif ( $input{'type'} eq 'jpeg' ) {
1404 $self->_set_opts(\%input, "jpeg_", $self)
1406 $self->_set_opts(\%input, "exif_", $self)
1408 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1409 $self->{ERRSTR} = $self->_error_as_msg();
1412 $self->{DEBUG} && print "writing a jpeg file\n";
1413 } elsif ( $input{'type'} eq 'bmp' ) {
1414 $self->_set_opts(\%input, "bmp_", $self)
1416 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1417 $self->{ERRSTR}='unable to write bmp image';
1420 $self->{DEBUG} && print "writing a bmp file\n";
1421 } elsif ( $input{'type'} eq 'tga' ) {
1422 $self->_set_opts(\%input, "tga_", $self)
1425 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1426 $self->{ERRSTR}=$self->_error_as_msg();
1429 $self->{DEBUG} && print "writing a tga file\n";
1430 } elsif ( $input{'type'} eq 'gif' ) {
1431 $self->_set_opts(\%input, "gif_", $self)
1433 # compatibility with the old interfaces
1434 if ($input{gifquant} eq 'lm') {
1435 $input{make_colors} = 'addi';
1436 $input{translate} = 'perturb';
1437 $input{perturb} = $input{lmdither};
1438 } elsif ($input{gifquant} eq 'gen') {
1439 # just pass options through
1441 $input{make_colors} = 'webmap'; # ignored
1442 $input{translate} = 'giflib';
1444 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1445 $self->{ERRSTR} = $self->_error_as_msg;
1450 if (exists $input{'data'}) {
1451 my $data = io_slurp($IO);
1453 $self->{ERRSTR}='Could not slurp from buffer';
1456 ${$input{data}} = $data;
1462 my ($class, $opts, @images) = @_;
1464 if (!$opts->{'type'} && $opts->{'file'}) {
1465 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1467 unless ($opts->{'type'}) {
1468 $class->_set_error('type parameter missing and not possible to guess from extension');
1471 # translate to ImgRaw
1472 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1473 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1476 $class->_set_opts($opts, "i_", @images)
1478 my @work = map $_->{IMG}, @images;
1479 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1481 if ($opts->{'type'} eq 'gif') {
1482 $class->_set_opts($opts, "gif_", @images)
1484 my $gif_delays = $opts->{gif_delays};
1485 local $opts->{gif_delays} = $gif_delays;
1486 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1487 # assume the caller wants the same delay for each frame
1488 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1490 my $res = i_writegif_wiol($IO, $opts, @work);
1491 $res or $class->_set_error($class->_error_as_msg());
1494 elsif ($opts->{'type'} eq 'tiff') {
1495 $class->_set_opts($opts, "tiff_", @images)
1497 $class->_set_opts($opts, "exif_", @images)
1500 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1501 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1502 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1505 $res = i_writetiff_multi_wiol($IO, @work);
1507 $res or $class->_set_error($class->_error_as_msg());
1511 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1516 # read multiple images from a file
1518 my ($class, %opts) = @_;
1520 if ($opts{file} && !exists $opts{'type'}) {
1522 my $type = $FORMATGUESS->($opts{file});
1523 $opts{'type'} = $type;
1525 unless ($opts{'type'}) {
1526 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1530 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1532 if ($opts{'type'} eq 'gif') {
1534 @imgs = i_readgif_multi_wiol($IO);
1537 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1541 $ERRSTR = _error_as_msg();
1545 elsif ($opts{'type'} eq 'tiff') {
1546 my @imgs = i_readtiff_multi_wiol($IO, -1);
1549 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1553 $ERRSTR = _error_as_msg();
1558 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1562 # Destroy an Imager object
1566 # delete $instances{$self};
1567 if (defined($self->{IMG})) {
1568 # the following is now handled by the XS DESTROY method for
1569 # Imager::ImgRaw object
1570 # Re-enabling this will break virtual images
1571 # tested for in t/t020masked.t
1572 # i_img_destroy($self->{IMG});
1573 undef($self->{IMG});
1575 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1579 # Perform an inplace filter of an image
1580 # that is the image will be overwritten with the data
1586 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1588 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1590 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1591 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1594 if ($filters{$input{'type'}}{names}) {
1595 my $names = $filters{$input{'type'}}{names};
1596 for my $name (keys %$names) {
1597 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1598 $input{$name} = $names->{$name}{$input{$name}};
1602 if (defined($filters{$input{'type'}}{defaults})) {
1603 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1605 %hsh=('image',$self->{IMG},%input);
1608 my @cs=@{$filters{$input{'type'}}{callseq}};
1611 if (!defined($hsh{$_})) {
1612 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1616 &{$filters{$input{'type'}}{callsub}}(%hsh);
1620 $self->{DEBUG} && print "callseq is: @cs\n";
1621 $self->{DEBUG} && print "matching callseq is: @b\n";
1626 # Scale an image to requested size and return the scaled version
1630 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1631 my $img = Imager->new();
1632 my $tmp = Imager->new();
1634 unless (defined wantarray) {
1635 my @caller = caller;
1636 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1640 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1642 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1643 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1644 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1645 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1646 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1647 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1649 if ($opts{qtype} eq 'normal') {
1650 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1651 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1652 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1653 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1656 if ($opts{'qtype'} eq 'preview') {
1657 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1658 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1661 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1664 # Scales only along the X axis
1668 my %opts=(scalefactor=>0.5,@_);
1670 unless (defined wantarray) {
1671 my @caller = caller;
1672 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1676 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1678 my $img = Imager->new();
1680 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1682 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1683 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1685 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1689 # Scales only along the Y axis
1693 my %opts=(scalefactor=>0.5,@_);
1695 unless (defined wantarray) {
1696 my @caller = caller;
1697 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1701 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1703 my $img = Imager->new();
1705 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1707 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1708 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1710 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1715 # Transform returns a spatial transformation of the input image
1716 # this moves pixels to a new location in the returned image.
1717 # NOTE - should make a utility function to check transforms for
1722 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1724 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1726 # print Dumper(\%opts);
1729 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1731 eval ("use Affix::Infix2Postfix;");
1734 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1737 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1738 {op=>'-',trans=>'Sub'},
1739 {op=>'*',trans=>'Mult'},
1740 {op=>'/',trans=>'Div'},
1741 {op=>'-','type'=>'unary',trans=>'u-'},
1743 {op=>'func','type'=>'unary'}],
1744 'grouping'=>[qw( \( \) )],
1745 'func'=>[qw( sin cos )],
1750 @xt=$I2P->translate($opts{'xexpr'});
1751 @yt=$I2P->translate($opts{'yexpr'});
1753 $numre=$I2P->{'numre'};
1756 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1757 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1758 @{$opts{'parm'}}=@pt;
1761 # print Dumper(\%opts);
1763 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1764 $self->{ERRSTR}='transform: no xopcodes given.';
1768 @op=@{$opts{'xopcodes'}};
1770 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1771 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1774 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1780 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1781 $self->{ERRSTR}='transform: no yopcodes given.';
1785 @op=@{$opts{'yopcodes'}};
1787 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1788 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1791 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1796 if ( !exists $opts{'parm'}) {
1797 $self->{ERRSTR}='transform: no parameter arg given.';
1801 # print Dumper(\@ropx);
1802 # print Dumper(\@ropy);
1803 # print Dumper(\@ropy);
1805 my $img = Imager->new();
1806 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1807 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1813 my ($opts, @imgs) = @_;
1815 require "Imager/Expr.pm";
1817 $opts->{variables} = [ qw(x y) ];
1818 my ($width, $height) = @{$opts}{qw(width height)};
1820 $width ||= $imgs[0]->getwidth();
1821 $height ||= $imgs[0]->getheight();
1823 for my $img (@imgs) {
1824 $opts->{constants}{"w$img_num"} = $img->getwidth();
1825 $opts->{constants}{"h$img_num"} = $img->getheight();
1826 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1827 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1832 $opts->{constants}{w} = $width;
1833 $opts->{constants}{cx} = $width/2;
1836 $Imager::ERRSTR = "No width supplied";
1840 $opts->{constants}{h} = $height;
1841 $opts->{constants}{cy} = $height/2;
1844 $Imager::ERRSTR = "No height supplied";
1847 my $code = Imager::Expr->new($opts);
1849 $Imager::ERRSTR = Imager::Expr::error();
1852 my $channels = $opts->{channels} || 3;
1853 unless ($channels >= 1 && $channels <= 4) {
1854 return Imager->_set_error("channels must be an integer between 1 and 4");
1857 my $img = Imager->new();
1858 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1859 $channels, $code->code(),
1860 $code->nregs(), $code->cregs(),
1861 [ map { $_->{IMG} } @imgs ]);
1862 if (!defined $img->{IMG}) {
1863 $Imager::ERRSTR = Imager->_error_as_msg();
1872 my %opts=(tx => 0,ty => 0, @_);
1874 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1875 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1877 %opts = (src_minx => 0,
1879 src_maxx => $opts{src}->getwidth(),
1880 src_maxy => $opts{src}->getheight(),
1883 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1884 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1885 $self->{ERRSTR} = $self->_error_as_msg();
1895 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
1897 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
1898 $dir = $xlate{$opts{'dir'}};
1899 return $self if i_flipxy($self->{IMG}, $dir);
1907 unless (defined wantarray) {
1908 my @caller = caller;
1909 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
1913 if (defined $opts{right}) {
1914 my $degrees = $opts{right};
1916 $degrees += 360 * int(((-$degrees)+360)/360);
1918 $degrees = $degrees % 360;
1919 if ($degrees == 0) {
1920 return $self->copy();
1922 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
1923 my $result = Imager->new();
1924 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
1928 $self->{ERRSTR} = $self->_error_as_msg();
1933 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
1937 elsif (defined $opts{radians} || defined $opts{degrees}) {
1938 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
1940 my $result = Imager->new;
1942 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
1945 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
1947 if ($result->{IMG}) {
1951 $self->{ERRSTR} = $self->_error_as_msg();
1956 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
1961 sub matrix_transform {
1965 unless (defined wantarray) {
1966 my @caller = caller;
1967 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
1971 if ($opts{matrix}) {
1972 my $xsize = $opts{xsize} || $self->getwidth;
1973 my $ysize = $opts{ysize} || $self->getheight;
1975 my $result = Imager->new;
1977 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1978 $opts{matrix}, $opts{back})
1982 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1990 $self->{ERRSTR} = "matrix parameter required";
1996 *yatf = \&matrix_transform;
1998 # These two are supported for legacy code only
2001 return Imager::Color->new(@_);
2005 return Imager::Color::set(@_);
2008 # Draws a box between the specified corner points.
2011 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2012 my $dflcl=i_color_new(255,255,255,255);
2013 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2015 if (exists $opts{'box'}) {
2016 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
2017 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
2018 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
2019 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
2022 if ($opts{filled}) {
2023 my $color = _color($opts{'color'});
2025 $self->{ERRSTR} = $Imager::ERRSTR;
2028 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2029 $opts{ymax}, $color);
2031 elsif ($opts{fill}) {
2032 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2033 # assume it's a hash ref
2034 require 'Imager/Fill.pm';
2035 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2036 $self->{ERRSTR} = $Imager::ERRSTR;
2040 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2041 $opts{ymax},$opts{fill}{fill});
2044 my $color = _color($opts{'color'});
2046 $self->{ERRSTR} = $Imager::ERRSTR;
2049 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2055 # Draws an arc - this routine SUCKS and is buggy - it sometimes doesn't work when the arc is a convex polygon
2059 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2060 my $dflcl=i_color_new(255,255,255,255);
2061 my %opts=(color=>$dflcl,
2062 'r'=>min($self->getwidth(),$self->getheight())/3,
2063 'x'=>$self->getwidth()/2,
2064 'y'=>$self->getheight()/2,
2065 'd1'=>0, 'd2'=>361, @_);
2067 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2068 # assume it's a hash ref
2069 require 'Imager/Fill.pm';
2070 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2071 $self->{ERRSTR} = $Imager::ERRSTR;
2075 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2076 $opts{'d2'}, $opts{fill}{fill});
2079 my $color = _color($opts{'color'});
2081 $self->{ERRSTR} = $Imager::ERRSTR;
2084 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2085 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2089 if ($opts{'d1'} <= $opts{'d2'}) {
2090 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2091 $opts{'d1'}, $opts{'d2'}, $color);
2094 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2095 $opts{'d1'}, 361, $color);
2096 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2097 0, $opts{'d2'}, $color);
2105 # Draws a line from one point to the other
2106 # the endpoint is set if the endp parameter is set which it is by default.
2107 # to turn of the endpoint being set use endp=>0 when calling line.
2111 my $dflcl=i_color_new(0,0,0,0);
2112 my %opts=(color=>$dflcl,
2115 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2117 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2118 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2120 my $color = _color($opts{'color'});
2122 $self->{ERRSTR} = $Imager::ERRSTR;
2126 $opts{antialias} = $opts{aa} if defined $opts{aa};
2127 if ($opts{antialias}) {
2128 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2129 $color, $opts{endp});
2131 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2132 $color, $opts{endp});
2137 # Draws a line between an ordered set of points - It more or less just transforms this
2138 # into a list of lines.
2142 my ($pt,$ls,@points);
2143 my $dflcl=i_color_new(0,0,0,0);
2144 my %opts=(color=>$dflcl,@_);
2146 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2148 if (exists($opts{points})) { @points=@{$opts{points}}; }
2149 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2150 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2153 # print Dumper(\@points);
2155 my $color = _color($opts{'color'});
2157 $self->{ERRSTR} = $Imager::ERRSTR;
2160 $opts{antialias} = $opts{aa} if defined $opts{aa};
2161 if ($opts{antialias}) {
2164 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2171 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
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 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2193 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2196 if ($opts{'fill'}) {
2197 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2198 # assume it's a hash ref
2199 require 'Imager/Fill.pm';
2200 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2201 $self->{ERRSTR} = $Imager::ERRSTR;
2205 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2206 $opts{'fill'}{'fill'});
2209 my $color = _color($opts{'color'});
2211 $self->{ERRSTR} = $Imager::ERRSTR;
2214 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2221 # this the multipoint bezier curve
2222 # this is here more for testing that actual usage since
2223 # this is not a good algorithm. Usually the curve would be
2224 # broken into smaller segments and each done individually.
2228 my ($pt,$ls,@points);
2229 my $dflcl=i_color_new(0,0,0,0);
2230 my %opts=(color=>$dflcl,@_);
2232 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2234 if (exists $opts{points}) {
2235 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2236 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2239 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2240 $self->{ERRSTR}='Missing or invalid points.';
2244 my $color = _color($opts{'color'});
2246 $self->{ERRSTR} = $Imager::ERRSTR;
2249 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2255 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2258 unless (exists $opts{'x'} && exists $opts{'y'}) {
2259 $self->{ERRSTR} = "missing seed x and y parameters";
2264 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2265 # assume it's a hash ref
2266 require 'Imager/Fill.pm';
2267 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2268 $self->{ERRSTR} = $Imager::ERRSTR;
2272 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2275 my $color = _color($opts{'color'});
2277 $self->{ERRSTR} = $Imager::ERRSTR;
2280 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2282 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2288 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2290 unless (exists $opts{'x'} && exists $opts{'y'}) {
2291 $self->{ERRSTR} = 'missing x and y parameters';
2297 my $color = _color($opts{color})
2299 if (ref $x && ref $y) {
2300 unless (@$x == @$y) {
2301 $self->{ERRSTR} = 'length of x and y mismatch';
2304 if ($color->isa('Imager::Color')) {
2305 for my $i (0..$#{$opts{'x'}}) {
2306 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2310 for my $i (0..$#{$opts{'x'}}) {
2311 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2316 if ($color->isa('Imager::Color')) {
2317 i_ppix($self->{IMG}, $x, $y, $color);
2320 i_ppixf($self->{IMG}, $x, $y, $color);
2330 my %opts = ( "type"=>'8bit', @_);
2332 unless (exists $opts{'x'} && exists $opts{'y'}) {
2333 $self->{ERRSTR} = 'missing x and y parameters';
2339 if (ref $x && ref $y) {
2340 unless (@$x == @$y) {
2341 $self->{ERRSTR} = 'length of x and y mismatch';
2345 if ($opts{"type"} eq '8bit') {
2346 for my $i (0..$#{$opts{'x'}}) {
2347 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2351 for my $i (0..$#{$opts{'x'}}) {
2352 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2355 return wantarray ? @result : \@result;
2358 if ($opts{"type"} eq '8bit') {
2359 return i_get_pixel($self->{IMG}, $x, $y);
2362 return i_gpixf($self->{IMG}, $x, $y);
2369 # make an identity matrix of the given size
2373 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2374 for my $c (0 .. ($size-1)) {
2375 $matrix->[$c][$c] = 1;
2380 # general function to convert an image
2382 my ($self, %opts) = @_;
2385 unless (defined wantarray) {
2386 my @caller = caller;
2387 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2391 # the user can either specify a matrix or preset
2392 # the matrix overrides the preset
2393 if (!exists($opts{matrix})) {
2394 unless (exists($opts{preset})) {
2395 $self->{ERRSTR} = "convert() needs a matrix or preset";
2399 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2400 # convert to greyscale, keeping the alpha channel if any
2401 if ($self->getchannels == 3) {
2402 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2404 elsif ($self->getchannels == 4) {
2405 # preserve the alpha channel
2406 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2411 $matrix = _identity($self->getchannels);
2414 elsif ($opts{preset} eq 'noalpha') {
2415 # strip the alpha channel
2416 if ($self->getchannels == 2 or $self->getchannels == 4) {
2417 $matrix = _identity($self->getchannels);
2418 pop(@$matrix); # lose the alpha entry
2421 $matrix = _identity($self->getchannels);
2424 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2426 $matrix = [ [ 1 ] ];
2428 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2429 $matrix = [ [ 0, 1 ] ];
2431 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2432 $matrix = [ [ 0, 0, 1 ] ];
2434 elsif ($opts{preset} eq 'alpha') {
2435 if ($self->getchannels == 2 or $self->getchannels == 4) {
2436 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2439 # the alpha is just 1 <shrug>
2440 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2443 elsif ($opts{preset} eq 'rgb') {
2444 if ($self->getchannels == 1) {
2445 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2447 elsif ($self->getchannels == 2) {
2448 # preserve the alpha channel
2449 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2452 $matrix = _identity($self->getchannels);
2455 elsif ($opts{preset} eq 'addalpha') {
2456 if ($self->getchannels == 1) {
2457 $matrix = _identity(2);
2459 elsif ($self->getchannels == 3) {
2460 $matrix = _identity(4);
2463 $matrix = _identity($self->getchannels);
2467 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2473 $matrix = $opts{matrix};
2476 my $new = Imager->new();
2477 $new->{IMG} = i_img_new();
2478 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2479 # most likely a bad matrix
2480 $self->{ERRSTR} = _error_as_msg();
2487 # general function to map an image through lookup tables
2490 my ($self, %opts) = @_;
2491 my @chlist = qw( red green blue alpha );
2493 if (!exists($opts{'maps'})) {
2494 # make maps from channel maps
2496 for $chnum (0..$#chlist) {
2497 if (exists $opts{$chlist[$chnum]}) {
2498 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2499 } elsif (exists $opts{'all'}) {
2500 $opts{'maps'}[$chnum] = $opts{'all'};
2504 if ($opts{'maps'} and $self->{IMG}) {
2505 i_map($self->{IMG}, $opts{'maps'} );
2511 my ($self, %opts) = @_;
2513 defined $opts{mindist} or $opts{mindist} = 0;
2515 defined $opts{other}
2516 or return $self->_set_error("No 'other' parameter supplied");
2517 defined $opts{other}{IMG}
2518 or return $self->_set_error("No image data in 'other' image");
2521 or return $self->_set_error("No image data");
2523 my $result = Imager->new;
2524 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2526 or return $self->_set_error($self->_error_as_msg());
2531 # destructive border - image is shrunk by one pixel all around
2534 my ($self,%opts)=@_;
2535 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2536 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2540 # Get the width of an image
2544 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2545 return (i_img_info($self->{IMG}))[0];
2548 # Get the height of an image
2552 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2553 return (i_img_info($self->{IMG}))[1];
2556 # Get number of channels in an image
2560 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2561 return i_img_getchannels($self->{IMG});
2568 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2569 return i_img_getmask($self->{IMG});
2577 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2578 i_img_setmask( $self->{IMG} , $opts{mask} );
2581 # Get number of colors in an image
2585 my %opts=('maxcolors'=>2**30,@_);
2586 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2587 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2588 return ($rc==-1? undef : $rc);
2591 # draw string to an image
2595 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2597 my %input=('x'=>0, 'y'=>0, @_);
2598 $input{string}||=$input{text};
2600 unless(exists $input{string}) {
2601 $self->{ERRSTR}="missing required parameter 'string'";
2605 unless($input{font}) {
2606 $self->{ERRSTR}="missing required parameter 'font'";
2610 unless ($input{font}->draw(image=>$self, %input)) {
2611 $self->{ERRSTR} = $self->_error_as_msg();
2618 # Shortcuts that can be exported
2620 sub newcolor { Imager::Color->new(@_); }
2621 sub newfont { Imager::Font->new(@_); }
2623 *NC=*newcolour=*newcolor;
2630 #### Utility routines
2633 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2637 my ($self, $msg) = @_;
2640 $self->{ERRSTR} = $msg;
2648 # Default guess for the type of an image from extension
2650 sub def_guess_type {
2653 $ext=($name =~ m/\.([^\.]+)$/)[0];
2654 return 'tiff' if ($ext =~ m/^tiff?$/);
2655 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2656 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2657 return 'png' if ($ext eq "png");
2658 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2659 return 'tga' if ($ext eq "tga");
2660 return 'rgb' if ($ext eq "rgb");
2661 return 'gif' if ($ext eq "gif");
2662 return 'raw' if ($ext eq "raw");
2666 # get the minimum of a list
2670 for(@_) { if ($_<$mx) { $mx=$_; }}
2674 # get the maximum of a list
2678 for(@_) { if ($_>$mx) { $mx=$_; }}
2682 # string stuff for iptc headers
2686 $str = substr($str,3);
2687 $str =~ s/[\n\r]//g;
2694 # A little hack to parse iptc headers.
2699 my($caption,$photogr,$headln,$credit);
2701 my $str=$self->{IPTCRAW};
2705 @ar=split(/8BIM/,$str);
2710 @sar=split(/\034\002/);
2711 foreach $item (@sar) {
2712 if ($item =~ m/^x/) {
2713 $caption=&clean($item);
2716 if ($item =~ m/^P/) {
2717 $photogr=&clean($item);
2720 if ($item =~ m/^i/) {
2721 $headln=&clean($item);
2724 if ($item =~ m/^n/) {
2725 $credit=&clean($item);
2731 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
2734 # Autoload methods go after =cut, and are processed by the autosplit program.
2738 # Below is the stub of documentation for your module. You better edit it!
2742 Imager - Perl extension for Generating 24 bit Images
2752 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
2757 my $img = Imager->new();
2758 # see Imager::Files for information on the read() method
2759 $img->read(file=>$file) or die $img->errstr();
2761 $file =~ s/\.[^.]*$//;
2763 # Create smaller version
2764 # documented in Imager::Transformations
2765 my $thumb = $img->scale(scalefactor=>.3);
2767 # Autostretch individual channels
2768 $thumb->filter(type=>'autolevels');
2770 # try to save in one of these formats
2773 for $format ( qw( png gif jpg tiff ppm ) ) {
2774 # Check if given format is supported
2775 if ($Imager::formats{$format}) {
2776 $file.="_low.$format";
2777 print "Storing image as: $file\n";
2778 # documented in Imager::Files
2779 $thumb->write(file=>$file) or
2787 Imager is a module for creating and altering images. It can read and
2788 write various image formats, draw primitive shapes like lines,and
2789 polygons, blend multiple images together in various ways, scale, crop,
2790 render text and more.
2792 =head2 Overview of documentation
2798 Imager - This document - Synopsis Example, Table of Contents and
2803 L<Imager::Cookbook> - how to do various things with Imager.
2807 L<Imager::ImageTypes> - Basics of constructing image objects with
2808 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
2809 8/16/double bits/channel, color maps, channel masks, image tags, color
2810 quantization. Also discusses basic image information methods.
2814 L<Imager::Files> - IO interaction, reading/writing images, format
2819 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
2824 L<Imager::Color> - Color specification.
2828 L<Imager::Fill> - Fill pattern specification.
2832 L<Imager::Font> - General font rendering, bounding boxes and font
2837 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
2838 blending, pasting, convert and map.
2842 L<Imager::Engines> - Programmable transformations through
2843 C<transform()>, C<transform2()> and C<matrix_transform()>.
2847 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
2852 L<Imager::Expr> - Expressions for evaluation engine used by
2857 L<Imager::Matrix2d> - Helper class for affine transformations.
2861 L<Imager::Fountain> - Helper for making gradient profiles.
2865 =head2 Basic Overview
2867 An Image object is created with C<$img = Imager-E<gt>new()>.
2870 $img=Imager->new(); # create empty image
2871 $img->read(file=>'lena.png',type=>'png') or # read image from file
2872 die $img->errstr(); # give an explanation
2873 # if something failed
2875 or if you want to create an empty image:
2877 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
2879 This example creates a completely black image of width 400 and height
2882 When an operation fails which can be directly associated with an image
2883 the error message is stored can be retrieved with
2884 C<$img-E<gt>errstr()>.
2886 In cases where no image object is associated with an operation
2887 C<$Imager::ERRSTR> is used to report errors not directly associated
2888 with an image object. You can also call C<Imager->errstr> to get this
2891 The C<Imager-E<gt>new> method is described in detail in
2892 L<Imager::ImageTypes>.
2896 Where to find information on methods for Imager class objects.
2898 addcolors() - L<Imager::ImageTypes>
2900 addtag() - L<Imager::ImageTypes> - add image tags
2902 arc() - L<Imager::Draw/arc>
2904 bits() - L<Imager::ImageTypes> - number of bits per sample for the
2907 box() - L<Imager::Draw/box>
2909 circle() - L<Imager::Draw/circle>
2911 convert() - L<Imager::Transformations/"Color transformations"> -
2912 transform the color space
2914 copy() - L<Imager::Transformations/copy>
2916 crop() - L<Imager::Transformations/crop> - extract part of an image
2918 deltag() - L<Imager::ImageTypes> - delete image tags
2920 difference() - L<Imager::Filters/"Image Difference">
2922 errstr() - L<Imager/"Basic Overview">
2924 filter() - L<Imager::Filters>
2926 findcolor() - L<Imager::ImageTypes> - search the image palette, if it
2929 flip() - L<Imager::Transformations/flip>
2931 flood_fill() - L<Imager::Draw/flood_fill>
2933 getchannels() - L<Imager::ImageTypes>
2935 getcolorcount() - L<Imager::ImageTypes>
2937 getcolors() - L<Imager::ImageTypes> - get colors from the image
2938 palette, if it has one
2940 getheight() - L<Imager::ImageTypes>
2942 getpixel() - L<Imager::Draw/setpixel and getpixel>
2944 getwidth() - L<Imager::ImageTypes>
2946 img_set() - L<Imager::ImageTypes>
2948 line() - L<Imager::Draw/line>
2950 map() - L<Imager::Transformations/"Color Mappings"> - remap color
2953 masked() - L<Imager::ImageTypes> - make a masked image
2955 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
2957 new() - L<Imager::ImageTypes>
2959 open() - L<Imager::Files> - an alias for read()
2961 paste() - L<Imager::Transformations/paste> - draw an image onto an image
2963 polygon() - L<Imager::Draw/polygon>
2965 polyline() - L<Imager::Draw/polyline>
2967 read() - L<Imager::Files> - read a single image from an image file
2969 read_multi() - L<Imager::Files> - read multiple images from an image
2972 rotate() - L<Imager::Transformations/rotate>
2974 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
2975 image and use the alpha channel
2977 scale() - L<Imager::Transformations/scale>
2979 scaleX() - L<Imager::Transformations/scaleX>
2981 scaleY() - L<Imager::Transformations/scaleY>
2983 setcolors() - L<Imager::ImageTypes> - set palette colors in a paletted image
2985 setpixel() - L<Imager::Draw/setpixel and getpixel>
2987 string() - L<Imager::Font/string> - draw text on an image
2989 tags() - L<Imager::ImageTypes> - fetch image tags
2991 to_paletted() - L<Imager::ImageTypes>
2993 to_rgb8() - L<Imager::ImageTypes>
2995 transform() - L<Imager::Engines/"transform">
2997 transform2() - L<Imager::Engines/"transform2">
2999 type() - L<Imager::ImageTypes> - type of image (direct vs paletted)
3001 virtual() - L<Imager::ImageTypes> - whether the image has it's own
3004 write() - L<Imager::Files> - write an image to a file
3006 write_multi() - L<Imager::Files> - write multiple image to an image
3009 =head1 CONCEPT INDEX
3011 animated GIF - L<Imager::File/"Writing an animated GIF">
3013 aspect ratio - L<Imager::ImageTypes/i_xres>,
3014 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3016 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3018 boxes, drawing - L<Imager::Draw/box>
3020 color - L<Imager::Color>
3022 color names - L<Imager::Color>, L<Imager::Color::Table>
3024 combine modes - L<Imager::Fill/combine>
3026 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3028 convolution - L<Imager::Filter/conv>
3030 cropping - L<Imager::Transformations/crop>
3032 dpi - L<Imager::ImageTypes/i_xres>
3034 drawing boxes - L<Imager::Draw/box>
3036 drawing lines - L<Imager::Draw/line>
3038 drawing text - L<Imager::Font/string>
3040 error message - L<Imager/"Basic Overview">
3042 files, font - L<Imager::Font>
3044 files, image - L<Imager::Files>
3046 filling, types of fill - L<Imager::Fill>
3048 filling, boxes - L<Imager::Draw/box>
3050 filling, flood fill - L<Imager::Draw/flood_fill>
3052 flood fill - L<Imager::Draw/flood_fill>
3054 fonts - L<Imager::Font>
3056 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3057 L<Imager::Font::Wrap>
3059 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3061 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3063 fountain fill - L<Imager::Fill/"Fountain fills">,
3064 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3065 L<Imager::Filters/gradgen>
3067 GIF files - L<Imager::Files/"GIF">
3069 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3071 gradient fill - L<Imager::Fill/"Fountain fills">,
3072 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3073 L<Imager::Filters/gradgen>
3075 guassian blur - L<Imager::Filter/guassian>
3077 hatch fills - L<Imager::Fill/"Hatched fills">
3079 invert image - L<Imager::Filter/hardinvert>
3081 JPEG - L<Imager::Files/"JPEG">
3083 lines, drawing - L<Imager::Draw/line>
3085 matrix - L<Imager::Matrix2d>,
3086 L<Imager::Transformations/"Matrix Transformations">,
3087 L<Imager::Font/transform>
3089 metadata, image - L<Imager::ImageTypes/"Tags">
3091 mosaic - L<Imager::Filter/mosaic>
3093 noise, filter - L<Imager::Filter/noise>
3095 noise, rendered - L<Imager::Filter/turbnoise>,
3096 L<Imager::Filter/radnoise>
3098 posterize - L<Imager::Filter/postlevels>
3100 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3102 pnm - L<Imager::Files/"PNM (Portable aNy Map">
3104 rectangles, drawing - L<Imager::Draw/box>
3106 resizing an image - L<Imager::Transformations/scale>,
3107 L<Imager::Transformations/crop>
3109 saving an image - L<Imager::Files>
3111 scaling - L<Imager::Transformations/scale>
3113 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3115 size, image - L<Imager::ImageTypes/getwidth>,
3116 L<Imager::ImageTypes/getheight>
3118 size, text - L<Imager::Font/bounding_box>
3120 text, drawing - L<Imager::Font/string>, L<Imager::Font/align>,
3121 L<Imager::Font::Wrap>
3123 text, wrapping text in an area - L<Imager::Font::Wrap>
3125 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3127 tiles, color - L<Imager::Filter/mosaic>
3129 unsharp mask - L<Imager::Filter/unsharpmask>
3131 watermark - L<Imager::Filter/watermark>
3133 writing an image - L<Imager::Files>
3137 You can ask for help, report bugs or express your undying love for
3138 Imager on the Imager-devel mailing list.
3140 To subscribe send a message with C<subscribe> in the body to:
3142 imager-devel+request@molar.is
3146 http://www.molar.is/en/lists/imager-devel/
3147 (annonymous is temporarily off due to spam)
3149 where you can also find the mailing list archive.
3151 If you're into IRC, you can typically find the developers in #Imager
3152 on irc.perl.org. As with any IRC channel, the participants could be
3153 occupied or asleep, so please be patient.
3155 You can report bugs either by sending email to:
3157 bug-Imager@rt.cpan.org
3159 or by pointing your browser at:
3161 https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager
3163 Please remember to include the versions of Imager, perl, supporting
3164 libraries, and any relevant code. If you have specific images that
3165 cause the problems, please include those too.
3169 Bugs are listed individually for relevant pod pages.
3173 Arnar M. Hrafnkelsson (addi@imager.perl.org) and Tony Cook
3174 (tony@imager.perl.org) See the README for a complete list.
3178 perl(1), Imager::ImageTypes(3), Imager::Files(3), Imager::Draw(3),
3179 Imager::Color(3), Imager::Fill(3), Imager::Font(3),
3180 Imager::Transformations(3), Imager::Engines(3), Imager::Filters(3),
3181 Imager::Expr(3), Imager::Matrix2d(3), Imager::Fountain(3)
3183 Affix::Infix2Postfix(3), Parse::RecDescent(3)
3184 http://imager.perl.org/