4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
109 # registered file readers
112 # registered file writers
115 # modules we attempted to autoload
116 my %attempted_to_load;
118 # errors from loading files
119 my %file_load_errors;
121 # what happened when we tried to load
122 my %reader_load_errors;
123 my %writer_load_errors;
125 # library keys that are image file formats
126 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
128 # image pixel combine types
130 qw/none normal multiply dissolve add subtract diff lighten darken
131 hue saturation value color/;
133 @combine_types{@combine_types} = 0 .. $#combine_types;
134 $combine_types{mult} = $combine_types{multiply};
135 $combine_types{'sub'} = $combine_types{subtract};
136 $combine_types{sat} = $combine_types{saturation};
138 # this will be used to store global defaults at some point
143 my $ex_version = eval $Exporter::VERSION;
144 if ($ex_version < 5.57) {
149 XSLoader::load(Imager => $VERSION);
155 png => "Imager::File::PNG",
156 gif => "Imager::File::GIF",
157 tiff => "Imager::File::TIFF",
158 jpeg => "Imager::File::JPEG",
159 w32 => "Imager::Font::W32",
160 ft2 => "Imager::Font::FT2",
161 t1 => "Imager::Font::T1",
164 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
167 for(i_list_formats()) { $formats_low{$_}++; }
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{hardinvertall} =
202 callseq => ['image'],
204 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
207 $filters{autolevels_skew} ={
208 callseq => ['image','lsat','usat','skew'],
209 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
210 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
213 $filters{autolevels} ={
214 callseq => ['image','lsat','usat'],
215 defaults => { lsat=>0.1,usat=>0.1 },
216 callsub => sub { my %hsh=@_; i_autolevels_mono($hsh{image},$hsh{lsat},$hsh{usat}); }
219 $filters{turbnoise} ={
220 callseq => ['image'],
221 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
222 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
225 $filters{radnoise} ={
226 callseq => ['image'],
227 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
228 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
233 callseq => ['image', 'coef'],
238 i_conv($hsh{image},$hsh{coef})
239 or die Imager->_error_as_msg() . "\n";
245 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
246 defaults => { dist => 0 },
250 my @colors = @{$hsh{colors}};
253 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
257 $filters{nearest_color} =
259 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
264 # make sure the segments are specified with colors
266 for my $color (@{$hsh{colors}}) {
267 my $new_color = _color($color)
268 or die $Imager::ERRSTR."\n";
269 push @colors, $new_color;
272 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
274 or die Imager->_error_as_msg() . "\n";
277 $filters{gaussian} = {
278 callseq => [ 'image', 'stddev' ],
280 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
284 callseq => [ qw(image size) ],
285 defaults => { size => 20 },
286 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
290 callseq => [ qw(image bump elevation lightx lighty st) ],
291 defaults => { elevation=>0, st=> 2 },
294 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
295 $hsh{lightx}, $hsh{lighty}, $hsh{st});
298 $filters{bumpmap_complex} =
300 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
317 for my $cname (qw/Ia Il Is/) {
318 my $old = $hsh{$cname};
319 my $new_color = _color($old)
320 or die $Imager::ERRSTR, "\n";
321 $hsh{$cname} = $new_color;
323 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
324 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
325 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
329 $filters{postlevels} =
331 callseq => [ qw(image levels) ],
332 defaults => { levels => 10 },
333 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
335 $filters{watermark} =
337 callseq => [ qw(image wmark tx ty pixdiff) ],
338 defaults => { pixdiff=>10, tx=>0, ty=>0 },
342 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
348 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
350 ftype => { linear => 0,
356 repeat => { none => 0,
371 multiply => 2, mult => 2,
374 subtract => 5, 'sub' => 5,
384 defaults => { ftype => 0, repeat => 0, combine => 0,
385 super_sample => 0, ssample_param => 4,
398 # make sure the segments are specified with colors
400 for my $segment (@{$hsh{segments}}) {
401 my @new_segment = @$segment;
403 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
404 push @segments, \@new_segment;
407 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
408 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
409 $hsh{ssample_param}, \@segments)
410 or die Imager->_error_as_msg() . "\n";
413 $filters{unsharpmask} =
415 callseq => [ qw(image stddev scale) ],
416 defaults => { stddev=>2.0, scale=>1.0 },
420 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
424 $FORMATGUESS=\&def_guess_type;
434 # NOTE: this might be moved to an import override later on
439 if ($_[$i] eq '-log-stderr') {
447 goto &Exporter::import;
451 Imager->open_log(log => $_[0], level => $_[1]);
456 my %parms=(loglevel=>1,@_);
458 if (exists $parms{'warn_obsolete'}) {
459 $warn_obsolete = $parms{'warn_obsolete'};
463 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
467 if (exists $parms{'t1log'}) {
469 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
470 Imager->_set_error(Imager->_error_as_msg);
484 my (%opts) = ( loglevel => 1, @_ );
486 $is_logging = i_init_log($opts{log}, $opts{loglevel});
487 unless ($is_logging) {
488 Imager->_set_error(Imager->_error_as_msg());
492 Imager->log("Imager $VERSION starting\n", 1);
498 i_init_log(undef, -1);
503 my ($class, $message, $level) = @_;
505 defined $level or $level = 1;
507 i_log_entry($message, $level);
517 print "shutdown code\n";
518 # for(keys %instances) { $instances{$_}->DESTROY(); }
519 malloc_state(); # how do decide if this should be used? -- store something from the import
520 print "Imager exiting\n";
524 # Load a filter plugin
530 if ($^O eq 'android') {
532 $filename = File::Spec->rel2abs($filename);
535 my ($DSO_handle,$str)=DSO_open($filename);
536 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
537 my %funcs=DSO_funclist($DSO_handle);
538 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
540 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
542 $DSOs{$filename}=[$DSO_handle,\%funcs];
545 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
546 $DEBUG && print "eval string:\n",$evstr,"\n";
558 if ($^O eq 'android') {
560 $filename = File::Spec->rel2abs($filename);
563 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
564 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
565 for(keys %{$funcref}) {
567 $DEBUG && print "unloading: $_\n";
569 my $rc=DSO_close($DSO_handle);
570 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
574 # take the results of i_error() and make a message out of it
576 return join(": ", map $_->[0], i_errors());
579 # this function tries to DWIM for color parameters
580 # color objects are used as is
581 # simple scalars are simply treated as single parameters to Imager::Color->new
582 # hashrefs are treated as named argument lists to Imager::Color->new
583 # arrayrefs are treated as list arguments to Imager::Color->new iff any
585 # other arrayrefs are treated as list arguments to Imager::Color::Float
589 # perl 5.6.0 seems to do weird things to $arg if we don't make an
590 # explicitly stringified copy
591 # I vaguely remember a bug on this on p5p, but couldn't find it
592 # through bugs.perl.org (I had trouble getting it to find any bugs)
593 my $copy = $arg . "";
597 if (UNIVERSAL::isa($arg, "Imager::Color")
598 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
602 if ($copy =~ /^HASH\(/) {
603 $result = Imager::Color->new(%$arg);
605 elsif ($copy =~ /^ARRAY\(/) {
606 $result = Imager::Color->new(@$arg);
609 $Imager::ERRSTR = "Not a color";
614 # assume Imager::Color::new knows how to handle it
615 $result = Imager::Color->new($arg);
622 my ($self, $combine, $default) = @_;
624 if (!defined $combine && ref $self) {
625 $combine = $self->{combine};
627 defined $combine or $combine = $defaults{combine};
628 defined $combine or $combine = $default;
630 if (exists $combine_types{$combine}) {
631 $combine = $combine_types{$combine};
638 my ($self, $method) = @_;
641 or return Imager->_set_error("$method needs an image object");
643 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
645 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
646 $msg = "$method: $msg" if $method;
647 $self->_set_error($msg);
652 # returns first defined parameter
655 return $_ if defined $_;
661 # Methods to be called on objects.
664 # Create a new Imager object takes very few parameters.
665 # usually you call this method and then call open from
666 # the resulting object
673 $self->{IMG}=undef; # Just to indicate what exists
674 $self->{ERRSTR}=undef; #
675 $self->{DEBUG}=$DEBUG;
676 $self->{DEBUG} and print "Initialized Imager\n";
677 if (defined $hsh{file} ||
680 defined $hsh{callback} ||
681 defined $hsh{readcb} ||
682 defined $hsh{data} ||
684 # allow $img = Imager->new(file => $filename)
687 # type is already used as a parameter to new(), rename it for the
689 if ($hsh{filetype}) {
690 $extras{type} = $hsh{filetype};
692 unless ($self->read(%hsh, %extras)) {
693 $Imager::ERRSTR = $self->{ERRSTR};
697 elsif (defined $hsh{xsize} || defined $hsh{ysize}) {
698 unless ($self->img_set(%hsh)) {
699 $Imager::ERRSTR = $self->{ERRSTR};
704 Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
711 # Copy an entire image with no changes
712 # - if an image has magic the copy of it will not be magical
717 $self->_valid_image("copy")
720 unless (defined wantarray) {
722 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
726 my $newcopy=Imager->new();
727 $newcopy->{IMG} = i_copy($self->{IMG});
736 $self->_valid_image("paste")
739 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
740 my $src = $input{img} || $input{src};
742 $self->_set_error("no source image");
745 unless ($src->_valid_image("paste")) {
746 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
749 $input{left}=0 if $input{left} <= 0;
750 $input{top}=0 if $input{top} <= 0;
752 my($r,$b)=i_img_info($src->{IMG});
753 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
754 my ($src_right, $src_bottom);
755 if ($input{src_coords}) {
756 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
759 if (defined $input{src_maxx}) {
760 $src_right = $input{src_maxx};
762 elsif (defined $input{width}) {
763 if ($input{width} <= 0) {
764 $self->_set_error("paste: width must me positive");
767 $src_right = $src_left + $input{width};
772 if (defined $input{src_maxy}) {
773 $src_bottom = $input{src_maxy};
775 elsif (defined $input{height}) {
776 if ($input{height} < 0) {
777 $self->_set_error("paste: height must be positive");
780 $src_bottom = $src_top + $input{height};
787 $src_right > $r and $src_right = $r;
788 $src_bottom > $b and $src_bottom = $b;
790 if ($src_right <= $src_left
791 || $src_bottom < $src_top) {
792 $self->_set_error("nothing to paste");
796 i_copyto($self->{IMG}, $src->{IMG},
797 $src_left, $src_top, $src_right, $src_bottom,
798 $input{left}, $input{top});
800 return $self; # What should go here??
803 # Crop an image - i.e. return a new image that is smaller
808 $self->_valid_image("crop")
811 unless (defined wantarray) {
813 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
819 my ($w, $h, $l, $r, $b, $t) =
820 @hsh{qw(width height left right bottom top)};
822 # work through the various possibilities
827 elsif (!defined $r) {
828 $r = $self->getwidth;
840 $l = int(0.5+($self->getwidth()-$w)/2);
845 $r = $self->getwidth;
851 elsif (!defined $b) {
852 $b = $self->getheight;
864 $t=int(0.5+($self->getheight()-$h)/2);
869 $b = $self->getheight;
872 ($l,$r)=($r,$l) if $l>$r;
873 ($t,$b)=($b,$t) if $t>$b;
876 $r > $self->getwidth and $r = $self->getwidth;
878 $b > $self->getheight and $b = $self->getheight;
880 if ($l == $r || $t == $b) {
881 $self->_set_error("resulting image would have no content");
884 if( $r < $l or $b < $t ) {
885 $self->_set_error("attempting to crop outside of the image");
888 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
890 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
895 my ($self, %opts) = @_;
900 my $x = $opts{xsize} || $self->getwidth;
901 my $y = $opts{ysize} || $self->getheight;
902 my $channels = $opts{channels} || $self->getchannels;
904 my $out = Imager->new;
905 if ($channels == $self->getchannels) {
906 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
909 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
911 unless ($out->{IMG}) {
912 $self->{ERRSTR} = $self->_error_as_msg;
919 # Sets an image to a certain size and channel number
920 # if there was previously data in the image it is discarded
933 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
938 if (my $channels = $model_channels{$hsh{model}}) {
939 $hsh{channels} = $channels;
942 $self->_set_error("new: unknown value for model '$hsh{model}'");
947 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
948 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
949 $hsh{maxcolors} || 256);
951 elsif ($hsh{bits} eq 'double') {
952 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
954 elsif ($hsh{bits} == 16) {
955 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
958 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
962 unless ($self->{IMG}) {
963 $self->_set_error(Imager->_error_as_msg());
970 # created a masked version of the current image
974 $self->_valid_image("masked")
977 my %opts = (left => 0,
979 right => $self->getwidth,
980 bottom => $self->getheight,
982 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
984 my $result = Imager->new;
985 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
986 $opts{top}, $opts{right} - $opts{left},
987 $opts{bottom} - $opts{top});
988 unless ($result->{IMG}) {
989 $self->_set_error(Imager->_error_as_msg);
993 # keep references to the mask and base images so they don't
995 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
1000 # convert an RGB image into a paletted image
1004 if (@_ != 1 && !ref $_[0]) {
1011 unless (defined wantarray) {
1012 my @caller = caller;
1013 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
1017 $self->_valid_image("to_paletted")
1020 my $result = Imager->new;
1021 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1022 $self->_set_error(Imager->_error_as_msg);
1030 my ($class, $quant, @images) = @_;
1033 Imager->_set_error("make_palette: supply at least one image");
1037 for my $img (@images) {
1038 unless ($img->{IMG}) {
1039 Imager->_set_error("make_palette: image $index is empty");
1045 my @cols = i_img_make_palette($quant, map $_->{IMG}, @images);
1047 Imager->_set_error(Imager->_error_as_msg);
1053 # convert a paletted (or any image) to an 8-bit/channel RGB image
1057 unless (defined wantarray) {
1058 my @caller = caller;
1059 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1063 $self->_valid_image("to_rgb8")
1066 my $result = Imager->new;
1067 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1068 $self->_set_error(Imager->_error_as_msg());
1075 # convert a paletted (or any image) to a 16-bit/channel RGB image
1079 unless (defined wantarray) {
1080 my @caller = caller;
1081 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1085 $self->_valid_image("to_rgb16")
1088 my $result = Imager->new;
1089 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1090 $self->_set_error(Imager->_error_as_msg());
1097 # convert a paletted (or any image) to an double/channel RGB image
1101 unless (defined wantarray) {
1102 my @caller = caller;
1103 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1107 $self->_valid_image("to_rgb_double")
1110 my $result = Imager->new;
1111 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1112 $self->_set_error(Imager->_error_as_msg());
1121 my %opts = (colors=>[], @_);
1123 $self->_valid_image("addcolors")
1126 my @colors = @{$opts{colors}}
1129 for my $color (@colors) {
1130 $color = _color($color);
1132 $self->_set_error($Imager::ERRSTR);
1137 return i_addcolors($self->{IMG}, @colors);
1142 my %opts = (start=>0, colors=>[], @_);
1144 $self->_valid_image("setcolors")
1147 my @colors = @{$opts{colors}}
1150 for my $color (@colors) {
1151 $color = _color($color);
1153 $self->_set_error($Imager::ERRSTR);
1158 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1165 $self->_valid_image("getcolors")
1168 if (!exists $opts{start} && !exists $opts{count}) {
1171 $opts{count} = $self->colorcount;
1173 elsif (!exists $opts{count}) {
1176 elsif (!exists $opts{start}) {
1180 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1186 $self->_valid_image("colorcount")
1189 return i_colorcount($self->{IMG});
1195 $self->_valid_image("maxcolors")
1198 i_maxcolors($self->{IMG});
1205 $self->_valid_image("findcolor")
1208 unless ($opts{color}) {
1209 $self->_set_error("findcolor: no color parameter");
1213 my $color = _color($opts{color})
1216 return i_findcolor($self->{IMG}, $color);
1222 $self->_valid_image("bits")
1225 my $bits = i_img_bits($self->{IMG});
1226 if ($bits && $bits == length(pack("d", 1)) * 8) {
1235 $self->_valid_image("type")
1238 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1244 $self->_valid_image("virtual")
1247 return i_img_virtual($self->{IMG});
1253 $self->_valid_image("is_bilevel")
1256 return i_img_is_monochrome($self->{IMG});
1260 my ($self, %opts) = @_;
1262 $self->_valid_image("tags")
1265 if (defined $opts{name}) {
1269 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1270 push @result, (i_tags_get($self->{IMG}, $found))[1];
1273 return wantarray ? @result : $result[0];
1275 elsif (defined $opts{code}) {
1279 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1280 push @result, (i_tags_get($self->{IMG}, $found))[1];
1287 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1290 return i_tags_count($self->{IMG});
1299 $self->_valid_image("addtag")
1303 if (defined $opts{value}) {
1304 if ($opts{value} =~ /^\d+$/) {
1306 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1309 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1312 elsif (defined $opts{data}) {
1313 # force addition as a string
1314 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1317 $self->{ERRSTR} = "No value supplied";
1321 elsif ($opts{code}) {
1322 if (defined $opts{value}) {
1323 if ($opts{value} =~ /^\d+$/) {
1325 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1328 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1331 elsif (defined $opts{data}) {
1332 # force addition as a string
1333 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1336 $self->{ERRSTR} = "No value supplied";
1349 $self->_valid_image("deltag")
1352 if (defined $opts{'index'}) {
1353 return i_tags_delete($self->{IMG}, $opts{'index'});
1355 elsif (defined $opts{name}) {
1356 return i_tags_delbyname($self->{IMG}, $opts{name});
1358 elsif (defined $opts{code}) {
1359 return i_tags_delbycode($self->{IMG}, $opts{code});
1362 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1368 my ($self, %opts) = @_;
1370 $self->_valid_image("settag")
1374 $self->deltag(name=>$opts{name});
1375 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1377 elsif (defined $opts{code}) {
1378 $self->deltag(code=>$opts{code});
1379 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1387 sub _get_reader_io {
1388 my ($self, $input) = @_;
1391 return $input->{io}, undef;
1393 elsif ($input->{fd}) {
1394 return io_new_fd($input->{fd});
1396 elsif ($input->{fh}) {
1397 unless (Scalar::Util::openhandle($input->{fh})) {
1398 $self->_set_error("Handle in fh option not opened");
1401 return Imager::IO->new_fh($input->{fh});
1403 elsif ($input->{file}) {
1404 my $file = IO::File->new($input->{file}, "r");
1406 $self->_set_error("Could not open $input->{file}: $!");
1410 return (io_new_fd(fileno($file)), $file);
1412 elsif ($input->{data}) {
1413 return io_new_buffer($input->{data});
1415 elsif ($input->{callback} || $input->{readcb}) {
1416 if (!$input->{seekcb}) {
1417 $self->_set_error("Need a seekcb parameter");
1419 if ($input->{maxbuffer}) {
1420 return io_new_cb($input->{writecb},
1421 $input->{callback} || $input->{readcb},
1422 $input->{seekcb}, $input->{closecb},
1423 $input->{maxbuffer});
1426 return io_new_cb($input->{writecb},
1427 $input->{callback} || $input->{readcb},
1428 $input->{seekcb}, $input->{closecb});
1432 $self->_set_error("file/fd/fh/data/callback parameter missing");
1437 sub _get_writer_io {
1438 my ($self, $input) = @_;
1440 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1447 elsif ($input->{fd}) {
1448 $io = io_new_fd($input->{fd});
1450 elsif ($input->{fh}) {
1451 unless (Scalar::Util::openhandle($input->{fh})) {
1452 $self->_set_error("Handle in fh option not opened");
1455 $io = Imager::IO->new_fh($input->{fh});
1457 elsif ($input->{file}) {
1458 my $fh = new IO::File($input->{file},"w+");
1460 $self->_set_error("Could not open file $input->{file}: $!");
1463 binmode($fh) or die;
1464 $io = io_new_fd(fileno($fh));
1467 elsif ($input->{data}) {
1468 $io = io_new_bufchain();
1470 elsif ($input->{callback} || $input->{writecb}) {
1471 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1474 $io = io_new_cb($input->{callback} || $input->{writecb},
1476 $input->{seekcb}, $input->{closecb});
1479 $self->_set_error("file/fd/fh/data/callback parameter missing");
1483 unless ($buffered) {
1484 $io->set_buffered(0);
1487 return ($io, @extras);
1493 return i_test_format_probe($io, -1);
1496 sub add_file_magic {
1497 my ($class, %opts) = @_;
1499 my $name = delete $opts{name};
1500 my $bits = delete $opts{bits};
1501 my $mask = delete $opts{mask};
1503 unless (i_add_file_magic($name, $bits, $mask)) {
1504 Imager->_set_error(Imager->_error_as_msg);
1511 # Read an image from file
1517 if (defined($self->{IMG})) {
1518 # let IIM_DESTROY do the destruction, since the image may be
1519 # referenced from elsewhere
1520 #i_img_destroy($self->{IMG});
1521 undef($self->{IMG});
1524 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1526 my $type = $input{'type'};
1528 $type = _test_format($IO);
1531 if ($input{file} && !$type) {
1533 $type = $FORMATGUESS->($input{file});
1537 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1538 $input{file} and $msg .= " or file name";
1539 $self->_set_error($msg);
1543 _reader_autoload($type);
1545 if ($readers{$type} && $readers{$type}{single}) {
1546 return $readers{$type}{single}->($self, $IO, %input);
1549 unless ($formats_low{$type}) {
1550 my $read_types = join ', ', sort Imager->read_types();
1551 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1555 my $allow_incomplete = $input{allow_incomplete};
1556 defined $allow_incomplete or $allow_incomplete = 0;
1558 if ( $type eq 'pnm' ) {
1559 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1560 if ( !defined($self->{IMG}) ) {
1561 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1564 $self->{DEBUG} && print "loading a pnm file\n";
1568 if ( $type eq 'bmp' ) {
1569 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1570 if ( !defined($self->{IMG}) ) {
1571 $self->{ERRSTR}=$self->_error_as_msg();
1574 $self->{DEBUG} && print "loading a bmp file\n";
1577 if ( $type eq 'tga' ) {
1578 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1579 if ( !defined($self->{IMG}) ) {
1580 $self->{ERRSTR}=$self->_error_as_msg();
1583 $self->{DEBUG} && print "loading a tga file\n";
1586 if ( $type eq 'raw' ) {
1587 unless ( $input{xsize} && $input{ysize} ) {
1588 $self->_set_error('missing xsize or ysize parameter for raw');
1592 my $interleave = _first($input{raw_interleave}, $input{interleave});
1593 unless (defined $interleave) {
1594 my @caller = caller;
1595 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1598 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1599 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1601 $self->{IMG} = i_readraw_wiol( $IO,
1607 if ( !defined($self->{IMG}) ) {
1608 $self->{ERRSTR}=$self->_error_as_msg();
1611 $self->{DEBUG} && print "loading a raw file\n";
1617 sub register_reader {
1618 my ($class, %opts) = @_;
1621 or die "register_reader called with no type parameter\n";
1623 my $type = $opts{type};
1625 defined $opts{single} || defined $opts{multiple}
1626 or die "register_reader called with no single or multiple parameter\n";
1628 $readers{$type} = { };
1629 if ($opts{single}) {
1630 $readers{$type}{single} = $opts{single};
1632 if ($opts{multiple}) {
1633 $readers{$type}{multiple} = $opts{multiple};
1639 sub register_writer {
1640 my ($class, %opts) = @_;
1643 or die "register_writer called with no type parameter\n";
1645 my $type = $opts{type};
1647 defined $opts{single} || defined $opts{multiple}
1648 or die "register_writer called with no single or multiple parameter\n";
1650 $writers{$type} = { };
1651 if ($opts{single}) {
1652 $writers{$type}{single} = $opts{single};
1654 if ($opts{multiple}) {
1655 $writers{$type}{multiple} = $opts{multiple};
1666 grep($file_formats{$_}, keys %formats),
1667 qw(ico sgi), # formats not handled directly, but supplied with Imager
1678 grep($file_formats{$_}, keys %formats),
1679 qw(ico sgi), # formats not handled directly, but supplied with Imager
1686 my ($file, $error) = @_;
1688 if ($attempted_to_load{$file}) {
1689 if ($file_load_errors{$file}) {
1690 $$error = $file_load_errors{$file};
1698 local $SIG{__DIE__};
1701 pop @INC if $INC[-1] eq '.';
1702 ++$attempted_to_load{$file};
1710 my $work = $@ || "Unknown error";
1712 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1713 $work =~ s/\n/\\n/g;
1714 $work =~ s/\s*\.?\z/ loading $file/;
1715 $file_load_errors{$file} = $work;
1722 # probes for an Imager::File::whatever module
1723 sub _reader_autoload {
1726 return if $formats_low{$type} || $readers{$type};
1728 return unless $type =~ /^\w+$/;
1730 my $file = "Imager/File/\U$type\E.pm";
1733 my $loaded = _load_file($file, \$error);
1734 if (!$loaded && $error =~ /^Can't locate /) {
1735 my $filer = "Imager/File/\U$type\EReader.pm";
1736 $loaded = _load_file($filer, \$error);
1737 if ($error =~ /^Can't locate /) {
1738 $error = "Can't locate $file or $filer";
1742 $reader_load_errors{$type} = $error;
1746 # probes for an Imager::File::whatever module
1747 sub _writer_autoload {
1750 return if $formats_low{$type} || $writers{$type};
1752 return unless $type =~ /^\w+$/;
1754 my $file = "Imager/File/\U$type\E.pm";
1757 my $loaded = _load_file($file, \$error);
1758 if (!$loaded && $error =~ /^Can't locate /) {
1759 my $filew = "Imager/File/\U$type\EWriter.pm";
1760 $loaded = _load_file($filew, \$error);
1761 if ($error =~ /^Can't locate /) {
1762 $error = "Can't locate $file or $filew";
1766 $writer_load_errors{$type} = $error;
1770 sub _fix_gif_positions {
1771 my ($opts, $opt, $msg, @imgs) = @_;
1773 my $positions = $opts->{'gif_positions'};
1775 for my $pos (@$positions) {
1776 my ($x, $y) = @$pos;
1777 my $img = $imgs[$index++];
1778 $img->settag(name=>'gif_left', value=>$x);
1779 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1781 $$msg .= "replaced with the gif_left and gif_top tags";
1786 gif_each_palette=>'gif_local_map',
1787 interlace => 'gif_interlace',
1788 gif_delays => 'gif_delay',
1789 gif_positions => \&_fix_gif_positions,
1790 gif_loop_count => 'gif_loop',
1793 # options that should be converted to colors
1794 my %color_opts = map { $_ => 1 } qw/i_background/;
1797 my ($self, $opts, $prefix, @imgs) = @_;
1799 for my $opt (keys %$opts) {
1801 if ($obsolete_opts{$opt}) {
1802 my $new = $obsolete_opts{$opt};
1803 my $msg = "Obsolete option $opt ";
1805 $new->($opts, $opt, \$msg, @imgs);
1808 $msg .= "replaced with the $new tag ";
1811 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1812 warn $msg if $warn_obsolete && $^W;
1814 next unless $tagname =~ /^\Q$prefix/;
1815 my $value = $opts->{$opt};
1816 if ($color_opts{$opt}) {
1817 $value = _color($value);
1819 $self->_set_error($Imager::ERRSTR);
1824 if (UNIVERSAL::isa($value, "Imager::Color")) {
1825 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1826 for my $img (@imgs) {
1827 $img->settag(name=>$tagname, value=>$tag);
1830 elsif (ref($value) eq 'ARRAY') {
1831 for my $i (0..$#$value) {
1832 my $val = $value->[$i];
1834 if (UNIVERSAL::isa($val, "Imager::Color")) {
1835 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1837 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1840 $self->_set_error("Unknown reference type " . ref($value) .
1841 " supplied in array for $opt");
1847 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1852 $self->_set_error("Unknown reference type " . ref($value) .
1853 " supplied for $opt");
1858 # set it as a tag for every image
1859 for my $img (@imgs) {
1860 $img->settag(name=>$tagname, value=>$value);
1868 # Write an image to file
1871 my %input=(jpegquality=>75,
1881 $self->_valid_image("write")
1884 $self->_set_opts(\%input, "i_", $self)
1887 my $type = $input{'type'};
1888 if (!$type and $input{file}) {
1889 $type = $FORMATGUESS->($input{file});
1892 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1896 _writer_autoload($type);
1899 if ($writers{$type} && $writers{$type}{single}) {
1900 ($IO, $fh) = $self->_get_writer_io(\%input)
1903 $writers{$type}{single}->($self, $IO, %input, type => $type)
1907 if (!$formats_low{$type}) {
1908 my $write_types = join ', ', sort Imager->write_types();
1909 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1913 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1916 if ( $type eq 'pnm' ) {
1917 $self->_set_opts(\%input, "pnm_", $self)
1919 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1920 $self->{ERRSTR} = $self->_error_as_msg();
1923 $self->{DEBUG} && print "writing a pnm file\n";
1925 elsif ( $type eq 'raw' ) {
1926 $self->_set_opts(\%input, "raw_", $self)
1928 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1929 $self->{ERRSTR} = $self->_error_as_msg();
1932 $self->{DEBUG} && print "writing a raw file\n";
1934 elsif ( $type eq 'bmp' ) {
1935 $self->_set_opts(\%input, "bmp_", $self)
1937 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1938 $self->{ERRSTR} = $self->_error_as_msg;
1941 $self->{DEBUG} && print "writing a bmp file\n";
1943 elsif ( $type eq 'tga' ) {
1944 $self->_set_opts(\%input, "tga_", $self)
1947 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1948 $self->{ERRSTR}=$self->_error_as_msg();
1951 $self->{DEBUG} && print "writing a tga file\n";
1955 if (exists $input{'data'}) {
1956 my $data = io_slurp($IO);
1958 $self->{ERRSTR}='Could not slurp from buffer';
1961 ${$input{data}} = $data;
1967 my ($class, $opts, @images) = @_;
1969 my $type = $opts->{type};
1971 if (!$type && $opts->{'file'}) {
1972 $type = $FORMATGUESS->($opts->{'file'});
1975 $class->_set_error('type parameter missing and not possible to guess from extension');
1978 # translate to ImgRaw
1980 for my $img (@images) {
1981 unless (ref $img && Scalar::Util::blessed($img) && $img->isa("Imager")) {
1982 $class->_set_error("write_multi: image $index is not an Imager image object");
1985 unless ($img->_valid_image("write_multi")) {
1986 $class->_set_error($img->errstr . " (image $index)");
1991 $class->_set_opts($opts, "i_", @images)
1993 my @work = map $_->{IMG}, @images;
1995 _writer_autoload($type);
1998 if ($writers{$type} && $writers{$type}{multiple}) {
1999 ($IO, $file) = $class->_get_writer_io($opts, $type)
2002 $writers{$type}{multiple}->($class, $IO, $opts, @images)
2006 if (!$formats{$type}) {
2007 my $write_types = join ', ', sort Imager->write_types();
2008 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
2012 ($IO, $file) = $class->_get_writer_io($opts, $type)
2015 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
2019 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
2024 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
2030 if (exists $opts->{'data'}) {
2031 my $data = io_slurp($IO);
2033 Imager->_set_error('Could not slurp from buffer');
2036 ${$opts->{data}} = $data;
2041 # read multiple images from a file
2043 my ($class, %opts) = @_;
2045 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2048 my $type = $opts{'type'};
2050 $type = _test_format($IO);
2053 if ($opts{file} && !$type) {
2055 $type = $FORMATGUESS->($opts{file});
2059 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2060 $opts{file} and $msg .= " or file name";
2061 Imager->_set_error($msg);
2065 _reader_autoload($type);
2067 if ($readers{$type} && $readers{$type}{multiple}) {
2068 return $readers{$type}{multiple}->($IO, %opts);
2071 unless ($formats{$type}) {
2072 my $read_types = join ', ', sort Imager->read_types();
2073 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2078 if ($type eq 'pnm') {
2079 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2082 my $img = Imager->new;
2083 if ($img->read(%opts, io => $IO, type => $type)) {
2086 Imager->_set_error($img->errstr);
2091 $ERRSTR = _error_as_msg();
2095 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2099 # Destroy an Imager object
2103 # delete $instances{$self};
2104 if (defined($self->{IMG})) {
2105 # the following is now handled by the XS DESTROY method for
2106 # Imager::ImgRaw object
2107 # Re-enabling this will break virtual images
2108 # tested for in t/t020masked.t
2109 # i_img_destroy($self->{IMG});
2110 undef($self->{IMG});
2112 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2116 # Perform an inplace filter of an image
2117 # that is the image will be overwritten with the data
2124 $self->_valid_image("filter")
2127 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2129 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2130 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2133 if ($filters{$input{'type'}}{names}) {
2134 my $names = $filters{$input{'type'}}{names};
2135 for my $name (keys %$names) {
2136 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2137 $input{$name} = $names->{$name}{$input{$name}};
2141 if (defined($filters{$input{'type'}}{defaults})) {
2142 %hsh=( image => $self->{IMG},
2144 %{$filters{$input{'type'}}{defaults}},
2147 %hsh=( image => $self->{IMG},
2152 my @cs=@{$filters{$input{'type'}}{callseq}};
2155 if (!defined($hsh{$_})) {
2156 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2161 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2162 &{$filters{$input{'type'}}{callsub}}(%hsh);
2165 chomp($self->{ERRSTR} = $@);
2171 $self->{DEBUG} && print "callseq is: @cs\n";
2172 $self->{DEBUG} && print "matching callseq is: @b\n";
2177 sub register_filter {
2179 my %hsh = ( defaults => {}, @_ );
2182 or die "register_filter() with no type\n";
2183 defined $hsh{callsub}
2184 or die "register_filter() with no callsub\n";
2185 defined $hsh{callseq}
2186 or die "register_filter() with no callseq\n";
2188 exists $filters{$hsh{type}}
2191 $filters{$hsh{type}} = \%hsh;
2196 sub scale_calculate {
2199 my %opts = ('type'=>'max', @_);
2201 # none of these should be references
2202 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2203 if (defined $opts{$name} && ref $opts{$name}) {
2204 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2209 my ($x_scale, $y_scale);
2210 my $width = $opts{width};
2211 my $height = $opts{height};
2213 defined $width or $width = $self->getwidth;
2214 defined $height or $height = $self->getheight;
2217 unless (defined $width && defined $height) {
2218 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2223 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2224 $x_scale = $opts{'xscalefactor'};
2225 $y_scale = $opts{'yscalefactor'};
2227 elsif ($opts{'xscalefactor'}) {
2228 $x_scale = $opts{'xscalefactor'};
2229 $y_scale = $opts{'scalefactor'} || $x_scale;
2231 elsif ($opts{'yscalefactor'}) {
2232 $y_scale = $opts{'yscalefactor'};
2233 $x_scale = $opts{'scalefactor'} || $y_scale;
2236 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2239 # work out the scaling
2240 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2241 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2242 $opts{ypixels} / $height );
2243 if ($opts{'type'} eq 'min') {
2244 $x_scale = $y_scale = _min($xpix,$ypix);
2246 elsif ($opts{'type'} eq 'max') {
2247 $x_scale = $y_scale = _max($xpix,$ypix);
2249 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2254 $self->_set_error('invalid value for type parameter');
2257 } elsif ($opts{xpixels}) {
2258 $x_scale = $y_scale = $opts{xpixels} / $width;
2260 elsif ($opts{ypixels}) {
2261 $x_scale = $y_scale = $opts{ypixels}/$height;
2263 elsif ($opts{constrain} && ref $opts{constrain}
2264 && $opts{constrain}->can('constrain')) {
2265 # we've been passed an Image::Math::Constrain object or something
2266 # that looks like one
2268 (undef, undef, $scalefactor)
2269 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2270 unless ($scalefactor) {
2271 $self->_set_error('constrain method failed on constrain parameter');
2274 $x_scale = $y_scale = $scalefactor;
2277 my $new_width = int($x_scale * $width + 0.5);
2278 $new_width > 0 or $new_width = 1;
2279 my $new_height = int($y_scale * $height + 0.5);
2280 $new_height > 0 or $new_height = 1;
2282 return ($x_scale, $y_scale, $new_width, $new_height);
2286 # Scale an image to requested size and return the scaled version
2290 my %opts = (qtype=>'normal' ,@_);
2291 my $img = Imager->new();
2292 my $tmp = Imager->new();
2294 unless (defined wantarray) {
2295 my @caller = caller;
2296 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2300 $self->_valid_image("scale")
2303 my ($x_scale, $y_scale, $new_width, $new_height) =
2304 $self->scale_calculate(%opts)
2307 if ($opts{qtype} eq 'normal') {
2308 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2309 if ( !defined($tmp->{IMG}) ) {
2310 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2313 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2314 if ( !defined($img->{IMG}) ) {
2315 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2321 elsif ($opts{'qtype'} eq 'preview') {
2322 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2323 if ( !defined($img->{IMG}) ) {
2324 $self->{ERRSTR}='unable to scale image';
2329 elsif ($opts{'qtype'} eq 'mixing') {
2330 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2331 unless ($img->{IMG}) {
2332 $self->_set_error(Imager->_error_as_msg);
2338 $self->_set_error('invalid value for qtype parameter');
2343 # Scales only along the X axis
2347 my %opts = ( scalefactor=>0.5, @_ );
2349 unless (defined wantarray) {
2350 my @caller = caller;
2351 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2355 $self->_valid_image("scaleX")
2358 my $img = Imager->new();
2360 my $scalefactor = $opts{scalefactor};
2362 if ($opts{pixels}) {
2363 $scalefactor = $opts{pixels} / $self->getwidth();
2366 unless ($self->{IMG}) {
2367 $self->{ERRSTR}='empty input image';
2371 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2373 if ( !defined($img->{IMG}) ) {
2374 $self->{ERRSTR} = 'unable to scale image';
2381 # Scales only along the Y axis
2385 my %opts = ( scalefactor => 0.5, @_ );
2387 unless (defined wantarray) {
2388 my @caller = caller;
2389 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2393 $self->_valid_image("scaleY")
2396 my $img = Imager->new();
2398 my $scalefactor = $opts{scalefactor};
2400 if ($opts{pixels}) {
2401 $scalefactor = $opts{pixels} / $self->getheight();
2404 unless ($self->{IMG}) {
2405 $self->{ERRSTR} = 'empty input image';
2408 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2410 if ( !defined($img->{IMG}) ) {
2411 $self->{ERRSTR} = 'unable to scale image';
2418 # Transform returns a spatial transformation of the input image
2419 # this moves pixels to a new location in the returned image.
2420 # NOTE - should make a utility function to check transforms for
2426 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2428 # print Dumper(\%opts);
2431 $self->_valid_image("transform")
2434 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2438 pop @INC if $INC[-1] eq '.';
2439 eval ("use Affix::Infix2Postfix;");
2443 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2446 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2447 {op=>'-',trans=>'Sub'},
2448 {op=>'*',trans=>'Mult'},
2449 {op=>'/',trans=>'Div'},
2450 {op=>'-','type'=>'unary',trans=>'u-'},
2452 {op=>'func','type'=>'unary'}],
2453 'grouping'=>[qw( \( \) )],
2454 'func'=>[qw( sin cos )],
2459 @xt=$I2P->translate($opts{'xexpr'});
2460 @yt=$I2P->translate($opts{'yexpr'});
2462 $numre=$I2P->{'numre'};
2465 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2466 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2467 @{$opts{'parm'}}=@pt;
2470 # print Dumper(\%opts);
2472 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2473 $self->{ERRSTR}='transform: no xopcodes given.';
2477 @op=@{$opts{'xopcodes'}};
2479 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2480 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2483 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2489 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2490 $self->{ERRSTR}='transform: no yopcodes given.';
2494 @op=@{$opts{'yopcodes'}};
2496 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2497 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2500 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2505 if ( !exists $opts{'parm'}) {
2506 $self->{ERRSTR}='transform: no parameter arg given.';
2510 # print Dumper(\@ropx);
2511 # print Dumper(\@ropy);
2512 # print Dumper(\@ropy);
2514 my $img = Imager->new();
2515 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2516 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2522 my ($opts, @imgs) = @_;
2524 require "Imager/Expr.pm";
2526 $opts->{variables} = [ qw(x y) ];
2527 my ($width, $height) = @{$opts}{qw(width height)};
2530 for my $img (@imgs) {
2531 unless ($img->_valid_image("transform2")) {
2532 Imager->_set_error($img->errstr . " (input image $index)");
2538 $width ||= $imgs[0]->getwidth();
2539 $height ||= $imgs[0]->getheight();
2541 for my $img (@imgs) {
2542 $opts->{constants}{"w$img_num"} = $img->getwidth();
2543 $opts->{constants}{"h$img_num"} = $img->getheight();
2544 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2545 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2550 $opts->{constants}{w} = $width;
2551 $opts->{constants}{cx} = $width/2;
2554 $Imager::ERRSTR = "No width supplied";
2558 $opts->{constants}{h} = $height;
2559 $opts->{constants}{cy} = $height/2;
2562 $Imager::ERRSTR = "No height supplied";
2565 my $code = Imager::Expr->new($opts);
2567 $Imager::ERRSTR = Imager::Expr::error();
2570 my $channels = $opts->{channels} || 3;
2571 unless ($channels >= 1 && $channels <= 4) {
2572 return Imager->_set_error("channels must be an integer between 1 and 4");
2575 my $img = Imager->new();
2576 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2577 $channels, $code->code(),
2578 $code->nregs(), $code->cregs(),
2579 [ map { $_->{IMG} } @imgs ]);
2580 if (!defined $img->{IMG}) {
2581 $Imager::ERRSTR = Imager->_error_as_msg();
2592 $self->_valid_image("rubthrough")
2595 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2596 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2600 %opts = (src_minx => 0,
2602 src_maxx => $opts{src}->getwidth(),
2603 src_maxy => $opts{src}->getheight(),
2607 defined $tx or $tx = $opts{left};
2608 defined $tx or $tx = 0;
2611 defined $ty or $ty = $opts{top};
2612 defined $ty or $ty = 0;
2614 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2615 $opts{src_minx}, $opts{src_miny},
2616 $opts{src_maxx}, $opts{src_maxy})) {
2617 $self->_set_error($self->_error_as_msg());
2634 $self->_valid_image("compose")
2637 unless ($opts{src}) {
2638 $self->_set_error("compose: src parameter missing");
2642 unless ($opts{src}->_valid_image("compose")) {
2643 $self->_set_error($opts{src}->errstr . " (for src)");
2646 my $src = $opts{src};
2648 my $left = $opts{left};
2649 defined $left or $left = $opts{tx};
2650 defined $left or $left = 0;
2652 my $top = $opts{top};
2653 defined $top or $top = $opts{ty};
2654 defined $top or $top = 0;
2656 my $src_left = $opts{src_left};
2657 defined $src_left or $src_left = $opts{src_minx};
2658 defined $src_left or $src_left = 0;
2660 my $src_top = $opts{src_top};
2661 defined $src_top or $src_top = $opts{src_miny};
2662 defined $src_top or $src_top = 0;
2664 my $width = $opts{width};
2665 if (!defined $width && defined $opts{src_maxx}) {
2666 $width = $opts{src_maxx} - $src_left;
2668 defined $width or $width = $src->getwidth() - $src_left;
2670 my $height = $opts{height};
2671 if (!defined $height && defined $opts{src_maxy}) {
2672 $height = $opts{src_maxy} - $src_top;
2674 defined $height or $height = $src->getheight() - $src_top;
2676 my $combine = $self->_combine($opts{combine}, 'normal');
2679 unless ($opts{mask}->_valid_image("compose")) {
2680 $self->_set_error($opts{mask}->errstr . " (for mask)");
2684 my $mask_left = $opts{mask_left};
2685 defined $mask_left or $mask_left = $opts{mask_minx};
2686 defined $mask_left or $mask_left = 0;
2688 my $mask_top = $opts{mask_top};
2689 defined $mask_top or $mask_top = $opts{mask_miny};
2690 defined $mask_top or $mask_top = 0;
2692 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2693 $left, $top, $src_left, $src_top,
2694 $mask_left, $mask_top, $width, $height,
2695 $combine, $opts{opacity})) {
2696 $self->_set_error(Imager->_error_as_msg);
2701 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2702 $width, $height, $combine, $opts{opacity})) {
2703 $self->_set_error(Imager->_error_as_msg);
2715 $self->_valid_image("flip")
2718 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2720 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2721 $dir = $xlate{$opts{'dir'}};
2722 return $self if i_flipxy($self->{IMG}, $dir);
2730 unless (defined wantarray) {
2731 my @caller = caller;
2732 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2736 $self->_valid_image("rotate")
2739 if (defined $opts{right}) {
2740 my $degrees = $opts{right};
2742 $degrees += 360 * int(((-$degrees)+360)/360);
2744 $degrees = $degrees % 360;
2745 if ($degrees == 0) {
2746 return $self->copy();
2748 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2749 my $result = Imager->new();
2750 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2754 $self->{ERRSTR} = $self->_error_as_msg();
2759 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2763 elsif (defined $opts{radians} || defined $opts{degrees}) {
2764 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2766 my $back = $opts{back};
2767 my $result = Imager->new;
2769 $back = _color($back);
2771 $self->_set_error(Imager->errstr);
2775 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2778 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2780 if ($result->{IMG}) {
2784 $self->{ERRSTR} = $self->_error_as_msg();
2789 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2794 sub matrix_transform {
2798 $self->_valid_image("matrix_transform")
2801 unless (defined wantarray) {
2802 my @caller = caller;
2803 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2807 if ($opts{matrix}) {
2808 my $xsize = $opts{xsize} || $self->getwidth;
2809 my $ysize = $opts{ysize} || $self->getheight;
2811 my $result = Imager->new;
2813 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2814 $opts{matrix}, $opts{back})
2818 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2826 $self->{ERRSTR} = "matrix parameter required";
2832 *yatf = \&matrix_transform;
2834 # These two are supported for legacy code only
2837 return Imager::Color->new(@_);
2841 return Imager::Color::set(@_);
2844 # Draws a box between the specified corner points.
2847 my $raw = $self->{IMG};
2849 $self->_valid_image("box")
2854 my ($xmin, $ymin, $xmax, $ymax);
2855 if (exists $opts{'box'}) {
2856 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2857 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2858 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2859 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2862 defined($xmin = $opts{xmin}) or $xmin = 0;
2863 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2864 defined($ymin = $opts{ymin}) or $ymin = 0;
2865 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2868 if ($opts{filled}) {
2869 my $color = $opts{'color'};
2871 if (defined $color) {
2872 unless (_is_color_object($color)) {
2873 $color = _color($color);
2875 $self->{ERRSTR} = $Imager::ERRSTR;
2881 $color = i_color_new(255,255,255,255);
2884 if ($color->isa("Imager::Color")) {
2885 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2888 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2891 elsif ($opts{fill}) {
2892 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2893 # assume it's a hash ref
2894 require 'Imager/Fill.pm';
2895 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2896 $self->{ERRSTR} = $Imager::ERRSTR;
2900 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2903 my $color = $opts{'color'};
2904 if (defined $color) {
2905 unless (_is_color_object($color)) {
2906 $color = _color($color);
2908 $self->{ERRSTR} = $Imager::ERRSTR;
2914 $color = i_color_new(255, 255, 255, 255);
2917 $self->{ERRSTR} = $Imager::ERRSTR;
2920 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2929 $self->_valid_image("arc")
2932 my $dflcl= [ 255, 255, 255, 255];
2937 'r'=>_min($self->getwidth(),$self->getheight())/3,
2938 'x'=>$self->getwidth()/2,
2939 'y'=>$self->getheight()/2,
2946 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2947 # assume it's a hash ref
2948 require 'Imager/Fill.pm';
2949 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2950 $self->{ERRSTR} = $Imager::ERRSTR;
2954 if ($opts{d1} == 0 && $opts{d2} == 361) {
2955 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2959 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2960 $opts{'d2'}, $opts{fill}{fill});
2963 elsif ($opts{filled}) {
2964 my $color = _color($opts{'color'});
2966 $self->{ERRSTR} = $Imager::ERRSTR;
2969 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2970 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2974 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2975 $opts{'d1'}, $opts{'d2'}, $color);
2979 my $color = _color($opts{'color'});
2980 if ($opts{d2} - $opts{d1} >= 360) {
2981 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2984 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2990 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2991 # assume it's a hash ref
2992 require 'Imager/Fill.pm';
2993 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2994 $self->{ERRSTR} = $Imager::ERRSTR;
2998 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2999 $opts{'d2'}, $opts{fill}{fill});
3002 my $color = _color($opts{'color'});
3004 $self->{ERRSTR} = $Imager::ERRSTR;
3007 if ($opts{filled}) {
3008 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
3009 $opts{'d1'}, $opts{'d2'}, $color);
3012 if ($opts{d1} == 0 && $opts{d2} == 361) {
3013 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
3016 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
3022 $self->_set_error($self->_error_as_msg);
3029 # Draws a line from one point to the other
3030 # the endpoint is set if the endp parameter is set which it is by default.
3031 # to turn of the endpoint being set use endp=>0 when calling line.
3035 my $dflcl=i_color_new(0,0,0,0);
3036 my %opts=(color=>$dflcl,
3040 $self->_valid_image("line")
3043 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
3044 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
3046 my $color = _color($opts{'color'});
3048 $self->{ERRSTR} = $Imager::ERRSTR;
3052 $opts{antialias} = $opts{aa} if defined $opts{aa};
3053 if ($opts{antialias}) {
3054 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3055 $color, $opts{endp});
3057 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3058 $color, $opts{endp});
3063 # Draws a line between an ordered set of points - It more or less just transforms this
3064 # into a list of lines.
3068 my ($pt,$ls,@points);
3069 my $dflcl=i_color_new(0,0,0,0);
3070 my %opts=(color=>$dflcl,@_);
3072 $self->_valid_image("polyline")
3075 if (exists($opts{points})) { @points=@{$opts{points}}; }
3076 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3077 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3080 # print Dumper(\@points);
3082 my $color = _color($opts{'color'});
3084 $self->{ERRSTR} = $Imager::ERRSTR;
3087 $opts{antialias} = $opts{aa} if defined $opts{aa};
3088 if ($opts{antialias}) {
3091 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3098 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3108 my ($pt,$ls,@points);
3109 my $dflcl = i_color_new(0,0,0,0);
3110 my %opts = (color=>$dflcl, @_);
3112 $self->_valid_image("polygon")
3115 if (exists($opts{points})) {
3116 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3117 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3120 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3121 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3124 my $mode = _first($opts{mode}, 0);
3126 if ($opts{'fill'}) {
3127 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3128 # assume it's a hash ref
3129 require 'Imager/Fill.pm';
3130 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3131 $self->{ERRSTR} = $Imager::ERRSTR;
3135 unless (i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3136 $mode, $opts{'fill'}{'fill'})) {
3137 return $self->_set_error($self->_error_as_msg);
3141 my $color = _color($opts{'color'});
3143 $self->{ERRSTR} = $Imager::ERRSTR;
3146 unless (i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color)) {
3147 return $self->_set_error($self->_error_as_msg);
3155 my ($self, %opts) = @_;
3157 $self->_valid_image("polypolygon")
3160 my $points = $opts{points};
3162 or return $self->_set_error("polypolygon: missing required points");
3164 my $mode = _first($opts{mode}, "evenodd");
3166 if ($opts{filled}) {
3167 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3168 or return $self->_set_error($Imager::ERRSTR);
3170 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3171 or return $self->_set_error($self->_error_as_msg);
3173 elsif ($opts{fill}) {
3174 my $fill = $opts{fill};
3175 $self->_valid_fill($fill, "polypolygon")
3178 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3179 or return $self->_set_error($self->_error_as_msg);
3182 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3183 or return $self->_set_error($Imager::ERRSTR);
3185 my $rimg = $self->{IMG};
3187 if (_first($opts{aa}, 1)) {
3188 for my $poly (@$points) {
3189 my $xp = $poly->[0];
3190 my $yp = $poly->[1];
3191 for my $i (0 .. $#$xp - 1) {
3192 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3195 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3200 for my $poly (@$points) {
3201 my $xp = $poly->[0];
3202 my $yp = $poly->[1];
3203 for my $i (0 .. $#$xp - 1) {
3204 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3207 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3216 # this the multipoint bezier curve
3217 # this is here more for testing that actual usage since
3218 # this is not a good algorithm. Usually the curve would be
3219 # broken into smaller segments and each done individually.
3223 my ($pt,$ls,@points);
3224 my $dflcl=i_color_new(0,0,0,0);
3225 my %opts=(color=>$dflcl,@_);
3227 $self->_valid_image("polybezier")
3230 if (exists $opts{points}) {
3231 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3232 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3235 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3236 $self->{ERRSTR}='Missing or invalid points.';
3240 my $color = _color($opts{'color'});
3242 $self->{ERRSTR} = $Imager::ERRSTR;
3245 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3251 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3254 $self->_valid_image("flood_fill")
3257 unless (exists $opts{'x'} && exists $opts{'y'}) {
3258 $self->{ERRSTR} = "missing seed x and y parameters";
3262 if ($opts{border}) {
3263 my $border = _color($opts{border});
3265 $self->_set_error($Imager::ERRSTR);
3269 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3270 # assume it's a hash ref
3271 require Imager::Fill;
3272 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3273 $self->{ERRSTR} = $Imager::ERRSTR;
3277 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3278 $opts{fill}{fill}, $border);
3281 my $color = _color($opts{'color'});
3283 $self->{ERRSTR} = $Imager::ERRSTR;
3286 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3293 $self->{ERRSTR} = $self->_error_as_msg();
3299 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3300 # assume it's a hash ref
3301 require 'Imager/Fill.pm';
3302 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3303 $self->{ERRSTR} = $Imager::ERRSTR;
3307 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3310 my $color = _color($opts{'color'});
3312 $self->{ERRSTR} = $Imager::ERRSTR;
3315 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3321 $self->{ERRSTR} = $self->_error_as_msg();
3328 my ($self, %opts) = @_;
3330 $self->_valid_image("setpixel")
3333 my $color = $opts{color};
3334 unless (defined $color) {
3335 $color = $self->{fg};
3336 defined $color or $color = NC(255, 255, 255);
3339 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3340 unless ($color = _color($color, 'setpixel')) {
3341 $self->_set_error("setpixel: " . Imager->errstr);
3346 unless (exists $opts{'x'} && exists $opts{'y'}) {
3347 $self->_set_error('setpixel: missing x or y parameter');
3353 if (ref $x || ref $y) {
3354 $x = ref $x ? $x : [ $x ];
3355 $y = ref $y ? $y : [ $y ];
3357 $self->_set_error("setpixel: x is a reference to an empty array");
3361 $self->_set_error("setpixel: y is a reference to an empty array");
3365 # make both the same length, replicating the last element
3367 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3370 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3374 if ($color->isa('Imager::Color')) {
3375 for my $i (0..$#$x) {
3376 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3381 for my $i (0..$#$x) {
3382 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3390 if ($color->isa('Imager::Color')) {
3391 i_ppix($self->{IMG}, $x, $y, $color)
3392 and return "0 but true";
3395 i_ppixf($self->{IMG}, $x, $y, $color)
3396 and return "0 but true";
3406 my %opts = ( "type"=>'8bit', @_);
3408 $self->_valid_image("getpixel")
3411 unless (exists $opts{'x'} && exists $opts{'y'}) {
3412 $self->_set_error('getpixel: missing x or y parameter');
3418 my $type = $opts{'type'};
3419 if (ref $x || ref $y) {
3420 $x = ref $x ? $x : [ $x ];
3421 $y = ref $y ? $y : [ $y ];
3423 $self->_set_error("getpixel: x is a reference to an empty array");
3427 $self->_set_error("getpixel: y is a reference to an empty array");
3431 # make both the same length, replicating the last element
3433 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3436 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3440 if ($type eq '8bit') {
3441 for my $i (0..$#$x) {
3442 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3445 elsif ($type eq 'float' || $type eq 'double') {
3446 for my $i (0..$#$x) {
3447 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3451 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3454 return wantarray ? @result : \@result;
3457 if ($type eq '8bit') {
3458 return i_get_pixel($self->{IMG}, $x, $y);
3460 elsif ($type eq 'float' || $type eq 'double') {
3461 return i_gpixf($self->{IMG}, $x, $y);
3464 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3472 my %opts = ( type => '8bit', x=>0, @_);
3474 $self->_valid_image("getscanline")
3477 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3479 unless (defined $opts{'y'}) {
3480 $self->_set_error("missing y parameter");
3484 if ($opts{type} eq '8bit') {
3485 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3488 elsif ($opts{type} eq 'float') {
3489 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3492 elsif ($opts{type} eq 'index') {
3493 unless (i_img_type($self->{IMG})) {
3494 $self->_set_error("type => index only valid on paletted images");
3497 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3501 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3508 my %opts = ( x=>0, @_);
3510 $self->_valid_image("setscanline")
3513 unless (defined $opts{'y'}) {
3514 $self->_set_error("missing y parameter");
3519 if (ref $opts{pixels} && @{$opts{pixels}}) {
3520 # try to guess the type
3521 if ($opts{pixels}[0]->isa('Imager::Color')) {
3522 $opts{type} = '8bit';
3524 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3525 $opts{type} = 'float';
3528 $self->_set_error("missing type parameter and could not guess from pixels");
3534 $opts{type} = '8bit';
3538 if ($opts{type} eq '8bit') {
3539 if (ref $opts{pixels}) {
3540 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3543 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3546 elsif ($opts{type} eq 'float') {
3547 if (ref $opts{pixels}) {
3548 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3551 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3554 elsif ($opts{type} eq 'index') {
3555 if (ref $opts{pixels}) {
3556 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3559 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3563 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3570 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3572 $self->_valid_image("getsamples")
3575 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3577 unless (defined $opts{'y'}) {
3578 $self->_set_error("missing y parameter");
3582 if ($opts{target}) {
3583 my $target = $opts{target};
3584 my $offset = $opts{offset};
3585 if ($opts{type} eq '8bit') {
3586 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3587 $opts{y}, $opts{channels})
3589 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3590 return scalar(@samples);
3592 elsif ($opts{type} eq 'float') {
3593 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3594 $opts{y}, $opts{channels});
3595 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3596 return scalar(@samples);
3598 elsif ($opts{type} =~ /^(\d+)bit$/) {
3602 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3603 $opts{y}, $bits, $target,
3604 $offset, $opts{channels});
3605 unless (defined $count) {
3606 $self->_set_error(Imager->_error_as_msg);
3613 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3618 if ($opts{type} eq '8bit') {
3619 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3620 $opts{y}, $opts{channels});
3622 elsif ($opts{type} eq 'float') {
3623 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3624 $opts{y}, $opts{channels});
3626 elsif ($opts{type} =~ /^(\d+)bit$/) {
3630 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3631 $opts{y}, $bits, \@data, 0, $opts{channels})
3636 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3645 $self->_valid_image("setsamples")
3648 my %opts = ( x => 0, offset => 0 );
3650 # avoid duplicating the data parameter, it may be a large scalar
3652 while ($i < @_ -1) {
3653 if ($_[$i] eq 'data') {
3657 $opts{$_[$i]} = $_[$i+1];
3663 unless(defined $data_index) {
3664 $self->_set_error('setsamples: data parameter missing');
3667 unless (defined $_[$data_index]) {
3668 $self->_set_error('setsamples: data parameter not defined');
3672 my $type = $opts{type};
3673 defined $type or $type = '8bit';
3675 my $width = defined $opts{width} ? $opts{width}
3676 : $self->getwidth() - $opts{x};
3679 if ($type eq '8bit') {
3680 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3681 $_[$data_index], $opts{offset}, $width);
3683 elsif ($type eq 'float') {
3684 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3685 $_[$data_index], $opts{offset}, $width);
3687 elsif ($type =~ /^([0-9]+)bit$/) {
3690 unless (ref $_[$data_index]) {
3691 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3695 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3696 $opts{channels}, $_[$data_index], $opts{offset},
3700 $self->_set_error('setsamples: type parameter invalid');
3704 unless (defined $count) {
3705 $self->_set_error(Imager->_error_as_msg);
3712 # make an identity matrix of the given size
3716 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3717 for my $c (0 .. ($size-1)) {
3718 $matrix->[$c][$c] = 1;
3723 # general function to convert an image
3725 my ($self, %opts) = @_;
3728 $self->_valid_image("convert")
3731 unless (defined wantarray) {
3732 my @caller = caller;
3733 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3737 # the user can either specify a matrix or preset
3738 # the matrix overrides the preset
3739 if (!exists($opts{matrix})) {
3740 unless (exists($opts{preset})) {
3741 $self->{ERRSTR} = "convert() needs a matrix or preset";
3745 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3746 # convert to greyscale, keeping the alpha channel if any
3747 if ($self->getchannels == 3) {
3748 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3750 elsif ($self->getchannels == 4) {
3751 # preserve the alpha channel
3752 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3757 $matrix = _identity($self->getchannels);
3760 elsif ($opts{preset} eq 'noalpha') {
3761 # strip the alpha channel
3762 if ($self->getchannels == 2 or $self->getchannels == 4) {
3763 $matrix = _identity($self->getchannels);
3764 pop(@$matrix); # lose the alpha entry
3767 $matrix = _identity($self->getchannels);
3770 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3772 $matrix = [ [ 1 ] ];
3774 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3775 $matrix = [ [ 0, 1 ] ];
3777 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3778 $matrix = [ [ 0, 0, 1 ] ];
3780 elsif ($opts{preset} eq 'alpha') {
3781 if ($self->getchannels == 2 or $self->getchannels == 4) {
3782 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3785 # the alpha is just 1 <shrug>
3786 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3789 elsif ($opts{preset} eq 'rgb') {
3790 if ($self->getchannels == 1) {
3791 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3793 elsif ($self->getchannels == 2) {
3794 # preserve the alpha channel
3795 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3798 $matrix = _identity($self->getchannels);
3801 elsif ($opts{preset} eq 'addalpha') {
3802 if ($self->getchannels == 1) {
3803 $matrix = _identity(2);
3805 elsif ($self->getchannels == 3) {
3806 $matrix = _identity(4);
3809 $matrix = _identity($self->getchannels);
3813 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3819 $matrix = $opts{matrix};
3822 my $new = Imager->new;
3823 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3824 unless ($new->{IMG}) {
3825 # most likely a bad matrix
3826 i_push_error(0, "convert");
3827 $self->{ERRSTR} = _error_as_msg();
3833 # combine channels from multiple input images, a class method
3835 my ($class, %opts) = @_;
3837 my $src = delete $opts{src};
3839 $class->_set_error("src parameter missing");
3844 for my $img (@$src) {
3845 unless (eval { $img->isa("Imager") }) {
3846 $class->_set_error("src must contain image objects");
3849 unless ($img->_valid_image("combine")) {
3850 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3853 push @imgs, $img->{IMG};
3856 if (my $channels = delete $opts{channels}) {
3857 $result = i_combine(\@imgs, $channels);
3860 $result = i_combine(\@imgs);
3863 $class->_set_error($class->_error_as_msg);
3867 my $img = $class->new;
3868 $img->{IMG} = $result;
3874 # general function to map an image through lookup tables
3877 my ($self, %opts) = @_;
3878 my @chlist = qw( red green blue alpha );
3880 $self->_valid_image("map")
3883 if (!exists($opts{'maps'})) {
3884 # make maps from channel maps
3886 for $chnum (0..$#chlist) {
3887 if (exists $opts{$chlist[$chnum]}) {
3888 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3889 } elsif (exists $opts{'all'}) {
3890 $opts{'maps'}[$chnum] = $opts{'all'};
3894 if ($opts{'maps'} and $self->{IMG}) {
3895 i_map($self->{IMG}, $opts{'maps'} );
3901 my ($self, %opts) = @_;
3903 $self->_valid_image("difference")
3906 defined $opts{mindist} or $opts{mindist} = 0;
3908 defined $opts{other}
3909 or return $self->_set_error("No 'other' parameter supplied");
3910 unless ($opts{other}->_valid_image("difference")) {
3911 $self->_set_error($opts{other}->errstr . " (other image)");
3915 my $result = Imager->new;
3916 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3918 or return $self->_set_error($self->_error_as_msg());
3923 # destructive border - image is shrunk by one pixel all around
3926 my ($self,%opts)=@_;
3927 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3928 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3932 # Get the width of an image
3937 $self->_valid_image("getwidth")
3940 return i_img_get_width($self->{IMG});
3943 # Get the height of an image
3948 $self->_valid_image("getheight")
3951 return i_img_get_height($self->{IMG});
3954 # Get number of channels in an image
3959 $self->_valid_image("getchannels")
3962 return i_img_getchannels($self->{IMG});
3965 my @model_names = qw(unknown gray graya rgb rgba);
3968 my ($self, %opts) = @_;
3970 $self->_valid_image("colormodel")
3973 my $model = i_img_color_model($self->{IMG});
3975 return $opts{numeric} ? $model : $model_names[$model];
3981 $self->_valid_image("colorchannels")
3984 return i_img_color_channels($self->{IMG});
3990 $self->_valid_image("alphachannel")
3993 return scalar(i_img_alpha_channel($self->{IMG}));
4001 $self->_valid_image("getmask")
4004 return i_img_getmask($self->{IMG});
4013 $self->_valid_image("setmask")
4016 unless (defined $opts{mask}) {
4017 $self->_set_error("mask parameter required");
4021 i_img_setmask( $self->{IMG} , $opts{mask} );
4026 # Get number of colors in an image
4030 my %opts=('maxcolors'=>2**30,@_);
4032 $self->_valid_image("getcolorcount")
4035 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
4036 return ($rc==-1? undef : $rc);
4039 # Returns a reference to a hash. The keys are colour named (packed) and the
4040 # values are the number of pixels in this colour.
4041 sub getcolorusagehash {
4044 $self->_valid_image("getcolorusagehash")
4047 my %opts = ( maxcolors => 2**30, @_ );
4048 my $max_colors = $opts{maxcolors};
4049 unless (defined $max_colors && $max_colors > 0) {
4050 $self->_set_error('maxcolors must be a positive integer');
4054 my $channels= $self->getchannels;
4055 # We don't want to look at the alpha channel, because some gifs using it
4056 # doesn't define it for every colour (but only for some)
4057 $channels -= 1 if $channels == 2 or $channels == 4;
4059 my $height = $self->getheight;
4060 for my $y (0 .. $height - 1) {
4061 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4062 while (length $colors) {
4063 $color_use{ substr($colors, 0, $channels, '') }++;
4065 keys %color_use > $max_colors
4071 # This will return a ordered array of the colour usage. Kind of the sorted
4072 # version of the values of the hash returned by getcolorusagehash.
4073 # You might want to add safety checks and change the names, etc...
4077 $self->_valid_image("getcolorusage")
4080 my %opts = ( maxcolors => 2**30, @_ );
4081 my $max_colors = $opts{maxcolors};
4082 unless (defined $max_colors && $max_colors > 0) {
4083 $self->_set_error('maxcolors must be a positive integer');
4087 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4090 # draw string to an image
4095 $self->_valid_image("string")
4098 my %input=('x'=>0, 'y'=>0, @_);
4099 defined($input{string}) or $input{string} = $input{text};
4101 unless(defined $input{string}) {
4102 $self->{ERRSTR}="missing required parameter 'string'";
4106 unless($input{font}) {
4107 $self->{ERRSTR}="missing required parameter 'font'";
4111 unless ($input{font}->draw(image=>$self, %input)) {
4123 $self->_valid_image("align_string")
4132 my %input=('x'=>0, 'y'=>0, @_);
4133 defined $input{string}
4134 or $input{string} = $input{text};
4136 unless(exists $input{string}) {
4137 $self->_set_error("missing required parameter 'string'");
4141 unless($input{font}) {
4142 $self->_set_error("missing required parameter 'font'");
4147 unless (@result = $input{font}->align(image=>$img, %input)) {
4151 return wantarray ? @result : $result[0];
4154 my @file_limit_names = qw/width height bytes/;
4156 sub set_file_limits {
4163 @values{@file_limit_names} = (0) x @file_limit_names;
4166 @values{@file_limit_names} = i_get_image_file_limits();
4169 for my $key (keys %values) {
4170 defined $opts{$key} and $values{$key} = $opts{$key};
4173 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4176 sub get_file_limits {
4177 i_get_image_file_limits();
4180 my @check_args = qw(width height channels sample_size);
4182 sub check_file_limits {
4192 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4193 $opts{sample_size} = length(pack("d", 0));
4196 for my $name (@check_args) {
4197 unless (defined $opts{$name}) {
4198 $class->_set_error("check_file_limits: $name must be defined");
4201 unless ($opts{$name} == int($opts{$name})) {
4202 $class->_set_error("check_file_limits: $name must be a positive integer");
4207 my $result = i_int_check_image_file_limits(@opts{@check_args});
4209 $class->_set_error($class->_error_as_msg());
4215 # Shortcuts that can be exported
4217 sub newcolor { Imager::Color->new(@_); }
4218 sub newfont { Imager::Font->new(@_); }
4220 require Imager::Color::Float;
4221 return Imager::Color::Float->new(@_);
4224 *NC=*newcolour=*newcolor;
4231 #### Utility routines
4234 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4238 my ($self, $msg) = @_;
4241 $self->{ERRSTR} = $msg;
4249 # Default guess for the type of an image from extension
4251 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps webp xwd xpm dng ras);
4255 ( map { $_ => $_ } @simple_types ),
4261 pnm => "pnm", # technically wrong, but historically it works in Imager
4274 sub def_guess_type {
4277 my ($ext) = $name =~ /\.([^.]+)$/
4280 my $type = $ext_types{$ext}
4286 sub add_type_extensions {
4287 my ($class, $type, @exts) = @_;
4289 for my $ext (@exts) {
4290 exists $ext_types{lc $ext} or $ext_types{lc $ext} = lc $type;
4296 return @combine_types;
4299 # get the minimum of a list
4303 for(@_) { if ($_<$mx) { $mx=$_; }}
4307 # get the maximum of a list
4311 for(@_) { if ($_>$mx) { $mx=$_; }}
4315 # string stuff for iptc headers
4319 $str = substr($str,3);
4320 $str =~ s/[\n\r]//g;
4327 # A little hack to parse iptc headers.
4332 my($caption,$photogr,$headln,$credit);
4334 my $str=$self->{IPTCRAW};
4339 @ar=split(/8BIM/,$str);
4344 @sar=split(/\034\002/);
4345 foreach $item (@sar) {
4346 if ($item =~ m/^x/) {
4347 $caption = _clean($item);
4350 if ($item =~ m/^P/) {
4351 $photogr = _clean($item);
4354 if ($item =~ m/^i/) {
4355 $headln = _clean($item);
4358 if ($item =~ m/^n/) {
4359 $credit = _clean($item);
4365 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4369 # Inline added a new argument at the beginning
4373 or die "Only C language supported";
4375 require Imager::ExtUtils;
4376 return Imager::ExtUtils->inline_config;
4379 # threads shouldn't try to close raw Imager objects
4380 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4383 # this serves two purposes:
4384 # - a class method to load the file support modules included with Imager
4385 # (or were included, once the library dependent modules are split out)
4386 # - something for Module::ScanDeps to analyze
4387 # https://rt.cpan.org/Ticket/Display.html?id=6566
4390 pop @INC if $INC[-1] eq '.';
4391 eval { require Imager::File::GIF };
4392 eval { require Imager::File::JPEG };
4393 eval { require Imager::File::PNG };
4394 eval { require Imager::File::SGI };
4395 eval { require Imager::File::TIFF };
4396 eval { require Imager::File::ICO };
4397 eval { require Imager::Font::W32 };
4398 eval { require Imager::Font::FT2 };
4399 eval { require Imager::Font::T1 };
4400 eval { require Imager::Color::Table };
4409 my ($class, $fh) = @_;
4412 return $class->new_cb
4417 return print $fh $_[0];
4421 my $count = CORE::read $fh, $tmp, $_[1];
4429 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4430 unless (CORE::seek $fh, $_[0], $_[1]) {
4441 return $class->_new_perlio($fh);
4445 # backward compatibility for %formats
4446 package Imager::FORMATS;
4448 use constant IX_FORMATS => 0;
4449 use constant IX_LIST => 1;
4450 use constant IX_INDEX => 2;
4451 use constant IX_CLASSES => 3;
4454 my ($class, $formats, $classes) = @_;
4456 return bless [ $formats, [ ], 0, $classes ], $class;
4460 my ($self, $key) = @_;
4462 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4465 my $loaded = Imager::_load_file($file, \$error);
4470 if ($error =~ /^Can't locate /) {
4471 $error = "Can't locate $file";
4473 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4476 $self->[IX_FORMATS]{$key} = $value;
4482 my ($self, $key) = @_;
4484 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4486 $self->[IX_CLASSES]{$key} or return undef;
4488 return $self->_check($key);
4492 die "%Imager::formats is not user monifiable";
4496 die "%Imager::formats is not user monifiable";
4500 die "%Imager::formats is not user monifiable";
4504 my ($self, $key) = @_;
4506 if (exists $self->[IX_FORMATS]{$key}) {
4507 my $value = $self->[IX_FORMATS]{$key}
4512 $self->_check($key) or return 1==0;
4520 unless (@{$self->[IX_LIST]}) {
4522 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4523 keys %{$self->[IX_FORMATS]};
4525 for my $key (keys %{$self->[IX_CLASSES]}) {
4526 $self->[IX_FORMATS]{$key} and next;
4528 and push @{$self->[IX_LIST]}, $key;
4532 @{$self->[IX_LIST]} or return;
4533 $self->[IX_INDEX] = 1;
4534 return $self->[IX_LIST][0];
4540 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4543 return $self->[IX_LIST][$self->[IX_INDEX]++];
4549 return scalar @{$self->[IX_LIST]};
4554 # Below is the stub of documentation for your module. You better edit it!
4558 Imager - Perl extension for Generating 24 bit Images
4568 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4573 # see Imager::Files for information on the read() method
4574 my $img = Imager->new(file=>$file)
4575 or die Imager->errstr();
4577 $file =~ s/\.[^.]*$//;
4579 # Create smaller version
4580 # documented in Imager::Transformations
4581 my $thumb = $img->scale(scalefactor=>.3);
4583 # Autostretch individual channels
4584 $thumb->filter(type=>'autolevels');
4586 # try to save in one of these formats
4589 for $format ( qw( png gif jpeg tiff ppm ) ) {
4590 # Check if given format is supported
4591 if ($Imager::formats{$format}) {
4592 $file.="_low.$format";
4593 print "Storing image as: $file\n";
4594 # documented in Imager::Files
4595 $thumb->write(file=>$file) or
4603 Imager is a module for creating and altering images. It can read and
4604 write various image formats, draw primitive shapes like lines,and
4605 polygons, blend multiple images together in various ways, scale, crop,
4606 render text and more.
4608 =head2 Overview of documentation
4614 Imager - This document - Synopsis, Example, Table of Contents and
4619 L<Imager::Install> - installation notes for Imager.
4623 L<Imager::Tutorial> - a brief introduction to Imager.
4627 L<Imager::Cookbook> - how to do various things with Imager.
4631 L<Imager::ImageTypes> - Basics of constructing image objects with
4632 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4633 8/16/double bits/channel, color maps, channel masks, image tags, color
4634 quantization. Also discusses basic image information methods.
4638 L<Imager::Files> - IO interaction, reading/writing images, format
4643 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4648 L<Imager::Color> - Color specification.
4652 L<Imager::Fill> - Fill pattern specification.
4656 L<Imager::Font> - General font rendering, bounding boxes and font
4661 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4662 blending, pasting, convert and map.
4666 L<Imager::Engines> - Programmable transformations through
4667 C<transform()>, C<transform2()> and C<matrix_transform()>.
4671 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4676 L<Imager::Expr> - Expressions for evaluation engine used by
4681 L<Imager::Matrix2d> - Helper class for affine transformations.
4685 L<Imager::Fountain> - Helper for making gradient profiles.
4689 L<Imager::IO> - Imager I/O abstraction.
4693 L<Imager::API> - using Imager's C API
4697 L<Imager::APIRef> - API function reference
4701 L<Imager::Inline> - using Imager's C API from Inline::C
4705 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4709 L<Imager::Security> - brief security notes.
4713 L<Imager::Threads> - brief information on working with threads.
4717 =head2 Basic Overview
4719 An Image object is created with C<$img = Imager-E<gt>new()>.
4722 $img=Imager->new(); # create empty image
4723 $img->read(file=>'lena.png',type=>'png') or # read image from file
4724 die $img->errstr(); # give an explanation
4725 # if something failed
4727 or if you want to create an empty image:
4729 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4731 This example creates a completely black image of width 400 and height
4734 =head1 ERROR HANDLING
4736 In general a method will return false when it fails, if it does use
4737 the C<errstr()> method to find out why:
4743 Returns the last error message in that context.
4745 If the last error you received was from calling an object method, such
4746 as read, call errstr() as an object method to find out why:
4748 my $image = Imager->new;
4749 $image->read(file => 'somefile.gif')
4750 or die $image->errstr;
4752 If it was a class method then call errstr() as a class method:
4754 my @imgs = Imager->read_multi(file => 'somefile.gif')
4755 or die Imager->errstr;
4757 Note that in some cases object methods are implemented in terms of
4758 class methods so a failing object method may set both.
4762 The C<Imager-E<gt>new> method is described in detail in
4763 L<Imager::ImageTypes>.
4767 Where to find information on methods for Imager class objects.
4769 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4774 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4776 add_type_extensions() - L<Imager::Files/add_file_magic()> - add magic
4777 for new image file types.
4779 L<Imager::Files/add_type_extensions($type, $ext, ...)> - add extensions for
4780 new image file types.
4782 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4785 alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
4786 channel index of the alpha channel (if any).
4788 arc() - L<Imager::Draw/arc()> - draw a filled arc
4790 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4793 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4795 check_file_limits() - L<Imager::Files/check_file_limits()>
4797 circle() - L<Imager::Draw/circle()> - draw a filled circle
4799 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4802 colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
4803 of channels used for color.
4805 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4806 colors in an image's palette (paletted images only)
4808 colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
4811 combine() - L<Imager::Transformations/combine()> - combine channels
4812 from one or more images.
4814 combines() - L<Imager::Draw/combines()> - return a list of the
4815 different combine type keywords
4817 compose() - L<Imager::Transformations/compose()> - compose one image
4820 convert() - L<Imager::Transformations/convert()> - transform the color
4823 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4826 crop() - L<Imager::Transformations/crop()> - extract part of an image
4828 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4829 used to guess the output file format based on the output file name
4831 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4833 difference() - L<Imager::Filters/difference()> - produce a difference
4834 images from two input images.
4836 errstr() - L</errstr()> - the error from the last failed operation.
4838 filter() - L<Imager::Filters/filter()> - image filtering
4840 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4841 palette, if it has one
4843 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4846 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4849 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4850 samples per pixel for an image
4852 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4853 different colors used by an image (works for direct color images)
4855 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4856 palette, if it has one
4858 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4860 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4862 get_file_limits() - L<Imager::Files/get_file_limits()>
4864 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4867 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4869 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4872 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4873 row or partial row of pixels.
4875 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4876 row or partial row of pixels.
4878 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4881 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4884 init() - L<Imager::ImageTypes/init()>
4886 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4887 image write functions should write the image in their bilevel (blank
4888 and white, no gray levels) format
4890 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4893 line() - L<Imager::Draw/line()> - draw an interval
4895 load_plugin() - L<Imager::Filters/load_plugin()>
4897 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4900 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4901 color palette from one or more input images.
4903 map() - L<Imager::Transformations/map()> - remap color
4906 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4908 matrix_transform() - L<Imager::Engines/matrix_transform()>
4910 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4912 NC() - L<Imager::Handy/NC()>
4914 NCF() - L<Imager::Handy/NCF()>
4916 new() - L<Imager::ImageTypes/new()>
4918 newcolor() - L<Imager::Handy/newcolor()>
4920 newcolour() - L<Imager::Handy/newcolour()>
4922 newfont() - L<Imager::Handy/newfont()>
4924 NF() - L<Imager::Handy/NF()>
4926 open() - L<Imager::Files/read()> - an alias for read()
4928 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4932 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4935 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4938 polygon() - L<Imager::Draw/polygon()>
4940 polyline() - L<Imager::Draw/polyline()>
4942 polypolygon() - L<Imager::Draw/polypolygon()>
4944 preload() - L<Imager::Files/preload()>
4946 read() - L<Imager::Files/read()> - read a single image from an image file
4948 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4951 read_types() - L<Imager::Files/read_types()> - list image types Imager
4954 register_filter() - L<Imager::Filters/register_filter()>
4956 register_reader() - L<Imager::Files/register_reader()>
4958 register_writer() - L<Imager::Files/register_writer()>
4960 rotate() - L<Imager::Transformations/rotate()>
4962 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4963 onto an image and use the alpha channel
4965 scale() - L<Imager::Transformations/scale()>
4967 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4969 scaleX() - L<Imager::Transformations/scaleX()>
4971 scaleY() - L<Imager::Transformations/scaleY()>
4973 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4976 set_file_limits() - L<Imager::Files/set_file_limits()>
4978 setmask() - L<Imager::ImageTypes/setmask()>
4980 setpixel() - L<Imager::Draw/setpixel()>
4982 setsamples() - L<Imager::Draw/setsamples()>
4984 setscanline() - L<Imager::Draw/setscanline()>
4986 settag() - L<Imager::ImageTypes/settag()>
4988 string() - L<Imager::Draw/string()> - draw text on an image
4990 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4992 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4994 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4996 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4998 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4999 double per sample image.
5001 transform() - L<Imager::Engines/"transform()">
5003 transform2() - L<Imager::Engines/"transform2()">
5005 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
5007 unload_plugin() - L<Imager::Filters/unload_plugin()>
5009 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
5012 write() - L<Imager::Files/write()> - write an image to a file
5014 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
5017 write_types() - L<Imager::Files/read_types()> - list image types Imager
5020 =head1 CONCEPT INDEX
5022 animated GIF - L<Imager::Files/"Writing an animated GIF">
5024 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
5025 L<Imager::ImageTypes/"Common Tags">.
5027 blend - alpha blending one image onto another
5028 L<Imager::Transformations/rubthrough()>
5030 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
5032 boxes, drawing - L<Imager::Draw/box()>
5034 changes between image - L<Imager::Filters/"Image Difference">
5036 channels, combine into one image - L<Imager::Transformations/combine()>
5038 color - L<Imager::Color>
5040 color names - L<Imager::Color>, L<Imager::Color::Table>
5042 combine modes - L<Imager::Draw/"Combine Types">
5044 compare images - L<Imager::Filters/"Image Difference">
5046 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
5048 convolution - L<Imager::Filters/conv>
5050 cropping - L<Imager::Transformations/crop()>
5052 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5054 C<diff> images - L<Imager::Filters/"Image Difference">
5056 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
5057 L<Imager::Cookbook/"Image spatial resolution">
5059 drawing boxes - L<Imager::Draw/box()>
5061 drawing lines - L<Imager::Draw/line()>
5063 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
5065 error message - L</"ERROR HANDLING">
5067 files, font - L<Imager::Font>
5069 files, image - L<Imager::Files>
5071 filling, types of fill - L<Imager::Fill>
5073 filling, boxes - L<Imager::Draw/box()>
5075 filling, flood fill - L<Imager::Draw/flood_fill()>
5077 flood fill - L<Imager::Draw/flood_fill()>
5079 fonts - L<Imager::Font>
5081 fonts, drawing with - L<Imager::Draw/string()>,
5082 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
5084 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5086 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
5088 fountain fill - L<Imager::Fill/"Fountain fills">,
5089 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5090 L<Imager::Filters/gradgen>
5092 GIF files - L<Imager::Files/"GIF">
5094 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
5096 gradient fill - L<Imager::Fill/"Fountain fills">,
5097 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5098 L<Imager::Filters/gradgen>
5100 gray scale, convert image to - L<Imager::Transformations/convert()>
5102 gaussian blur - L<Imager::Filters/gaussian>
5104 hatch fills - L<Imager::Fill/"Hatched fills">
5106 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5108 invert image - L<Imager::Filters/hardinvert>,
5109 L<Imager::Filters/hardinvertall>
5111 JPEG - L<Imager::Files/"JPEG">
5113 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
5115 lines, drawing - L<Imager::Draw/line()>
5117 matrix - L<Imager::Matrix2d>,
5118 L<Imager::Engines/"Matrix Transformations">,
5119 L<Imager::Font/transform()>
5121 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5123 mosaic - L<Imager::Filters/mosaic>
5125 noise, filter - L<Imager::Filters/noise>
5127 noise, rendered - L<Imager::Filters/turbnoise>,
5128 L<Imager::Filters/radnoise>
5130 paste - L<Imager::Transformations/paste()>,
5131 L<Imager::Transformations/rubthrough()>
5133 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5134 L<Imager::ImageTypes/new()>
5136 =for stopwords posterize
5138 posterize - L<Imager::Filters/postlevels>
5140 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5142 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5144 rectangles, drawing - L<Imager::Draw/box()>
5146 resizing an image - L<Imager::Transformations/scale()>,
5147 L<Imager::Transformations/crop()>
5149 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5151 saving an image - L<Imager::Files>
5153 scaling - L<Imager::Transformations/scale()>
5155 security - L<Imager::Security>
5157 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5159 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
5161 size, image - L<Imager::ImageTypes/getwidth()>,
5162 L<Imager::ImageTypes/getheight()>
5164 size, text - L<Imager::Font/bounding_box()>
5166 tags, image metadata - L<Imager::ImageTypes/"Tags">
5168 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5169 L<Imager::Font::Wrap>
5171 text, wrapping text in an area - L<Imager::Font::Wrap>
5173 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5175 threads - L<Imager::Threads>
5177 tiles, color - L<Imager::Filters/mosaic>
5179 transparent images - L<Imager::ImageTypes>,
5180 L<Imager::Cookbook/"Transparent PNG">
5182 =for stopwords unsharp
5184 unsharp mask - L<Imager::Filters/unsharpmask>
5186 watermark - L<Imager::Filters/watermark>
5188 writing an image to a file - L<Imager::Files>
5192 The best place to get help with Imager is the mailing list.
5194 To subscribe send a message with C<subscribe> in the body to:
5196 imager-devel+request@molar.is
5202 L<http://www.molar.is/en/lists/imager-devel/>
5206 where you can also find the mailing list archive.
5208 You can report bugs by pointing your browser at:
5212 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5216 or by sending an email to:
5220 bug-Imager@rt.cpan.org
5224 Please remember to include the versions of Imager, perl, supporting
5225 libraries, and any relevant code. If you have specific images that
5226 cause the problems, please include those too.
5228 If you don't want to publish your email address on a mailing list you
5229 can use CPAN::Forum:
5231 http://www.cpanforum.com/dist/Imager
5233 You will need to register to post.
5235 =head1 CONTRIBUTING TO IMAGER
5241 If you like or dislike Imager, you can add a public review of Imager
5244 http://cpanratings.perl.org/dist/Imager
5246 =for stopwords Bitcard
5248 This requires a Bitcard account (http://www.bitcard.org).
5250 You can also send email to the maintainer below.
5252 If you send me a bug report via email, it will be copied to Request
5257 I accept patches, preferably against the master branch in git. Please
5258 include an explanation of the reason for why the patch is needed or
5261 Your patch should include regression tests where possible, otherwise
5262 it will be delayed until I get a chance to write them.
5264 To browse Imager's git repository:
5266 http://git.imager.perl.org/imager.git
5270 git clone git://git.imager.perl.org/imager.git
5272 My preference is that patches are provided in the format produced by
5273 C<git format-patch>, for example, if you made your changes in a branch
5274 from master you might do:
5276 git format-patch -k --stdout master >my-patch.txt
5278 and then attach that to your bug report, either by adding it as an
5279 attachment in your email client, or by using the Request Tracker
5280 attachment mechanism.
5284 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5286 Arnar M. Hrafnkelsson is the original author of Imager.
5288 Many others have contributed to Imager, please see the C<README> for a
5293 Imager is licensed under the same terms as perl itself.
5296 makeblendedfont Fontforge
5298 A test font, generated by the Debian packaged Fontforge,
5299 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5300 copyrighted by Adobe. See F<adobe.txt> in the source for license
5305 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5306 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5307 L<Imager::Font>(3), L<Imager::Transformations>(3),
5308 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5309 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5311 L<http://imager.perl.org/>
5313 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5315 Other perl imaging modules include:
5317 L<GD>(3), L<Image::Magick>(3),
5318 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5319 L<Prima::Image>, L<IPA>.
5321 For manipulating image metadata see L<Image::ExifTool>.
5323 If you're trying to use Imager for array processing, you should
5324 probably using L<PDL>.