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);
1490 # Read an image from file
1496 if (defined($self->{IMG})) {
1497 # let IIM_DESTROY do the destruction, since the image may be
1498 # referenced from elsewhere
1499 #i_img_destroy($self->{IMG});
1500 undef($self->{IMG});
1503 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1505 my $type = $input{'type'};
1507 $type = i_test_format_probe($IO, -1);
1510 if ($input{file} && !$type) {
1512 $type = $FORMATGUESS->($input{file});
1516 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1517 $input{file} and $msg .= " or file name";
1518 $self->_set_error($msg);
1522 _reader_autoload($type);
1524 if ($readers{$type} && $readers{$type}{single}) {
1525 return $readers{$type}{single}->($self, $IO, %input);
1528 unless ($formats_low{$type}) {
1529 my $read_types = join ', ', sort Imager->read_types();
1530 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1534 my $allow_incomplete = $input{allow_incomplete};
1535 defined $allow_incomplete or $allow_incomplete = 0;
1537 if ( $type eq 'pnm' ) {
1538 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1539 if ( !defined($self->{IMG}) ) {
1540 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1543 $self->{DEBUG} && print "loading a pnm file\n";
1547 if ( $type eq 'bmp' ) {
1548 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1549 if ( !defined($self->{IMG}) ) {
1550 $self->{ERRSTR}=$self->_error_as_msg();
1553 $self->{DEBUG} && print "loading a bmp file\n";
1556 if ( $type eq 'tga' ) {
1557 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1558 if ( !defined($self->{IMG}) ) {
1559 $self->{ERRSTR}=$self->_error_as_msg();
1562 $self->{DEBUG} && print "loading a tga file\n";
1565 if ( $type eq 'raw' ) {
1566 unless ( $input{xsize} && $input{ysize} ) {
1567 $self->_set_error('missing xsize or ysize parameter for raw');
1571 my $interleave = _first($input{raw_interleave}, $input{interleave});
1572 unless (defined $interleave) {
1573 my @caller = caller;
1574 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1577 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1578 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1580 $self->{IMG} = i_readraw_wiol( $IO,
1586 if ( !defined($self->{IMG}) ) {
1587 $self->{ERRSTR}=$self->_error_as_msg();
1590 $self->{DEBUG} && print "loading a raw file\n";
1596 sub register_reader {
1597 my ($class, %opts) = @_;
1600 or die "register_reader called with no type parameter\n";
1602 my $type = $opts{type};
1604 defined $opts{single} || defined $opts{multiple}
1605 or die "register_reader called with no single or multiple parameter\n";
1607 $readers{$type} = { };
1608 if ($opts{single}) {
1609 $readers{$type}{single} = $opts{single};
1611 if ($opts{multiple}) {
1612 $readers{$type}{multiple} = $opts{multiple};
1618 sub register_writer {
1619 my ($class, %opts) = @_;
1622 or die "register_writer called with no type parameter\n";
1624 my $type = $opts{type};
1626 defined $opts{single} || defined $opts{multiple}
1627 or die "register_writer called with no single or multiple parameter\n";
1629 $writers{$type} = { };
1630 if ($opts{single}) {
1631 $writers{$type}{single} = $opts{single};
1633 if ($opts{multiple}) {
1634 $writers{$type}{multiple} = $opts{multiple};
1645 grep($file_formats{$_}, keys %formats),
1646 qw(ico sgi), # formats not handled directly, but supplied with Imager
1657 grep($file_formats{$_}, keys %formats),
1658 qw(ico sgi), # formats not handled directly, but supplied with Imager
1665 my ($file, $error) = @_;
1667 if ($attempted_to_load{$file}) {
1668 if ($file_load_errors{$file}) {
1669 $$error = $file_load_errors{$file};
1677 local $SIG{__DIE__};
1680 pop @INC if $INC[-1] eq '.';
1681 ++$attempted_to_load{$file};
1689 my $work = $@ || "Unknown error";
1691 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1692 $work =~ s/\n/\\n/g;
1693 $work =~ s/\s*\.?\z/ loading $file/;
1694 $file_load_errors{$file} = $work;
1701 # probes for an Imager::File::whatever module
1702 sub _reader_autoload {
1705 return if $formats_low{$type} || $readers{$type};
1707 return unless $type =~ /^\w+$/;
1709 my $file = "Imager/File/\U$type\E.pm";
1712 my $loaded = _load_file($file, \$error);
1713 if (!$loaded && $error =~ /^Can't locate /) {
1714 my $filer = "Imager/File/\U$type\EReader.pm";
1715 $loaded = _load_file($filer, \$error);
1716 if ($error =~ /^Can't locate /) {
1717 $error = "Can't locate $file or $filer";
1721 $reader_load_errors{$type} = $error;
1725 # probes for an Imager::File::whatever module
1726 sub _writer_autoload {
1729 return if $formats_low{$type} || $writers{$type};
1731 return unless $type =~ /^\w+$/;
1733 my $file = "Imager/File/\U$type\E.pm";
1736 my $loaded = _load_file($file, \$error);
1737 if (!$loaded && $error =~ /^Can't locate /) {
1738 my $filew = "Imager/File/\U$type\EWriter.pm";
1739 $loaded = _load_file($filew, \$error);
1740 if ($error =~ /^Can't locate /) {
1741 $error = "Can't locate $file or $filew";
1745 $writer_load_errors{$type} = $error;
1749 sub _fix_gif_positions {
1750 my ($opts, $opt, $msg, @imgs) = @_;
1752 my $positions = $opts->{'gif_positions'};
1754 for my $pos (@$positions) {
1755 my ($x, $y) = @$pos;
1756 my $img = $imgs[$index++];
1757 $img->settag(name=>'gif_left', value=>$x);
1758 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1760 $$msg .= "replaced with the gif_left and gif_top tags";
1765 gif_each_palette=>'gif_local_map',
1766 interlace => 'gif_interlace',
1767 gif_delays => 'gif_delay',
1768 gif_positions => \&_fix_gif_positions,
1769 gif_loop_count => 'gif_loop',
1772 # options that should be converted to colors
1773 my %color_opts = map { $_ => 1 } qw/i_background/;
1776 my ($self, $opts, $prefix, @imgs) = @_;
1778 for my $opt (keys %$opts) {
1780 if ($obsolete_opts{$opt}) {
1781 my $new = $obsolete_opts{$opt};
1782 my $msg = "Obsolete option $opt ";
1784 $new->($opts, $opt, \$msg, @imgs);
1787 $msg .= "replaced with the $new tag ";
1790 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1791 warn $msg if $warn_obsolete && $^W;
1793 next unless $tagname =~ /^\Q$prefix/;
1794 my $value = $opts->{$opt};
1795 if ($color_opts{$opt}) {
1796 $value = _color($value);
1798 $self->_set_error($Imager::ERRSTR);
1803 if (UNIVERSAL::isa($value, "Imager::Color")) {
1804 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1805 for my $img (@imgs) {
1806 $img->settag(name=>$tagname, value=>$tag);
1809 elsif (ref($value) eq 'ARRAY') {
1810 for my $i (0..$#$value) {
1811 my $val = $value->[$i];
1813 if (UNIVERSAL::isa($val, "Imager::Color")) {
1814 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1816 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1819 $self->_set_error("Unknown reference type " . ref($value) .
1820 " supplied in array for $opt");
1826 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1831 $self->_set_error("Unknown reference type " . ref($value) .
1832 " supplied for $opt");
1837 # set it as a tag for every image
1838 for my $img (@imgs) {
1839 $img->settag(name=>$tagname, value=>$value);
1847 # Write an image to file
1850 my %input=(jpegquality=>75,
1860 $self->_valid_image("write")
1863 $self->_set_opts(\%input, "i_", $self)
1866 my $type = $input{'type'};
1867 if (!$type and $input{file}) {
1868 $type = $FORMATGUESS->($input{file});
1871 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1875 _writer_autoload($type);
1878 if ($writers{$type} && $writers{$type}{single}) {
1879 ($IO, $fh) = $self->_get_writer_io(\%input)
1882 $writers{$type}{single}->($self, $IO, %input, type => $type)
1886 if (!$formats_low{$type}) {
1887 my $write_types = join ', ', sort Imager->write_types();
1888 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1892 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1895 if ( $type eq 'pnm' ) {
1896 $self->_set_opts(\%input, "pnm_", $self)
1898 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1899 $self->{ERRSTR} = $self->_error_as_msg();
1902 $self->{DEBUG} && print "writing a pnm file\n";
1904 elsif ( $type eq 'raw' ) {
1905 $self->_set_opts(\%input, "raw_", $self)
1907 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1908 $self->{ERRSTR} = $self->_error_as_msg();
1911 $self->{DEBUG} && print "writing a raw file\n";
1913 elsif ( $type eq 'bmp' ) {
1914 $self->_set_opts(\%input, "bmp_", $self)
1916 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1917 $self->{ERRSTR} = $self->_error_as_msg;
1920 $self->{DEBUG} && print "writing a bmp file\n";
1922 elsif ( $type eq 'tga' ) {
1923 $self->_set_opts(\%input, "tga_", $self)
1926 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1927 $self->{ERRSTR}=$self->_error_as_msg();
1930 $self->{DEBUG} && print "writing a tga file\n";
1934 if (exists $input{'data'}) {
1935 my $data = io_slurp($IO);
1937 $self->{ERRSTR}='Could not slurp from buffer';
1940 ${$input{data}} = $data;
1946 my ($class, $opts, @images) = @_;
1948 my $type = $opts->{type};
1950 if (!$type && $opts->{'file'}) {
1951 $type = $FORMATGUESS->($opts->{'file'});
1954 $class->_set_error('type parameter missing and not possible to guess from extension');
1957 # translate to ImgRaw
1959 for my $img (@images) {
1960 unless (ref $img && Scalar::Util::blessed($img) && $img->isa("Imager")) {
1961 $class->_set_error("write_multi: image $index is not an Imager image object");
1964 unless ($img->_valid_image("write_multi")) {
1965 $class->_set_error($img->errstr . " (image $index)");
1970 $class->_set_opts($opts, "i_", @images)
1972 my @work = map $_->{IMG}, @images;
1974 _writer_autoload($type);
1977 if ($writers{$type} && $writers{$type}{multiple}) {
1978 ($IO, $file) = $class->_get_writer_io($opts, $type)
1981 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1985 if (!$formats{$type}) {
1986 my $write_types = join ', ', sort Imager->write_types();
1987 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1991 ($IO, $file) = $class->_get_writer_io($opts, $type)
1994 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1998 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
2003 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
2009 if (exists $opts->{'data'}) {
2010 my $data = io_slurp($IO);
2012 Imager->_set_error('Could not slurp from buffer');
2015 ${$opts->{data}} = $data;
2020 # read multiple images from a file
2022 my ($class, %opts) = @_;
2024 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2027 my $type = $opts{'type'};
2029 $type = i_test_format_probe($IO, -1);
2032 if ($opts{file} && !$type) {
2034 $type = $FORMATGUESS->($opts{file});
2038 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2039 $opts{file} and $msg .= " or file name";
2040 Imager->_set_error($msg);
2044 _reader_autoload($type);
2046 if ($readers{$type} && $readers{$type}{multiple}) {
2047 return $readers{$type}{multiple}->($IO, %opts);
2050 unless ($formats{$type}) {
2051 my $read_types = join ', ', sort Imager->read_types();
2052 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2057 if ($type eq 'pnm') {
2058 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2061 my $img = Imager->new;
2062 if ($img->read(%opts, io => $IO, type => $type)) {
2065 Imager->_set_error($img->errstr);
2070 $ERRSTR = _error_as_msg();
2074 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2078 # Destroy an Imager object
2082 # delete $instances{$self};
2083 if (defined($self->{IMG})) {
2084 # the following is now handled by the XS DESTROY method for
2085 # Imager::ImgRaw object
2086 # Re-enabling this will break virtual images
2087 # tested for in t/t020masked.t
2088 # i_img_destroy($self->{IMG});
2089 undef($self->{IMG});
2091 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2095 # Perform an inplace filter of an image
2096 # that is the image will be overwritten with the data
2103 $self->_valid_image("filter")
2106 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2108 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2109 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2112 if ($filters{$input{'type'}}{names}) {
2113 my $names = $filters{$input{'type'}}{names};
2114 for my $name (keys %$names) {
2115 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2116 $input{$name} = $names->{$name}{$input{$name}};
2120 if (defined($filters{$input{'type'}}{defaults})) {
2121 %hsh=( image => $self->{IMG},
2123 %{$filters{$input{'type'}}{defaults}},
2126 %hsh=( image => $self->{IMG},
2131 my @cs=@{$filters{$input{'type'}}{callseq}};
2134 if (!defined($hsh{$_})) {
2135 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2140 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2141 &{$filters{$input{'type'}}{callsub}}(%hsh);
2144 chomp($self->{ERRSTR} = $@);
2150 $self->{DEBUG} && print "callseq is: @cs\n";
2151 $self->{DEBUG} && print "matching callseq is: @b\n";
2156 sub register_filter {
2158 my %hsh = ( defaults => {}, @_ );
2161 or die "register_filter() with no type\n";
2162 defined $hsh{callsub}
2163 or die "register_filter() with no callsub\n";
2164 defined $hsh{callseq}
2165 or die "register_filter() with no callseq\n";
2167 exists $filters{$hsh{type}}
2170 $filters{$hsh{type}} = \%hsh;
2175 sub scale_calculate {
2178 my %opts = ('type'=>'max', @_);
2180 # none of these should be references
2181 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2182 if (defined $opts{$name} && ref $opts{$name}) {
2183 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2188 my ($x_scale, $y_scale);
2189 my $width = $opts{width};
2190 my $height = $opts{height};
2192 defined $width or $width = $self->getwidth;
2193 defined $height or $height = $self->getheight;
2196 unless (defined $width && defined $height) {
2197 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2202 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2203 $x_scale = $opts{'xscalefactor'};
2204 $y_scale = $opts{'yscalefactor'};
2206 elsif ($opts{'xscalefactor'}) {
2207 $x_scale = $opts{'xscalefactor'};
2208 $y_scale = $opts{'scalefactor'} || $x_scale;
2210 elsif ($opts{'yscalefactor'}) {
2211 $y_scale = $opts{'yscalefactor'};
2212 $x_scale = $opts{'scalefactor'} || $y_scale;
2215 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2218 # work out the scaling
2219 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2220 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2221 $opts{ypixels} / $height );
2222 if ($opts{'type'} eq 'min') {
2223 $x_scale = $y_scale = _min($xpix,$ypix);
2225 elsif ($opts{'type'} eq 'max') {
2226 $x_scale = $y_scale = _max($xpix,$ypix);
2228 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2233 $self->_set_error('invalid value for type parameter');
2236 } elsif ($opts{xpixels}) {
2237 $x_scale = $y_scale = $opts{xpixels} / $width;
2239 elsif ($opts{ypixels}) {
2240 $x_scale = $y_scale = $opts{ypixels}/$height;
2242 elsif ($opts{constrain} && ref $opts{constrain}
2243 && $opts{constrain}->can('constrain')) {
2244 # we've been passed an Image::Math::Constrain object or something
2245 # that looks like one
2247 (undef, undef, $scalefactor)
2248 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2249 unless ($scalefactor) {
2250 $self->_set_error('constrain method failed on constrain parameter');
2253 $x_scale = $y_scale = $scalefactor;
2256 my $new_width = int($x_scale * $width + 0.5);
2257 $new_width > 0 or $new_width = 1;
2258 my $new_height = int($y_scale * $height + 0.5);
2259 $new_height > 0 or $new_height = 1;
2261 return ($x_scale, $y_scale, $new_width, $new_height);
2265 # Scale an image to requested size and return the scaled version
2269 my %opts = (qtype=>'normal' ,@_);
2270 my $img = Imager->new();
2271 my $tmp = Imager->new();
2273 unless (defined wantarray) {
2274 my @caller = caller;
2275 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2279 $self->_valid_image("scale")
2282 my ($x_scale, $y_scale, $new_width, $new_height) =
2283 $self->scale_calculate(%opts)
2286 if ($opts{qtype} eq 'normal') {
2287 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2288 if ( !defined($tmp->{IMG}) ) {
2289 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2292 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2293 if ( !defined($img->{IMG}) ) {
2294 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2300 elsif ($opts{'qtype'} eq 'preview') {
2301 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2302 if ( !defined($img->{IMG}) ) {
2303 $self->{ERRSTR}='unable to scale image';
2308 elsif ($opts{'qtype'} eq 'mixing') {
2309 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2310 unless ($img->{IMG}) {
2311 $self->_set_error(Imager->_error_as_msg);
2317 $self->_set_error('invalid value for qtype parameter');
2322 # Scales only along the X axis
2326 my %opts = ( scalefactor=>0.5, @_ );
2328 unless (defined wantarray) {
2329 my @caller = caller;
2330 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2334 $self->_valid_image("scaleX")
2337 my $img = Imager->new();
2339 my $scalefactor = $opts{scalefactor};
2341 if ($opts{pixels}) {
2342 $scalefactor = $opts{pixels} / $self->getwidth();
2345 unless ($self->{IMG}) {
2346 $self->{ERRSTR}='empty input image';
2350 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2352 if ( !defined($img->{IMG}) ) {
2353 $self->{ERRSTR} = 'unable to scale image';
2360 # Scales only along the Y axis
2364 my %opts = ( scalefactor => 0.5, @_ );
2366 unless (defined wantarray) {
2367 my @caller = caller;
2368 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2372 $self->_valid_image("scaleY")
2375 my $img = Imager->new();
2377 my $scalefactor = $opts{scalefactor};
2379 if ($opts{pixels}) {
2380 $scalefactor = $opts{pixels} / $self->getheight();
2383 unless ($self->{IMG}) {
2384 $self->{ERRSTR} = 'empty input image';
2387 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2389 if ( !defined($img->{IMG}) ) {
2390 $self->{ERRSTR} = 'unable to scale image';
2397 # Transform returns a spatial transformation of the input image
2398 # this moves pixels to a new location in the returned image.
2399 # NOTE - should make a utility function to check transforms for
2405 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2407 # print Dumper(\%opts);
2410 $self->_valid_image("transform")
2413 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2417 pop @INC if $INC[-1] eq '.';
2418 eval ("use Affix::Infix2Postfix;");
2422 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2425 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2426 {op=>'-',trans=>'Sub'},
2427 {op=>'*',trans=>'Mult'},
2428 {op=>'/',trans=>'Div'},
2429 {op=>'-','type'=>'unary',trans=>'u-'},
2431 {op=>'func','type'=>'unary'}],
2432 'grouping'=>[qw( \( \) )],
2433 'func'=>[qw( sin cos )],
2438 @xt=$I2P->translate($opts{'xexpr'});
2439 @yt=$I2P->translate($opts{'yexpr'});
2441 $numre=$I2P->{'numre'};
2444 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2445 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2446 @{$opts{'parm'}}=@pt;
2449 # print Dumper(\%opts);
2451 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2452 $self->{ERRSTR}='transform: no xopcodes given.';
2456 @op=@{$opts{'xopcodes'}};
2458 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2459 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2462 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2468 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2469 $self->{ERRSTR}='transform: no yopcodes given.';
2473 @op=@{$opts{'yopcodes'}};
2475 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2476 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2479 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2484 if ( !exists $opts{'parm'}) {
2485 $self->{ERRSTR}='transform: no parameter arg given.';
2489 # print Dumper(\@ropx);
2490 # print Dumper(\@ropy);
2491 # print Dumper(\@ropy);
2493 my $img = Imager->new();
2494 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2495 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2501 my ($opts, @imgs) = @_;
2503 require "Imager/Expr.pm";
2505 $opts->{variables} = [ qw(x y) ];
2506 my ($width, $height) = @{$opts}{qw(width height)};
2509 for my $img (@imgs) {
2510 unless ($img->_valid_image("transform2")) {
2511 Imager->_set_error($img->errstr . " (input image $index)");
2517 $width ||= $imgs[0]->getwidth();
2518 $height ||= $imgs[0]->getheight();
2520 for my $img (@imgs) {
2521 $opts->{constants}{"w$img_num"} = $img->getwidth();
2522 $opts->{constants}{"h$img_num"} = $img->getheight();
2523 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2524 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2529 $opts->{constants}{w} = $width;
2530 $opts->{constants}{cx} = $width/2;
2533 $Imager::ERRSTR = "No width supplied";
2537 $opts->{constants}{h} = $height;
2538 $opts->{constants}{cy} = $height/2;
2541 $Imager::ERRSTR = "No height supplied";
2544 my $code = Imager::Expr->new($opts);
2546 $Imager::ERRSTR = Imager::Expr::error();
2549 my $channels = $opts->{channels} || 3;
2550 unless ($channels >= 1 && $channels <= 4) {
2551 return Imager->_set_error("channels must be an integer between 1 and 4");
2554 my $img = Imager->new();
2555 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2556 $channels, $code->code(),
2557 $code->nregs(), $code->cregs(),
2558 [ map { $_->{IMG} } @imgs ]);
2559 if (!defined $img->{IMG}) {
2560 $Imager::ERRSTR = Imager->_error_as_msg();
2571 $self->_valid_image("rubthrough")
2574 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2575 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2579 %opts = (src_minx => 0,
2581 src_maxx => $opts{src}->getwidth(),
2582 src_maxy => $opts{src}->getheight(),
2586 defined $tx or $tx = $opts{left};
2587 defined $tx or $tx = 0;
2590 defined $ty or $ty = $opts{top};
2591 defined $ty or $ty = 0;
2593 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2594 $opts{src_minx}, $opts{src_miny},
2595 $opts{src_maxx}, $opts{src_maxy})) {
2596 $self->_set_error($self->_error_as_msg());
2613 $self->_valid_image("compose")
2616 unless ($opts{src}) {
2617 $self->_set_error("compose: src parameter missing");
2621 unless ($opts{src}->_valid_image("compose")) {
2622 $self->_set_error($opts{src}->errstr . " (for src)");
2625 my $src = $opts{src};
2627 my $left = $opts{left};
2628 defined $left or $left = $opts{tx};
2629 defined $left or $left = 0;
2631 my $top = $opts{top};
2632 defined $top or $top = $opts{ty};
2633 defined $top or $top = 0;
2635 my $src_left = $opts{src_left};
2636 defined $src_left or $src_left = $opts{src_minx};
2637 defined $src_left or $src_left = 0;
2639 my $src_top = $opts{src_top};
2640 defined $src_top or $src_top = $opts{src_miny};
2641 defined $src_top or $src_top = 0;
2643 my $width = $opts{width};
2644 if (!defined $width && defined $opts{src_maxx}) {
2645 $width = $opts{src_maxx} - $src_left;
2647 defined $width or $width = $src->getwidth() - $src_left;
2649 my $height = $opts{height};
2650 if (!defined $height && defined $opts{src_maxy}) {
2651 $height = $opts{src_maxy} - $src_top;
2653 defined $height or $height = $src->getheight() - $src_top;
2655 my $combine = $self->_combine($opts{combine}, 'normal');
2658 unless ($opts{mask}->_valid_image("compose")) {
2659 $self->_set_error($opts{mask}->errstr . " (for mask)");
2663 my $mask_left = $opts{mask_left};
2664 defined $mask_left or $mask_left = $opts{mask_minx};
2665 defined $mask_left or $mask_left = 0;
2667 my $mask_top = $opts{mask_top};
2668 defined $mask_top or $mask_top = $opts{mask_miny};
2669 defined $mask_top or $mask_top = 0;
2671 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2672 $left, $top, $src_left, $src_top,
2673 $mask_left, $mask_top, $width, $height,
2674 $combine, $opts{opacity})) {
2675 $self->_set_error(Imager->_error_as_msg);
2680 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2681 $width, $height, $combine, $opts{opacity})) {
2682 $self->_set_error(Imager->_error_as_msg);
2694 $self->_valid_image("flip")
2697 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2699 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2700 $dir = $xlate{$opts{'dir'}};
2701 return $self if i_flipxy($self->{IMG}, $dir);
2709 unless (defined wantarray) {
2710 my @caller = caller;
2711 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2715 $self->_valid_image("rotate")
2718 if (defined $opts{right}) {
2719 my $degrees = $opts{right};
2721 $degrees += 360 * int(((-$degrees)+360)/360);
2723 $degrees = $degrees % 360;
2724 if ($degrees == 0) {
2725 return $self->copy();
2727 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2728 my $result = Imager->new();
2729 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2733 $self->{ERRSTR} = $self->_error_as_msg();
2738 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2742 elsif (defined $opts{radians} || defined $opts{degrees}) {
2743 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2745 my $back = $opts{back};
2746 my $result = Imager->new;
2748 $back = _color($back);
2750 $self->_set_error(Imager->errstr);
2754 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2757 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2759 if ($result->{IMG}) {
2763 $self->{ERRSTR} = $self->_error_as_msg();
2768 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2773 sub matrix_transform {
2777 $self->_valid_image("matrix_transform")
2780 unless (defined wantarray) {
2781 my @caller = caller;
2782 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2786 if ($opts{matrix}) {
2787 my $xsize = $opts{xsize} || $self->getwidth;
2788 my $ysize = $opts{ysize} || $self->getheight;
2790 my $result = Imager->new;
2792 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2793 $opts{matrix}, $opts{back})
2797 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2805 $self->{ERRSTR} = "matrix parameter required";
2811 *yatf = \&matrix_transform;
2813 # These two are supported for legacy code only
2816 return Imager::Color->new(@_);
2820 return Imager::Color::set(@_);
2823 # Draws a box between the specified corner points.
2826 my $raw = $self->{IMG};
2828 $self->_valid_image("box")
2833 my ($xmin, $ymin, $xmax, $ymax);
2834 if (exists $opts{'box'}) {
2835 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2836 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2837 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2838 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2841 defined($xmin = $opts{xmin}) or $xmin = 0;
2842 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2843 defined($ymin = $opts{ymin}) or $ymin = 0;
2844 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2847 if ($opts{filled}) {
2848 my $color = $opts{'color'};
2850 if (defined $color) {
2851 unless (_is_color_object($color)) {
2852 $color = _color($color);
2854 $self->{ERRSTR} = $Imager::ERRSTR;
2860 $color = i_color_new(255,255,255,255);
2863 if ($color->isa("Imager::Color")) {
2864 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2867 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2870 elsif ($opts{fill}) {
2871 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2872 # assume it's a hash ref
2873 require 'Imager/Fill.pm';
2874 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2875 $self->{ERRSTR} = $Imager::ERRSTR;
2879 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2882 my $color = $opts{'color'};
2883 if (defined $color) {
2884 unless (_is_color_object($color)) {
2885 $color = _color($color);
2887 $self->{ERRSTR} = $Imager::ERRSTR;
2893 $color = i_color_new(255, 255, 255, 255);
2896 $self->{ERRSTR} = $Imager::ERRSTR;
2899 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2908 $self->_valid_image("arc")
2911 my $dflcl= [ 255, 255, 255, 255];
2916 'r'=>_min($self->getwidth(),$self->getheight())/3,
2917 'x'=>$self->getwidth()/2,
2918 'y'=>$self->getheight()/2,
2925 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2926 # assume it's a hash ref
2927 require 'Imager/Fill.pm';
2928 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2929 $self->{ERRSTR} = $Imager::ERRSTR;
2933 if ($opts{d1} == 0 && $opts{d2} == 361) {
2934 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2938 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2939 $opts{'d2'}, $opts{fill}{fill});
2942 elsif ($opts{filled}) {
2943 my $color = _color($opts{'color'});
2945 $self->{ERRSTR} = $Imager::ERRSTR;
2948 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2949 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2953 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2954 $opts{'d1'}, $opts{'d2'}, $color);
2958 my $color = _color($opts{'color'});
2959 if ($opts{d2} - $opts{d1} >= 360) {
2960 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2963 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2969 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2970 # assume it's a hash ref
2971 require 'Imager/Fill.pm';
2972 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2973 $self->{ERRSTR} = $Imager::ERRSTR;
2977 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2978 $opts{'d2'}, $opts{fill}{fill});
2981 my $color = _color($opts{'color'});
2983 $self->{ERRSTR} = $Imager::ERRSTR;
2986 if ($opts{filled}) {
2987 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2988 $opts{'d1'}, $opts{'d2'}, $color);
2991 if ($opts{d1} == 0 && $opts{d2} == 361) {
2992 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2995 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
3001 $self->_set_error($self->_error_as_msg);
3008 # Draws a line from one point to the other
3009 # the endpoint is set if the endp parameter is set which it is by default.
3010 # to turn of the endpoint being set use endp=>0 when calling line.
3014 my $dflcl=i_color_new(0,0,0,0);
3015 my %opts=(color=>$dflcl,
3019 $self->_valid_image("line")
3022 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
3023 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
3025 my $color = _color($opts{'color'});
3027 $self->{ERRSTR} = $Imager::ERRSTR;
3031 $opts{antialias} = $opts{aa} if defined $opts{aa};
3032 if ($opts{antialias}) {
3033 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3034 $color, $opts{endp});
3036 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3037 $color, $opts{endp});
3042 # Draws a line between an ordered set of points - It more or less just transforms this
3043 # into a list of lines.
3047 my ($pt,$ls,@points);
3048 my $dflcl=i_color_new(0,0,0,0);
3049 my %opts=(color=>$dflcl,@_);
3051 $self->_valid_image("polyline")
3054 if (exists($opts{points})) { @points=@{$opts{points}}; }
3055 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3056 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3059 # print Dumper(\@points);
3061 my $color = _color($opts{'color'});
3063 $self->{ERRSTR} = $Imager::ERRSTR;
3066 $opts{antialias} = $opts{aa} if defined $opts{aa};
3067 if ($opts{antialias}) {
3070 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3077 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3087 my ($pt,$ls,@points);
3088 my $dflcl = i_color_new(0,0,0,0);
3089 my %opts = (color=>$dflcl, @_);
3091 $self->_valid_image("polygon")
3094 if (exists($opts{points})) {
3095 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3096 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3099 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3100 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3103 my $mode = _first($opts{mode}, 0);
3105 if ($opts{'fill'}) {
3106 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3107 # assume it's a hash ref
3108 require 'Imager/Fill.pm';
3109 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3110 $self->{ERRSTR} = $Imager::ERRSTR;
3114 unless (i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3115 $mode, $opts{'fill'}{'fill'})) {
3116 return $self->_set_error($self->_error_as_msg);
3120 my $color = _color($opts{'color'});
3122 $self->{ERRSTR} = $Imager::ERRSTR;
3125 unless (i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color)) {
3126 return $self->_set_error($self->_error_as_msg);
3134 my ($self, %opts) = @_;
3136 $self->_valid_image("polypolygon")
3139 my $points = $opts{points};
3141 or return $self->_set_error("polypolygon: missing required points");
3143 my $mode = _first($opts{mode}, "evenodd");
3145 if ($opts{filled}) {
3146 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3147 or return $self->_set_error($Imager::ERRSTR);
3149 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3150 or return $self->_set_error($self->_error_as_msg);
3152 elsif ($opts{fill}) {
3153 my $fill = $opts{fill};
3154 $self->_valid_fill($fill, "polypolygon")
3157 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3158 or return $self->_set_error($self->_error_as_msg);
3161 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3162 or return $self->_set_error($Imager::ERRSTR);
3164 my $rimg = $self->{IMG};
3166 if (_first($opts{aa}, 1)) {
3167 for my $poly (@$points) {
3168 my $xp = $poly->[0];
3169 my $yp = $poly->[1];
3170 for my $i (0 .. $#$xp - 1) {
3171 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3174 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3179 for my $poly (@$points) {
3180 my $xp = $poly->[0];
3181 my $yp = $poly->[1];
3182 for my $i (0 .. $#$xp - 1) {
3183 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3186 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3195 # this the multipoint bezier curve
3196 # this is here more for testing that actual usage since
3197 # this is not a good algorithm. Usually the curve would be
3198 # broken into smaller segments and each done individually.
3202 my ($pt,$ls,@points);
3203 my $dflcl=i_color_new(0,0,0,0);
3204 my %opts=(color=>$dflcl,@_);
3206 $self->_valid_image("polybezier")
3209 if (exists $opts{points}) {
3210 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3211 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3214 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3215 $self->{ERRSTR}='Missing or invalid points.';
3219 my $color = _color($opts{'color'});
3221 $self->{ERRSTR} = $Imager::ERRSTR;
3224 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3230 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3233 $self->_valid_image("flood_fill")
3236 unless (exists $opts{'x'} && exists $opts{'y'}) {
3237 $self->{ERRSTR} = "missing seed x and y parameters";
3241 if ($opts{border}) {
3242 my $border = _color($opts{border});
3244 $self->_set_error($Imager::ERRSTR);
3248 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3249 # assume it's a hash ref
3250 require Imager::Fill;
3251 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3252 $self->{ERRSTR} = $Imager::ERRSTR;
3256 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3257 $opts{fill}{fill}, $border);
3260 my $color = _color($opts{'color'});
3262 $self->{ERRSTR} = $Imager::ERRSTR;
3265 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3272 $self->{ERRSTR} = $self->_error_as_msg();
3278 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3279 # assume it's a hash ref
3280 require 'Imager/Fill.pm';
3281 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3282 $self->{ERRSTR} = $Imager::ERRSTR;
3286 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3289 my $color = _color($opts{'color'});
3291 $self->{ERRSTR} = $Imager::ERRSTR;
3294 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3300 $self->{ERRSTR} = $self->_error_as_msg();
3307 my ($self, %opts) = @_;
3309 $self->_valid_image("setpixel")
3312 my $color = $opts{color};
3313 unless (defined $color) {
3314 $color = $self->{fg};
3315 defined $color or $color = NC(255, 255, 255);
3318 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3319 unless ($color = _color($color, 'setpixel')) {
3320 $self->_set_error("setpixel: " . Imager->errstr);
3325 unless (exists $opts{'x'} && exists $opts{'y'}) {
3326 $self->_set_error('setpixel: missing x or y parameter');
3332 if (ref $x || ref $y) {
3333 $x = ref $x ? $x : [ $x ];
3334 $y = ref $y ? $y : [ $y ];
3336 $self->_set_error("setpixel: x is a reference to an empty array");
3340 $self->_set_error("setpixel: y is a reference to an empty array");
3344 # make both the same length, replicating the last element
3346 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3349 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3353 if ($color->isa('Imager::Color')) {
3354 for my $i (0..$#$x) {
3355 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3360 for my $i (0..$#$x) {
3361 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3369 if ($color->isa('Imager::Color')) {
3370 i_ppix($self->{IMG}, $x, $y, $color)
3371 and return "0 but true";
3374 i_ppixf($self->{IMG}, $x, $y, $color)
3375 and return "0 but true";
3385 my %opts = ( "type"=>'8bit', @_);
3387 $self->_valid_image("getpixel")
3390 unless (exists $opts{'x'} && exists $opts{'y'}) {
3391 $self->_set_error('getpixel: missing x or y parameter');
3397 my $type = $opts{'type'};
3398 if (ref $x || ref $y) {
3399 $x = ref $x ? $x : [ $x ];
3400 $y = ref $y ? $y : [ $y ];
3402 $self->_set_error("getpixel: x is a reference to an empty array");
3406 $self->_set_error("getpixel: y is a reference to an empty array");
3410 # make both the same length, replicating the last element
3412 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3415 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3419 if ($type eq '8bit') {
3420 for my $i (0..$#$x) {
3421 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3424 elsif ($type eq 'float' || $type eq 'double') {
3425 for my $i (0..$#$x) {
3426 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3430 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3433 return wantarray ? @result : \@result;
3436 if ($type eq '8bit') {
3437 return i_get_pixel($self->{IMG}, $x, $y);
3439 elsif ($type eq 'float' || $type eq 'double') {
3440 return i_gpixf($self->{IMG}, $x, $y);
3443 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3451 my %opts = ( type => '8bit', x=>0, @_);
3453 $self->_valid_image("getscanline")
3456 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3458 unless (defined $opts{'y'}) {
3459 $self->_set_error("missing y parameter");
3463 if ($opts{type} eq '8bit') {
3464 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3467 elsif ($opts{type} eq 'float') {
3468 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3471 elsif ($opts{type} eq 'index') {
3472 unless (i_img_type($self->{IMG})) {
3473 $self->_set_error("type => index only valid on paletted images");
3476 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3480 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3487 my %opts = ( x=>0, @_);
3489 $self->_valid_image("setscanline")
3492 unless (defined $opts{'y'}) {
3493 $self->_set_error("missing y parameter");
3498 if (ref $opts{pixels} && @{$opts{pixels}}) {
3499 # try to guess the type
3500 if ($opts{pixels}[0]->isa('Imager::Color')) {
3501 $opts{type} = '8bit';
3503 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3504 $opts{type} = 'float';
3507 $self->_set_error("missing type parameter and could not guess from pixels");
3513 $opts{type} = '8bit';
3517 if ($opts{type} eq '8bit') {
3518 if (ref $opts{pixels}) {
3519 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3522 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3525 elsif ($opts{type} eq 'float') {
3526 if (ref $opts{pixels}) {
3527 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3530 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3533 elsif ($opts{type} eq 'index') {
3534 if (ref $opts{pixels}) {
3535 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3538 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3542 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3549 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3551 $self->_valid_image("getsamples")
3554 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3556 unless (defined $opts{'y'}) {
3557 $self->_set_error("missing y parameter");
3561 if ($opts{target}) {
3562 my $target = $opts{target};
3563 my $offset = $opts{offset};
3564 if ($opts{type} eq '8bit') {
3565 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3566 $opts{y}, $opts{channels})
3568 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3569 return scalar(@samples);
3571 elsif ($opts{type} eq 'float') {
3572 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3573 $opts{y}, $opts{channels});
3574 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3575 return scalar(@samples);
3577 elsif ($opts{type} =~ /^(\d+)bit$/) {
3581 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3582 $opts{y}, $bits, $target,
3583 $offset, $opts{channels});
3584 unless (defined $count) {
3585 $self->_set_error(Imager->_error_as_msg);
3592 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3597 if ($opts{type} eq '8bit') {
3598 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3599 $opts{y}, $opts{channels});
3601 elsif ($opts{type} eq 'float') {
3602 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3603 $opts{y}, $opts{channels});
3605 elsif ($opts{type} =~ /^(\d+)bit$/) {
3609 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3610 $opts{y}, $bits, \@data, 0, $opts{channels})
3615 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3624 $self->_valid_image("setsamples")
3627 my %opts = ( x => 0, offset => 0 );
3629 # avoid duplicating the data parameter, it may be a large scalar
3631 while ($i < @_ -1) {
3632 if ($_[$i] eq 'data') {
3636 $opts{$_[$i]} = $_[$i+1];
3642 unless(defined $data_index) {
3643 $self->_set_error('setsamples: data parameter missing');
3646 unless (defined $_[$data_index]) {
3647 $self->_set_error('setsamples: data parameter not defined');
3651 my $type = $opts{type};
3652 defined $type or $type = '8bit';
3654 my $width = defined $opts{width} ? $opts{width}
3655 : $self->getwidth() - $opts{x};
3658 if ($type eq '8bit') {
3659 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3660 $_[$data_index], $opts{offset}, $width);
3662 elsif ($type eq 'float') {
3663 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3664 $_[$data_index], $opts{offset}, $width);
3666 elsif ($type =~ /^([0-9]+)bit$/) {
3669 unless (ref $_[$data_index]) {
3670 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3674 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3675 $opts{channels}, $_[$data_index], $opts{offset},
3679 $self->_set_error('setsamples: type parameter invalid');
3683 unless (defined $count) {
3684 $self->_set_error(Imager->_error_as_msg);
3691 # make an identity matrix of the given size
3695 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3696 for my $c (0 .. ($size-1)) {
3697 $matrix->[$c][$c] = 1;
3702 # general function to convert an image
3704 my ($self, %opts) = @_;
3707 $self->_valid_image("convert")
3710 unless (defined wantarray) {
3711 my @caller = caller;
3712 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3716 # the user can either specify a matrix or preset
3717 # the matrix overrides the preset
3718 if (!exists($opts{matrix})) {
3719 unless (exists($opts{preset})) {
3720 $self->{ERRSTR} = "convert() needs a matrix or preset";
3724 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3725 # convert to greyscale, keeping the alpha channel if any
3726 if ($self->getchannels == 3) {
3727 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3729 elsif ($self->getchannels == 4) {
3730 # preserve the alpha channel
3731 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3736 $matrix = _identity($self->getchannels);
3739 elsif ($opts{preset} eq 'noalpha') {
3740 # strip the alpha channel
3741 if ($self->getchannels == 2 or $self->getchannels == 4) {
3742 $matrix = _identity($self->getchannels);
3743 pop(@$matrix); # lose the alpha entry
3746 $matrix = _identity($self->getchannels);
3749 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3751 $matrix = [ [ 1 ] ];
3753 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3754 $matrix = [ [ 0, 1 ] ];
3756 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3757 $matrix = [ [ 0, 0, 1 ] ];
3759 elsif ($opts{preset} eq 'alpha') {
3760 if ($self->getchannels == 2 or $self->getchannels == 4) {
3761 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3764 # the alpha is just 1 <shrug>
3765 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3768 elsif ($opts{preset} eq 'rgb') {
3769 if ($self->getchannels == 1) {
3770 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3772 elsif ($self->getchannels == 2) {
3773 # preserve the alpha channel
3774 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3777 $matrix = _identity($self->getchannels);
3780 elsif ($opts{preset} eq 'addalpha') {
3781 if ($self->getchannels == 1) {
3782 $matrix = _identity(2);
3784 elsif ($self->getchannels == 3) {
3785 $matrix = _identity(4);
3788 $matrix = _identity($self->getchannels);
3792 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3798 $matrix = $opts{matrix};
3801 my $new = Imager->new;
3802 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3803 unless ($new->{IMG}) {
3804 # most likely a bad matrix
3805 i_push_error(0, "convert");
3806 $self->{ERRSTR} = _error_as_msg();
3812 # combine channels from multiple input images, a class method
3814 my ($class, %opts) = @_;
3816 my $src = delete $opts{src};
3818 $class->_set_error("src parameter missing");
3823 for my $img (@$src) {
3824 unless (eval { $img->isa("Imager") }) {
3825 $class->_set_error("src must contain image objects");
3828 unless ($img->_valid_image("combine")) {
3829 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3832 push @imgs, $img->{IMG};
3835 if (my $channels = delete $opts{channels}) {
3836 $result = i_combine(\@imgs, $channels);
3839 $result = i_combine(\@imgs);
3842 $class->_set_error($class->_error_as_msg);
3846 my $img = $class->new;
3847 $img->{IMG} = $result;
3853 # general function to map an image through lookup tables
3856 my ($self, %opts) = @_;
3857 my @chlist = qw( red green blue alpha );
3859 $self->_valid_image("map")
3862 if (!exists($opts{'maps'})) {
3863 # make maps from channel maps
3865 for $chnum (0..$#chlist) {
3866 if (exists $opts{$chlist[$chnum]}) {
3867 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3868 } elsif (exists $opts{'all'}) {
3869 $opts{'maps'}[$chnum] = $opts{'all'};
3873 if ($opts{'maps'} and $self->{IMG}) {
3874 i_map($self->{IMG}, $opts{'maps'} );
3880 my ($self, %opts) = @_;
3882 $self->_valid_image("difference")
3885 defined $opts{mindist} or $opts{mindist} = 0;
3887 defined $opts{other}
3888 or return $self->_set_error("No 'other' parameter supplied");
3889 unless ($opts{other}->_valid_image("difference")) {
3890 $self->_set_error($opts{other}->errstr . " (other image)");
3894 my $result = Imager->new;
3895 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3897 or return $self->_set_error($self->_error_as_msg());
3902 # destructive border - image is shrunk by one pixel all around
3905 my ($self,%opts)=@_;
3906 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3907 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3911 # Get the width of an image
3916 $self->_valid_image("getwidth")
3919 return i_img_get_width($self->{IMG});
3922 # Get the height of an image
3927 $self->_valid_image("getheight")
3930 return i_img_get_height($self->{IMG});
3933 # Get number of channels in an image
3938 $self->_valid_image("getchannels")
3941 return i_img_getchannels($self->{IMG});
3944 my @model_names = qw(unknown gray graya rgb rgba);
3947 my ($self, %opts) = @_;
3949 $self->_valid_image("colormodel")
3952 my $model = i_img_color_model($self->{IMG});
3954 return $opts{numeric} ? $model : $model_names[$model];
3960 $self->_valid_image("colorchannels")
3963 return i_img_color_channels($self->{IMG});
3969 $self->_valid_image("alphachannel")
3972 return scalar(i_img_alpha_channel($self->{IMG}));
3980 $self->_valid_image("getmask")
3983 return i_img_getmask($self->{IMG});
3992 $self->_valid_image("setmask")
3995 unless (defined $opts{mask}) {
3996 $self->_set_error("mask parameter required");
4000 i_img_setmask( $self->{IMG} , $opts{mask} );
4005 # Get number of colors in an image
4009 my %opts=('maxcolors'=>2**30,@_);
4011 $self->_valid_image("getcolorcount")
4014 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
4015 return ($rc==-1? undef : $rc);
4018 # Returns a reference to a hash. The keys are colour named (packed) and the
4019 # values are the number of pixels in this colour.
4020 sub getcolorusagehash {
4023 $self->_valid_image("getcolorusagehash")
4026 my %opts = ( maxcolors => 2**30, @_ );
4027 my $max_colors = $opts{maxcolors};
4028 unless (defined $max_colors && $max_colors > 0) {
4029 $self->_set_error('maxcolors must be a positive integer');
4033 my $channels= $self->getchannels;
4034 # We don't want to look at the alpha channel, because some gifs using it
4035 # doesn't define it for every colour (but only for some)
4036 $channels -= 1 if $channels == 2 or $channels == 4;
4038 my $height = $self->getheight;
4039 for my $y (0 .. $height - 1) {
4040 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4041 while (length $colors) {
4042 $color_use{ substr($colors, 0, $channels, '') }++;
4044 keys %color_use > $max_colors
4050 # This will return a ordered array of the colour usage. Kind of the sorted
4051 # version of the values of the hash returned by getcolorusagehash.
4052 # You might want to add safety checks and change the names, etc...
4056 $self->_valid_image("getcolorusage")
4059 my %opts = ( maxcolors => 2**30, @_ );
4060 my $max_colors = $opts{maxcolors};
4061 unless (defined $max_colors && $max_colors > 0) {
4062 $self->_set_error('maxcolors must be a positive integer');
4066 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4069 # draw string to an image
4074 $self->_valid_image("string")
4077 my %input=('x'=>0, 'y'=>0, @_);
4078 defined($input{string}) or $input{string} = $input{text};
4080 unless(defined $input{string}) {
4081 $self->{ERRSTR}="missing required parameter 'string'";
4085 unless($input{font}) {
4086 $self->{ERRSTR}="missing required parameter 'font'";
4090 unless ($input{font}->draw(image=>$self, %input)) {
4102 $self->_valid_image("align_string")
4111 my %input=('x'=>0, 'y'=>0, @_);
4112 defined $input{string}
4113 or $input{string} = $input{text};
4115 unless(exists $input{string}) {
4116 $self->_set_error("missing required parameter 'string'");
4120 unless($input{font}) {
4121 $self->_set_error("missing required parameter 'font'");
4126 unless (@result = $input{font}->align(image=>$img, %input)) {
4130 return wantarray ? @result : $result[0];
4133 my @file_limit_names = qw/width height bytes/;
4135 sub set_file_limits {
4142 @values{@file_limit_names} = (0) x @file_limit_names;
4145 @values{@file_limit_names} = i_get_image_file_limits();
4148 for my $key (keys %values) {
4149 defined $opts{$key} and $values{$key} = $opts{$key};
4152 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4155 sub get_file_limits {
4156 i_get_image_file_limits();
4159 my @check_args = qw(width height channels sample_size);
4161 sub check_file_limits {
4171 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4172 $opts{sample_size} = length(pack("d", 0));
4175 for my $name (@check_args) {
4176 unless (defined $opts{$name}) {
4177 $class->_set_error("check_file_limits: $name must be defined");
4180 unless ($opts{$name} == int($opts{$name})) {
4181 $class->_set_error("check_file_limits: $name must be a positive integer");
4186 my $result = i_int_check_image_file_limits(@opts{@check_args});
4188 $class->_set_error($class->_error_as_msg());
4194 # Shortcuts that can be exported
4196 sub newcolor { Imager::Color->new(@_); }
4197 sub newfont { Imager::Font->new(@_); }
4199 require Imager::Color::Float;
4200 return Imager::Color::Float->new(@_);
4203 *NC=*newcolour=*newcolor;
4210 #### Utility routines
4213 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4217 my ($self, $msg) = @_;
4220 $self->{ERRSTR} = $msg;
4228 # Default guess for the type of an image from extension
4230 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps webp xwd xpm dng ras);
4234 ( map { $_ => $_ } @simple_types ),
4240 pnm => "pnm", # technically wrong, but historically it works in Imager
4253 sub def_guess_type {
4256 my ($ext) = $name =~ /\.([^.]+)$/
4259 my $type = $ext_types{$ext}
4265 sub add_type_extensions {
4266 my ($class, $type, @exts) = @_;
4268 for my $ext (@exts) {
4269 exists $ext_types{lc $ext} or $ext_types{lc $ext} = lc $type;
4275 return @combine_types;
4278 # get the minimum of a list
4282 for(@_) { if ($_<$mx) { $mx=$_; }}
4286 # get the maximum of a list
4290 for(@_) { if ($_>$mx) { $mx=$_; }}
4294 # string stuff for iptc headers
4298 $str = substr($str,3);
4299 $str =~ s/[\n\r]//g;
4306 # A little hack to parse iptc headers.
4311 my($caption,$photogr,$headln,$credit);
4313 my $str=$self->{IPTCRAW};
4318 @ar=split(/8BIM/,$str);
4323 @sar=split(/\034\002/);
4324 foreach $item (@sar) {
4325 if ($item =~ m/^x/) {
4326 $caption = _clean($item);
4329 if ($item =~ m/^P/) {
4330 $photogr = _clean($item);
4333 if ($item =~ m/^i/) {
4334 $headln = _clean($item);
4337 if ($item =~ m/^n/) {
4338 $credit = _clean($item);
4344 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4348 # Inline added a new argument at the beginning
4352 or die "Only C language supported";
4354 require Imager::ExtUtils;
4355 return Imager::ExtUtils->inline_config;
4358 # threads shouldn't try to close raw Imager objects
4359 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4362 # this serves two purposes:
4363 # - a class method to load the file support modules included with Imager
4364 # (or were included, once the library dependent modules are split out)
4365 # - something for Module::ScanDeps to analyze
4366 # https://rt.cpan.org/Ticket/Display.html?id=6566
4369 pop @INC if $INC[-1] eq '.';
4370 eval { require Imager::File::GIF };
4371 eval { require Imager::File::JPEG };
4372 eval { require Imager::File::PNG };
4373 eval { require Imager::File::SGI };
4374 eval { require Imager::File::TIFF };
4375 eval { require Imager::File::ICO };
4376 eval { require Imager::Font::W32 };
4377 eval { require Imager::Font::FT2 };
4378 eval { require Imager::Font::T1 };
4379 eval { require Imager::Color::Table };
4388 my ($class, $fh) = @_;
4391 return $class->new_cb
4396 return print $fh $_[0];
4400 my $count = CORE::read $fh, $tmp, $_[1];
4408 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4409 unless (CORE::seek $fh, $_[0], $_[1]) {
4420 return $class->_new_perlio($fh);
4424 # backward compatibility for %formats
4425 package Imager::FORMATS;
4427 use constant IX_FORMATS => 0;
4428 use constant IX_LIST => 1;
4429 use constant IX_INDEX => 2;
4430 use constant IX_CLASSES => 3;
4433 my ($class, $formats, $classes) = @_;
4435 return bless [ $formats, [ ], 0, $classes ], $class;
4439 my ($self, $key) = @_;
4441 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4444 my $loaded = Imager::_load_file($file, \$error);
4449 if ($error =~ /^Can't locate /) {
4450 $error = "Can't locate $file";
4452 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4455 $self->[IX_FORMATS]{$key} = $value;
4461 my ($self, $key) = @_;
4463 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4465 $self->[IX_CLASSES]{$key} or return undef;
4467 return $self->_check($key);
4471 die "%Imager::formats is not user monifiable";
4475 die "%Imager::formats is not user monifiable";
4479 die "%Imager::formats is not user monifiable";
4483 my ($self, $key) = @_;
4485 if (exists $self->[IX_FORMATS]{$key}) {
4486 my $value = $self->[IX_FORMATS]{$key}
4491 $self->_check($key) or return 1==0;
4499 unless (@{$self->[IX_LIST]}) {
4501 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4502 keys %{$self->[IX_FORMATS]};
4504 for my $key (keys %{$self->[IX_CLASSES]}) {
4505 $self->[IX_FORMATS]{$key} and next;
4507 and push @{$self->[IX_LIST]}, $key;
4511 @{$self->[IX_LIST]} or return;
4512 $self->[IX_INDEX] = 1;
4513 return $self->[IX_LIST][0];
4519 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4522 return $self->[IX_LIST][$self->[IX_INDEX]++];
4528 return scalar @{$self->[IX_LIST]};
4533 # Below is the stub of documentation for your module. You better edit it!
4537 Imager - Perl extension for Generating 24 bit Images
4547 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4552 # see Imager::Files for information on the read() method
4553 my $img = Imager->new(file=>$file)
4554 or die Imager->errstr();
4556 $file =~ s/\.[^.]*$//;
4558 # Create smaller version
4559 # documented in Imager::Transformations
4560 my $thumb = $img->scale(scalefactor=>.3);
4562 # Autostretch individual channels
4563 $thumb->filter(type=>'autolevels');
4565 # try to save in one of these formats
4568 for $format ( qw( png gif jpeg tiff ppm ) ) {
4569 # Check if given format is supported
4570 if ($Imager::formats{$format}) {
4571 $file.="_low.$format";
4572 print "Storing image as: $file\n";
4573 # documented in Imager::Files
4574 $thumb->write(file=>$file) or
4582 Imager is a module for creating and altering images. It can read and
4583 write various image formats, draw primitive shapes like lines,and
4584 polygons, blend multiple images together in various ways, scale, crop,
4585 render text and more.
4587 =head2 Overview of documentation
4593 Imager - This document - Synopsis, Example, Table of Contents and
4598 L<Imager::Install> - installation notes for Imager.
4602 L<Imager::Tutorial> - a brief introduction to Imager.
4606 L<Imager::Cookbook> - how to do various things with Imager.
4610 L<Imager::ImageTypes> - Basics of constructing image objects with
4611 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4612 8/16/double bits/channel, color maps, channel masks, image tags, color
4613 quantization. Also discusses basic image information methods.
4617 L<Imager::Files> - IO interaction, reading/writing images, format
4622 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4627 L<Imager::Color> - Color specification.
4631 L<Imager::Fill> - Fill pattern specification.
4635 L<Imager::Font> - General font rendering, bounding boxes and font
4640 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4641 blending, pasting, convert and map.
4645 L<Imager::Engines> - Programmable transformations through
4646 C<transform()>, C<transform2()> and C<matrix_transform()>.
4650 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4655 L<Imager::Expr> - Expressions for evaluation engine used by
4660 L<Imager::Matrix2d> - Helper class for affine transformations.
4664 L<Imager::Fountain> - Helper for making gradient profiles.
4668 L<Imager::IO> - Imager I/O abstraction.
4672 L<Imager::API> - using Imager's C API
4676 L<Imager::APIRef> - API function reference
4680 L<Imager::Inline> - using Imager's C API from Inline::C
4684 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4688 L<Imager::Security> - brief security notes.
4692 L<Imager::Threads> - brief information on working with threads.
4696 =head2 Basic Overview
4698 An Image object is created with C<$img = Imager-E<gt>new()>.
4701 $img=Imager->new(); # create empty image
4702 $img->read(file=>'lena.png',type=>'png') or # read image from file
4703 die $img->errstr(); # give an explanation
4704 # if something failed
4706 or if you want to create an empty image:
4708 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4710 This example creates a completely black image of width 400 and height
4713 =head1 ERROR HANDLING
4715 In general a method will return false when it fails, if it does use
4716 the C<errstr()> method to find out why:
4722 Returns the last error message in that context.
4724 If the last error you received was from calling an object method, such
4725 as read, call errstr() as an object method to find out why:
4727 my $image = Imager->new;
4728 $image->read(file => 'somefile.gif')
4729 or die $image->errstr;
4731 If it was a class method then call errstr() as a class method:
4733 my @imgs = Imager->read_multi(file => 'somefile.gif')
4734 or die Imager->errstr;
4736 Note that in some cases object methods are implemented in terms of
4737 class methods so a failing object method may set both.
4741 The C<Imager-E<gt>new> method is described in detail in
4742 L<Imager::ImageTypes>.
4746 Where to find information on methods for Imager class objects.
4748 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4751 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4753 add_type_extensions() -
4754 L<Imager::Files/add_type_extensions($type, $ext, ...)> - add extensions for
4755 new image file types.
4757 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4760 alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
4761 channel index of the alpha channel (if any).
4763 arc() - L<Imager::Draw/arc()> - draw a filled arc
4765 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4768 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4770 check_file_limits() - L<Imager::Files/check_file_limits()>
4772 circle() - L<Imager::Draw/circle()> - draw a filled circle
4774 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4777 colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
4778 of channels used for color.
4780 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4781 colors in an image's palette (paletted images only)
4783 colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
4786 combine() - L<Imager::Transformations/combine()> - combine channels
4787 from one or more images.
4789 combines() - L<Imager::Draw/combines()> - return a list of the
4790 different combine type keywords
4792 compose() - L<Imager::Transformations/compose()> - compose one image
4795 convert() - L<Imager::Transformations/convert()> - transform the color
4798 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4801 crop() - L<Imager::Transformations/crop()> - extract part of an image
4803 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4804 used to guess the output file format based on the output file name
4806 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4808 difference() - L<Imager::Filters/difference()> - produce a difference
4809 images from two input images.
4811 errstr() - L</errstr()> - the error from the last failed operation.
4813 filter() - L<Imager::Filters/filter()> - image filtering
4815 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4816 palette, if it has one
4818 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4821 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4824 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4825 samples per pixel for an image
4827 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4828 different colors used by an image (works for direct color images)
4830 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4831 palette, if it has one
4833 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4835 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4837 get_file_limits() - L<Imager::Files/get_file_limits()>
4839 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4842 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4844 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4847 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4848 row or partial row of pixels.
4850 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4851 row or partial row of pixels.
4853 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4856 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4859 init() - L<Imager::ImageTypes/init()>
4861 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4862 image write functions should write the image in their bilevel (blank
4863 and white, no gray levels) format
4865 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4868 line() - L<Imager::Draw/line()> - draw an interval
4870 load_plugin() - L<Imager::Filters/load_plugin()>
4872 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4875 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4876 color palette from one or more input images.
4878 map() - L<Imager::Transformations/map()> - remap color
4881 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4883 matrix_transform() - L<Imager::Engines/matrix_transform()>
4885 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4887 NC() - L<Imager::Handy/NC()>
4889 NCF() - L<Imager::Handy/NCF()>
4891 new() - L<Imager::ImageTypes/new()>
4893 newcolor() - L<Imager::Handy/newcolor()>
4895 newcolour() - L<Imager::Handy/newcolour()>
4897 newfont() - L<Imager::Handy/newfont()>
4899 NF() - L<Imager::Handy/NF()>
4901 open() - L<Imager::Files/read()> - an alias for read()
4903 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4907 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4910 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4913 polygon() - L<Imager::Draw/polygon()>
4915 polyline() - L<Imager::Draw/polyline()>
4917 polypolygon() - L<Imager::Draw/polypolygon()>
4919 preload() - L<Imager::Files/preload()>
4921 read() - L<Imager::Files/read()> - read a single image from an image file
4923 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4926 read_types() - L<Imager::Files/read_types()> - list image types Imager
4929 register_filter() - L<Imager::Filters/register_filter()>
4931 register_reader() - L<Imager::Files/register_reader()>
4933 register_writer() - L<Imager::Files/register_writer()>
4935 rotate() - L<Imager::Transformations/rotate()>
4937 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4938 onto an image and use the alpha channel
4940 scale() - L<Imager::Transformations/scale()>
4942 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4944 scaleX() - L<Imager::Transformations/scaleX()>
4946 scaleY() - L<Imager::Transformations/scaleY()>
4948 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4951 set_file_limits() - L<Imager::Files/set_file_limits()>
4953 setmask() - L<Imager::ImageTypes/setmask()>
4955 setpixel() - L<Imager::Draw/setpixel()>
4957 setsamples() - L<Imager::Draw/setsamples()>
4959 setscanline() - L<Imager::Draw/setscanline()>
4961 settag() - L<Imager::ImageTypes/settag()>
4963 string() - L<Imager::Draw/string()> - draw text on an image
4965 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4967 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4969 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4971 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4973 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4974 double per sample image.
4976 transform() - L<Imager::Engines/"transform()">
4978 transform2() - L<Imager::Engines/"transform2()">
4980 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4982 unload_plugin() - L<Imager::Filters/unload_plugin()>
4984 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4987 write() - L<Imager::Files/write()> - write an image to a file
4989 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4992 write_types() - L<Imager::Files/read_types()> - list image types Imager
4995 =head1 CONCEPT INDEX
4997 animated GIF - L<Imager::Files/"Writing an animated GIF">
4999 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
5000 L<Imager::ImageTypes/"Common Tags">.
5002 blend - alpha blending one image onto another
5003 L<Imager::Transformations/rubthrough()>
5005 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
5007 boxes, drawing - L<Imager::Draw/box()>
5009 changes between image - L<Imager::Filters/"Image Difference">
5011 channels, combine into one image - L<Imager::Transformations/combine()>
5013 color - L<Imager::Color>
5015 color names - L<Imager::Color>, L<Imager::Color::Table>
5017 combine modes - L<Imager::Draw/"Combine Types">
5019 compare images - L<Imager::Filters/"Image Difference">
5021 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
5023 convolution - L<Imager::Filters/conv>
5025 cropping - L<Imager::Transformations/crop()>
5027 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5029 C<diff> images - L<Imager::Filters/"Image Difference">
5031 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
5032 L<Imager::Cookbook/"Image spatial resolution">
5034 drawing boxes - L<Imager::Draw/box()>
5036 drawing lines - L<Imager::Draw/line()>
5038 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
5040 error message - L</"ERROR HANDLING">
5042 files, font - L<Imager::Font>
5044 files, image - L<Imager::Files>
5046 filling, types of fill - L<Imager::Fill>
5048 filling, boxes - L<Imager::Draw/box()>
5050 filling, flood fill - L<Imager::Draw/flood_fill()>
5052 flood fill - L<Imager::Draw/flood_fill()>
5054 fonts - L<Imager::Font>
5056 fonts, drawing with - L<Imager::Draw/string()>,
5057 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
5059 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5061 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
5063 fountain fill - L<Imager::Fill/"Fountain fills">,
5064 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5065 L<Imager::Filters/gradgen>
5067 GIF files - L<Imager::Files/"GIF">
5069 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
5071 gradient fill - L<Imager::Fill/"Fountain fills">,
5072 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5073 L<Imager::Filters/gradgen>
5075 gray scale, convert image to - L<Imager::Transformations/convert()>
5077 gaussian blur - L<Imager::Filters/gaussian>
5079 hatch fills - L<Imager::Fill/"Hatched fills">
5081 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5083 invert image - L<Imager::Filters/hardinvert>,
5084 L<Imager::Filters/hardinvertall>
5086 JPEG - L<Imager::Files/"JPEG">
5088 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
5090 lines, drawing - L<Imager::Draw/line()>
5092 matrix - L<Imager::Matrix2d>,
5093 L<Imager::Engines/"Matrix Transformations">,
5094 L<Imager::Font/transform()>
5096 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5098 mosaic - L<Imager::Filters/mosaic>
5100 noise, filter - L<Imager::Filters/noise>
5102 noise, rendered - L<Imager::Filters/turbnoise>,
5103 L<Imager::Filters/radnoise>
5105 paste - L<Imager::Transformations/paste()>,
5106 L<Imager::Transformations/rubthrough()>
5108 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5109 L<Imager::ImageTypes/new()>
5111 =for stopwords posterize
5113 posterize - L<Imager::Filters/postlevels>
5115 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5117 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5119 rectangles, drawing - L<Imager::Draw/box()>
5121 resizing an image - L<Imager::Transformations/scale()>,
5122 L<Imager::Transformations/crop()>
5124 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5126 saving an image - L<Imager::Files>
5128 scaling - L<Imager::Transformations/scale()>
5130 security - L<Imager::Security>
5132 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5134 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
5136 size, image - L<Imager::ImageTypes/getwidth()>,
5137 L<Imager::ImageTypes/getheight()>
5139 size, text - L<Imager::Font/bounding_box()>
5141 tags, image metadata - L<Imager::ImageTypes/"Tags">
5143 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5144 L<Imager::Font::Wrap>
5146 text, wrapping text in an area - L<Imager::Font::Wrap>
5148 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5150 threads - L<Imager::Threads>
5152 tiles, color - L<Imager::Filters/mosaic>
5154 transparent images - L<Imager::ImageTypes>,
5155 L<Imager::Cookbook/"Transparent PNG">
5157 =for stopwords unsharp
5159 unsharp mask - L<Imager::Filters/unsharpmask>
5161 watermark - L<Imager::Filters/watermark>
5163 writing an image to a file - L<Imager::Files>
5167 The best place to get help with Imager is the mailing list.
5169 To subscribe send a message with C<subscribe> in the body to:
5171 imager-devel+request@molar.is
5177 L<http://www.molar.is/en/lists/imager-devel/>
5181 where you can also find the mailing list archive.
5183 You can report bugs by pointing your browser at:
5187 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5191 or by sending an email to:
5195 bug-Imager@rt.cpan.org
5199 Please remember to include the versions of Imager, perl, supporting
5200 libraries, and any relevant code. If you have specific images that
5201 cause the problems, please include those too.
5203 If you don't want to publish your email address on a mailing list you
5204 can use CPAN::Forum:
5206 http://www.cpanforum.com/dist/Imager
5208 You will need to register to post.
5210 =head1 CONTRIBUTING TO IMAGER
5216 If you like or dislike Imager, you can add a public review of Imager
5219 http://cpanratings.perl.org/dist/Imager
5221 =for stopwords Bitcard
5223 This requires a Bitcard account (http://www.bitcard.org).
5225 You can also send email to the maintainer below.
5227 If you send me a bug report via email, it will be copied to Request
5232 I accept patches, preferably against the master branch in git. Please
5233 include an explanation of the reason for why the patch is needed or
5236 Your patch should include regression tests where possible, otherwise
5237 it will be delayed until I get a chance to write them.
5239 To browse Imager's git repository:
5241 http://git.imager.perl.org/imager.git
5245 git clone git://git.imager.perl.org/imager.git
5247 My preference is that patches are provided in the format produced by
5248 C<git format-patch>, for example, if you made your changes in a branch
5249 from master you might do:
5251 git format-patch -k --stdout master >my-patch.txt
5253 and then attach that to your bug report, either by adding it as an
5254 attachment in your email client, or by using the Request Tracker
5255 attachment mechanism.
5259 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5261 Arnar M. Hrafnkelsson is the original author of Imager.
5263 Many others have contributed to Imager, please see the C<README> for a
5268 Imager is licensed under the same terms as perl itself.
5271 makeblendedfont Fontforge
5273 A test font, generated by the Debian packaged Fontforge,
5274 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5275 copyrighted by Adobe. See F<adobe.txt> in the source for license
5280 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5281 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5282 L<Imager::Font>(3), L<Imager::Transformations>(3),
5283 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5284 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5286 L<http://imager.perl.org/>
5288 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5290 Other perl imaging modules include:
5292 L<GD>(3), L<Image::Magick>(3),
5293 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5294 L<Prima::Image>, L<IPA>.
5296 For manipulating image metadata see L<Image::ExifTool>.