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) = @_;
640 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
642 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
643 $msg = "$method: $msg" if $method;
644 $self->_set_error($msg);
649 # returns first defined parameter
652 return $_ if defined $_;
658 # Methods to be called on objects.
661 # Create a new Imager object takes very few parameters.
662 # usually you call this method and then call open from
663 # the resulting object
670 $self->{IMG}=undef; # Just to indicate what exists
671 $self->{ERRSTR}=undef; #
672 $self->{DEBUG}=$DEBUG;
673 $self->{DEBUG} and print "Initialized Imager\n";
674 if (defined $hsh{xsize} || defined $hsh{ysize}) {
675 unless ($self->img_set(%hsh)) {
676 $Imager::ERRSTR = $self->{ERRSTR};
680 elsif (defined $hsh{file} ||
683 defined $hsh{callback} ||
684 defined $hsh{readcb} ||
685 defined $hsh{data}) {
686 # allow $img = Imager->new(file => $filename)
689 # type is already used as a parameter to new(), rename it for the
691 if ($hsh{filetype}) {
692 $extras{type} = $hsh{filetype};
694 unless ($self->read(%hsh, %extras)) {
695 $Imager::ERRSTR = $self->{ERRSTR};
703 # Copy an entire image with no changes
704 # - if an image has magic the copy of it will not be magical
709 $self->_valid_image("copy")
712 unless (defined wantarray) {
714 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
718 my $newcopy=Imager->new();
719 $newcopy->{IMG} = i_copy($self->{IMG});
728 $self->_valid_image("paste")
731 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
732 my $src = $input{img} || $input{src};
734 $self->_set_error("no source image");
737 unless ($src->_valid_image("paste")) {
738 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
741 $input{left}=0 if $input{left} <= 0;
742 $input{top}=0 if $input{top} <= 0;
744 my($r,$b)=i_img_info($src->{IMG});
745 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
746 my ($src_right, $src_bottom);
747 if ($input{src_coords}) {
748 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
751 if (defined $input{src_maxx}) {
752 $src_right = $input{src_maxx};
754 elsif (defined $input{width}) {
755 if ($input{width} <= 0) {
756 $self->_set_error("paste: width must me positive");
759 $src_right = $src_left + $input{width};
764 if (defined $input{src_maxy}) {
765 $src_bottom = $input{src_maxy};
767 elsif (defined $input{height}) {
768 if ($input{height} < 0) {
769 $self->_set_error("paste: height must be positive");
772 $src_bottom = $src_top + $input{height};
779 $src_right > $r and $src_right = $r;
780 $src_bottom > $b and $src_bottom = $b;
782 if ($src_right <= $src_left
783 || $src_bottom < $src_top) {
784 $self->_set_error("nothing to paste");
788 i_copyto($self->{IMG}, $src->{IMG},
789 $src_left, $src_top, $src_right, $src_bottom,
790 $input{left}, $input{top});
792 return $self; # What should go here??
795 # Crop an image - i.e. return a new image that is smaller
800 $self->_valid_image("crop")
803 unless (defined wantarray) {
805 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
811 my ($w, $h, $l, $r, $b, $t) =
812 @hsh{qw(width height left right bottom top)};
814 # work through the various possibilities
819 elsif (!defined $r) {
820 $r = $self->getwidth;
832 $l = int(0.5+($self->getwidth()-$w)/2);
837 $r = $self->getwidth;
843 elsif (!defined $b) {
844 $b = $self->getheight;
856 $t=int(0.5+($self->getheight()-$h)/2);
861 $b = $self->getheight;
864 ($l,$r)=($r,$l) if $l>$r;
865 ($t,$b)=($b,$t) if $t>$b;
868 $r > $self->getwidth and $r = $self->getwidth;
870 $b > $self->getheight and $b = $self->getheight;
872 if ($l == $r || $t == $b) {
873 $self->_set_error("resulting image would have no content");
876 if( $r < $l or $b < $t ) {
877 $self->_set_error("attempting to crop outside of the image");
880 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
882 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
887 my ($self, %opts) = @_;
892 my $x = $opts{xsize} || $self->getwidth;
893 my $y = $opts{ysize} || $self->getheight;
894 my $channels = $opts{channels} || $self->getchannels;
896 my $out = Imager->new;
897 if ($channels == $self->getchannels) {
898 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
901 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
903 unless ($out->{IMG}) {
904 $self->{ERRSTR} = $self->_error_as_msg;
911 # Sets an image to a certain size and channel number
912 # if there was previously data in the image it is discarded
917 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
919 if (defined($self->{IMG})) {
920 # let IIM_DESTROY destroy it, it's possible this image is
921 # referenced from a virtual image (like masked)
922 #i_img_destroy($self->{IMG});
926 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
927 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
928 $hsh{maxcolors} || 256);
930 elsif ($hsh{bits} eq 'double') {
931 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
933 elsif ($hsh{bits} == 16) {
934 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
937 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
941 unless ($self->{IMG}) {
942 $self->{ERRSTR} = Imager->_error_as_msg();
949 # created a masked version of the current image
953 $self->_valid_image("masked")
956 my %opts = (left => 0,
958 right => $self->getwidth,
959 bottom => $self->getheight,
961 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
963 my $result = Imager->new;
964 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
965 $opts{top}, $opts{right} - $opts{left},
966 $opts{bottom} - $opts{top});
967 unless ($result->{IMG}) {
968 $self->_set_error(Imager->_error_as_msg);
972 # keep references to the mask and base images so they don't
974 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
979 # convert an RGB image into a paletted image
983 if (@_ != 1 && !ref $_[0]) {
990 unless (defined wantarray) {
992 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
996 $self->_valid_image("to_paletted")
999 my $result = Imager->new;
1000 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1001 $self->_set_error(Imager->_error_as_msg);
1009 my ($class, $quant, @images) = @_;
1012 Imager->_set_error("make_palette: supply at least one image");
1016 for my $img (@images) {
1017 unless ($img->{IMG}) {
1018 Imager->_set_error("make_palette: image $index is empty");
1024 return i_img_make_palette($quant, map $_->{IMG}, @images);
1027 # convert a paletted (or any image) to an 8-bit/channel RGB image
1031 unless (defined wantarray) {
1032 my @caller = caller;
1033 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1037 $self->_valid_image("to_rgb8")
1040 my $result = Imager->new;
1041 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1042 $self->_set_error(Imager->_error_as_msg());
1049 # convert a paletted (or any image) to a 16-bit/channel RGB image
1053 unless (defined wantarray) {
1054 my @caller = caller;
1055 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1059 $self->_valid_image("to_rgb16")
1062 my $result = Imager->new;
1063 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1064 $self->_set_error(Imager->_error_as_msg());
1071 # convert a paletted (or any image) to an double/channel RGB image
1075 unless (defined wantarray) {
1076 my @caller = caller;
1077 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1081 $self->_valid_image("to_rgb_double")
1084 my $result = Imager->new;
1085 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1086 $self->_set_error(Imager->_error_as_msg());
1095 my %opts = (colors=>[], @_);
1097 $self->_valid_image("addcolors")
1100 my @colors = @{$opts{colors}}
1103 for my $color (@colors) {
1104 $color = _color($color);
1106 $self->_set_error($Imager::ERRSTR);
1111 return i_addcolors($self->{IMG}, @colors);
1116 my %opts = (start=>0, colors=>[], @_);
1118 $self->_valid_image("setcolors")
1121 my @colors = @{$opts{colors}}
1124 for my $color (@colors) {
1125 $color = _color($color);
1127 $self->_set_error($Imager::ERRSTR);
1132 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1139 $self->_valid_image("getcolors")
1142 if (!exists $opts{start} && !exists $opts{count}) {
1145 $opts{count} = $self->colorcount;
1147 elsif (!exists $opts{count}) {
1150 elsif (!exists $opts{start}) {
1154 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1160 $self->_valid_image("colorcount")
1163 return i_colorcount($self->{IMG});
1169 $self->_valid_image("maxcolors")
1172 i_maxcolors($self->{IMG});
1179 $self->_valid_image("findcolor")
1182 unless ($opts{color}) {
1183 $self->_set_error("findcolor: no color parameter");
1187 my $color = _color($opts{color})
1190 return i_findcolor($self->{IMG}, $color);
1196 $self->_valid_image("bits")
1199 my $bits = i_img_bits($self->{IMG});
1200 if ($bits && $bits == length(pack("d", 1)) * 8) {
1209 $self->_valid_image("type")
1212 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1218 $self->_valid_image("virtual")
1221 return i_img_virtual($self->{IMG});
1227 $self->_valid_image("is_bilevel")
1230 return i_img_is_monochrome($self->{IMG});
1234 my ($self, %opts) = @_;
1236 $self->_valid_image("tags")
1239 if (defined $opts{name}) {
1243 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1244 push @result, (i_tags_get($self->{IMG}, $found))[1];
1247 return wantarray ? @result : $result[0];
1249 elsif (defined $opts{code}) {
1253 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1254 push @result, (i_tags_get($self->{IMG}, $found))[1];
1261 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1264 return i_tags_count($self->{IMG});
1273 $self->_valid_image("addtag")
1277 if (defined $opts{value}) {
1278 if ($opts{value} =~ /^\d+$/) {
1280 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1283 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1286 elsif (defined $opts{data}) {
1287 # force addition as a string
1288 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1291 $self->{ERRSTR} = "No value supplied";
1295 elsif ($opts{code}) {
1296 if (defined $opts{value}) {
1297 if ($opts{value} =~ /^\d+$/) {
1299 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1302 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1305 elsif (defined $opts{data}) {
1306 # force addition as a string
1307 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1310 $self->{ERRSTR} = "No value supplied";
1323 $self->_valid_image("deltag")
1326 if (defined $opts{'index'}) {
1327 return i_tags_delete($self->{IMG}, $opts{'index'});
1329 elsif (defined $opts{name}) {
1330 return i_tags_delbyname($self->{IMG}, $opts{name});
1332 elsif (defined $opts{code}) {
1333 return i_tags_delbycode($self->{IMG}, $opts{code});
1336 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1342 my ($self, %opts) = @_;
1344 $self->_valid_image("settag")
1348 $self->deltag(name=>$opts{name});
1349 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1351 elsif (defined $opts{code}) {
1352 $self->deltag(code=>$opts{code});
1353 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1361 sub _get_reader_io {
1362 my ($self, $input) = @_;
1365 return $input->{io}, undef;
1367 elsif ($input->{fd}) {
1368 return io_new_fd($input->{fd});
1370 elsif ($input->{fh}) {
1371 unless (Scalar::Util::openhandle($input->{fh})) {
1372 $self->_set_error("Handle in fh option not opened");
1375 return Imager::IO->new_fh($input->{fh});
1377 elsif ($input->{file}) {
1378 my $file = IO::File->new($input->{file}, "r");
1380 $self->_set_error("Could not open $input->{file}: $!");
1384 return (io_new_fd(fileno($file)), $file);
1386 elsif ($input->{data}) {
1387 return io_new_buffer($input->{data});
1389 elsif ($input->{callback} || $input->{readcb}) {
1390 if (!$input->{seekcb}) {
1391 $self->_set_error("Need a seekcb parameter");
1393 if ($input->{maxbuffer}) {
1394 return io_new_cb($input->{writecb},
1395 $input->{callback} || $input->{readcb},
1396 $input->{seekcb}, $input->{closecb},
1397 $input->{maxbuffer});
1400 return io_new_cb($input->{writecb},
1401 $input->{callback} || $input->{readcb},
1402 $input->{seekcb}, $input->{closecb});
1406 $self->_set_error("file/fd/fh/data/callback parameter missing");
1411 sub _get_writer_io {
1412 my ($self, $input) = @_;
1414 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1421 elsif ($input->{fd}) {
1422 $io = io_new_fd($input->{fd});
1424 elsif ($input->{fh}) {
1425 unless (Scalar::Util::openhandle($input->{fh})) {
1426 $self->_set_error("Handle in fh option not opened");
1429 $io = Imager::IO->new_fh($input->{fh});
1431 elsif ($input->{file}) {
1432 my $fh = new IO::File($input->{file},"w+");
1434 $self->_set_error("Could not open file $input->{file}: $!");
1437 binmode($fh) or die;
1438 $io = io_new_fd(fileno($fh));
1441 elsif ($input->{data}) {
1442 $io = io_new_bufchain();
1444 elsif ($input->{callback} || $input->{writecb}) {
1445 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1448 $io = io_new_cb($input->{callback} || $input->{writecb},
1450 $input->{seekcb}, $input->{closecb});
1453 $self->_set_error("file/fd/fh/data/callback parameter missing");
1457 unless ($buffered) {
1458 $io->set_buffered(0);
1461 return ($io, @extras);
1464 # Read an image from file
1470 if (defined($self->{IMG})) {
1471 # let IIM_DESTROY do the destruction, since the image may be
1472 # referenced from elsewhere
1473 #i_img_destroy($self->{IMG});
1474 undef($self->{IMG});
1477 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1479 my $type = $input{'type'};
1481 $type = i_test_format_probe($IO, -1);
1484 if ($input{file} && !$type) {
1486 $type = $FORMATGUESS->($input{file});
1490 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1491 $input{file} and $msg .= " or file name";
1492 $self->_set_error($msg);
1496 _reader_autoload($type);
1498 if ($readers{$type} && $readers{$type}{single}) {
1499 return $readers{$type}{single}->($self, $IO, %input);
1502 unless ($formats_low{$type}) {
1503 my $read_types = join ', ', sort Imager->read_types();
1504 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1508 my $allow_incomplete = $input{allow_incomplete};
1509 defined $allow_incomplete or $allow_incomplete = 0;
1511 if ( $type eq 'pnm' ) {
1512 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1513 if ( !defined($self->{IMG}) ) {
1514 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1517 $self->{DEBUG} && print "loading a pnm file\n";
1521 if ( $type eq 'bmp' ) {
1522 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1523 if ( !defined($self->{IMG}) ) {
1524 $self->{ERRSTR}=$self->_error_as_msg();
1527 $self->{DEBUG} && print "loading a bmp file\n";
1530 if ( $type eq 'tga' ) {
1531 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1532 if ( !defined($self->{IMG}) ) {
1533 $self->{ERRSTR}=$self->_error_as_msg();
1536 $self->{DEBUG} && print "loading a tga file\n";
1539 if ( $type eq 'raw' ) {
1540 unless ( $input{xsize} && $input{ysize} ) {
1541 $self->_set_error('missing xsize or ysize parameter for raw');
1545 my $interleave = _first($input{raw_interleave}, $input{interleave});
1546 unless (defined $interleave) {
1547 my @caller = caller;
1548 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1551 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1552 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1554 $self->{IMG} = i_readraw_wiol( $IO,
1560 if ( !defined($self->{IMG}) ) {
1561 $self->{ERRSTR}=$self->_error_as_msg();
1564 $self->{DEBUG} && print "loading a raw file\n";
1570 sub register_reader {
1571 my ($class, %opts) = @_;
1574 or die "register_reader called with no type parameter\n";
1576 my $type = $opts{type};
1578 defined $opts{single} || defined $opts{multiple}
1579 or die "register_reader called with no single or multiple parameter\n";
1581 $readers{$type} = { };
1582 if ($opts{single}) {
1583 $readers{$type}{single} = $opts{single};
1585 if ($opts{multiple}) {
1586 $readers{$type}{multiple} = $opts{multiple};
1592 sub register_writer {
1593 my ($class, %opts) = @_;
1596 or die "register_writer called with no type parameter\n";
1598 my $type = $opts{type};
1600 defined $opts{single} || defined $opts{multiple}
1601 or die "register_writer called with no single or multiple parameter\n";
1603 $writers{$type} = { };
1604 if ($opts{single}) {
1605 $writers{$type}{single} = $opts{single};
1607 if ($opts{multiple}) {
1608 $writers{$type}{multiple} = $opts{multiple};
1619 grep($file_formats{$_}, keys %formats),
1620 qw(ico sgi), # formats not handled directly, but supplied with Imager
1631 grep($file_formats{$_}, keys %formats),
1632 qw(ico sgi), # formats not handled directly, but supplied with Imager
1639 my ($file, $error) = @_;
1641 if ($attempted_to_load{$file}) {
1642 if ($file_load_errors{$file}) {
1643 $$error = $file_load_errors{$file};
1651 local $SIG{__DIE__};
1653 ++$attempted_to_load{$file};
1661 my $work = $@ || "Unknown error";
1663 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1664 $work =~ s/\n/\\n/g;
1665 $work =~ s/\s*\.?\z/ loading $file/;
1666 $file_load_errors{$file} = $work;
1673 # probes for an Imager::File::whatever module
1674 sub _reader_autoload {
1677 return if $formats_low{$type} || $readers{$type};
1679 return unless $type =~ /^\w+$/;
1681 my $file = "Imager/File/\U$type\E.pm";
1684 my $loaded = _load_file($file, \$error);
1685 if (!$loaded && $error =~ /^Can't locate /) {
1686 my $filer = "Imager/File/\U$type\EReader.pm";
1687 $loaded = _load_file($filer, \$error);
1688 if ($error =~ /^Can't locate /) {
1689 $error = "Can't locate $file or $filer";
1693 $reader_load_errors{$type} = $error;
1697 # probes for an Imager::File::whatever module
1698 sub _writer_autoload {
1701 return if $formats_low{$type} || $writers{$type};
1703 return unless $type =~ /^\w+$/;
1705 my $file = "Imager/File/\U$type\E.pm";
1708 my $loaded = _load_file($file, \$error);
1709 if (!$loaded && $error =~ /^Can't locate /) {
1710 my $filew = "Imager/File/\U$type\EWriter.pm";
1711 $loaded = _load_file($filew, \$error);
1712 if ($error =~ /^Can't locate /) {
1713 $error = "Can't locate $file or $filew";
1717 $writer_load_errors{$type} = $error;
1721 sub _fix_gif_positions {
1722 my ($opts, $opt, $msg, @imgs) = @_;
1724 my $positions = $opts->{'gif_positions'};
1726 for my $pos (@$positions) {
1727 my ($x, $y) = @$pos;
1728 my $img = $imgs[$index++];
1729 $img->settag(name=>'gif_left', value=>$x);
1730 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1732 $$msg .= "replaced with the gif_left and gif_top tags";
1737 gif_each_palette=>'gif_local_map',
1738 interlace => 'gif_interlace',
1739 gif_delays => 'gif_delay',
1740 gif_positions => \&_fix_gif_positions,
1741 gif_loop_count => 'gif_loop',
1744 # options that should be converted to colors
1745 my %color_opts = map { $_ => 1 } qw/i_background/;
1748 my ($self, $opts, $prefix, @imgs) = @_;
1750 for my $opt (keys %$opts) {
1752 if ($obsolete_opts{$opt}) {
1753 my $new = $obsolete_opts{$opt};
1754 my $msg = "Obsolete option $opt ";
1756 $new->($opts, $opt, \$msg, @imgs);
1759 $msg .= "replaced with the $new tag ";
1762 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1763 warn $msg if $warn_obsolete && $^W;
1765 next unless $tagname =~ /^\Q$prefix/;
1766 my $value = $opts->{$opt};
1767 if ($color_opts{$opt}) {
1768 $value = _color($value);
1770 $self->_set_error($Imager::ERRSTR);
1775 if (UNIVERSAL::isa($value, "Imager::Color")) {
1776 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1777 for my $img (@imgs) {
1778 $img->settag(name=>$tagname, value=>$tag);
1781 elsif (ref($value) eq 'ARRAY') {
1782 for my $i (0..$#$value) {
1783 my $val = $value->[$i];
1785 if (UNIVERSAL::isa($val, "Imager::Color")) {
1786 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1788 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1791 $self->_set_error("Unknown reference type " . ref($value) .
1792 " supplied in array for $opt");
1798 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1803 $self->_set_error("Unknown reference type " . ref($value) .
1804 " supplied for $opt");
1809 # set it as a tag for every image
1810 for my $img (@imgs) {
1811 $img->settag(name=>$tagname, value=>$value);
1819 # Write an image to file
1822 my %input=(jpegquality=>75,
1832 $self->_valid_image("write")
1835 $self->_set_opts(\%input, "i_", $self)
1838 my $type = $input{'type'};
1839 if (!$type and $input{file}) {
1840 $type = $FORMATGUESS->($input{file});
1843 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1847 _writer_autoload($type);
1850 if ($writers{$type} && $writers{$type}{single}) {
1851 ($IO, $fh) = $self->_get_writer_io(\%input)
1854 $writers{$type}{single}->($self, $IO, %input, type => $type)
1858 if (!$formats_low{$type}) {
1859 my $write_types = join ', ', sort Imager->write_types();
1860 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1864 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1867 if ( $type eq 'pnm' ) {
1868 $self->_set_opts(\%input, "pnm_", $self)
1870 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1871 $self->{ERRSTR} = $self->_error_as_msg();
1874 $self->{DEBUG} && print "writing a pnm file\n";
1876 elsif ( $type eq 'raw' ) {
1877 $self->_set_opts(\%input, "raw_", $self)
1879 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1880 $self->{ERRSTR} = $self->_error_as_msg();
1883 $self->{DEBUG} && print "writing a raw file\n";
1885 elsif ( $type eq 'bmp' ) {
1886 $self->_set_opts(\%input, "bmp_", $self)
1888 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1889 $self->{ERRSTR} = $self->_error_as_msg;
1892 $self->{DEBUG} && print "writing a bmp file\n";
1894 elsif ( $type eq 'tga' ) {
1895 $self->_set_opts(\%input, "tga_", $self)
1898 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1899 $self->{ERRSTR}=$self->_error_as_msg();
1902 $self->{DEBUG} && print "writing a tga file\n";
1906 if (exists $input{'data'}) {
1907 my $data = io_slurp($IO);
1909 $self->{ERRSTR}='Could not slurp from buffer';
1912 ${$input{data}} = $data;
1918 my ($class, $opts, @images) = @_;
1920 my $type = $opts->{type};
1922 if (!$type && $opts->{'file'}) {
1923 $type = $FORMATGUESS->($opts->{'file'});
1926 $class->_set_error('type parameter missing and not possible to guess from extension');
1929 # translate to ImgRaw
1931 for my $img (@images) {
1932 unless ($img->_valid_image("write_multi")) {
1933 $class->_set_error($img->errstr . " (image $index)");
1938 $class->_set_opts($opts, "i_", @images)
1940 my @work = map $_->{IMG}, @images;
1942 _writer_autoload($type);
1945 if ($writers{$type} && $writers{$type}{multiple}) {
1946 ($IO, $file) = $class->_get_writer_io($opts, $type)
1949 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1953 if (!$formats{$type}) {
1954 my $write_types = join ', ', sort Imager->write_types();
1955 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1959 ($IO, $file) = $class->_get_writer_io($opts, $type)
1962 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1966 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1971 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1977 if (exists $opts->{'data'}) {
1978 my $data = io_slurp($IO);
1980 Imager->_set_error('Could not slurp from buffer');
1983 ${$opts->{data}} = $data;
1988 # read multiple images from a file
1990 my ($class, %opts) = @_;
1992 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1995 my $type = $opts{'type'};
1997 $type = i_test_format_probe($IO, -1);
2000 if ($opts{file} && !$type) {
2002 $type = $FORMATGUESS->($opts{file});
2006 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2007 $opts{file} and $msg .= " or file name";
2008 Imager->_set_error($msg);
2012 _reader_autoload($type);
2014 if ($readers{$type} && $readers{$type}{multiple}) {
2015 return $readers{$type}{multiple}->($IO, %opts);
2018 unless ($formats{$type}) {
2019 my $read_types = join ', ', sort Imager->read_types();
2020 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2025 if ($type eq 'pnm') {
2026 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2029 my $img = Imager->new;
2030 if ($img->read(%opts, io => $IO, type => $type)) {
2033 Imager->_set_error($img->errstr);
2038 $ERRSTR = _error_as_msg();
2042 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2046 # Destroy an Imager object
2050 # delete $instances{$self};
2051 if (defined($self->{IMG})) {
2052 # the following is now handled by the XS DESTROY method for
2053 # Imager::ImgRaw object
2054 # Re-enabling this will break virtual images
2055 # tested for in t/t020masked.t
2056 # i_img_destroy($self->{IMG});
2057 undef($self->{IMG});
2059 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2063 # Perform an inplace filter of an image
2064 # that is the image will be overwritten with the data
2071 $self->_valid_image("filter")
2074 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2076 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2077 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2080 if ($filters{$input{'type'}}{names}) {
2081 my $names = $filters{$input{'type'}}{names};
2082 for my $name (keys %$names) {
2083 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2084 $input{$name} = $names->{$name}{$input{$name}};
2088 if (defined($filters{$input{'type'}}{defaults})) {
2089 %hsh=( image => $self->{IMG},
2091 %{$filters{$input{'type'}}{defaults}},
2094 %hsh=( image => $self->{IMG},
2099 my @cs=@{$filters{$input{'type'}}{callseq}};
2102 if (!defined($hsh{$_})) {
2103 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2108 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2109 &{$filters{$input{'type'}}{callsub}}(%hsh);
2112 chomp($self->{ERRSTR} = $@);
2118 $self->{DEBUG} && print "callseq is: @cs\n";
2119 $self->{DEBUG} && print "matching callseq is: @b\n";
2124 sub register_filter {
2126 my %hsh = ( defaults => {}, @_ );
2129 or die "register_filter() with no type\n";
2130 defined $hsh{callsub}
2131 or die "register_filter() with no callsub\n";
2132 defined $hsh{callseq}
2133 or die "register_filter() with no callseq\n";
2135 exists $filters{$hsh{type}}
2138 $filters{$hsh{type}} = \%hsh;
2143 sub scale_calculate {
2146 my %opts = ('type'=>'max', @_);
2148 # none of these should be references
2149 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2150 if (defined $opts{$name} && ref $opts{$name}) {
2151 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2156 my ($x_scale, $y_scale);
2157 my $width = $opts{width};
2158 my $height = $opts{height};
2160 defined $width or $width = $self->getwidth;
2161 defined $height or $height = $self->getheight;
2164 unless (defined $width && defined $height) {
2165 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2170 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2171 $x_scale = $opts{'xscalefactor'};
2172 $y_scale = $opts{'yscalefactor'};
2174 elsif ($opts{'xscalefactor'}) {
2175 $x_scale = $opts{'xscalefactor'};
2176 $y_scale = $opts{'scalefactor'} || $x_scale;
2178 elsif ($opts{'yscalefactor'}) {
2179 $y_scale = $opts{'yscalefactor'};
2180 $x_scale = $opts{'scalefactor'} || $y_scale;
2183 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2186 # work out the scaling
2187 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2188 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2189 $opts{ypixels} / $height );
2190 if ($opts{'type'} eq 'min') {
2191 $x_scale = $y_scale = _min($xpix,$ypix);
2193 elsif ($opts{'type'} eq 'max') {
2194 $x_scale = $y_scale = _max($xpix,$ypix);
2196 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2201 $self->_set_error('invalid value for type parameter');
2204 } elsif ($opts{xpixels}) {
2205 $x_scale = $y_scale = $opts{xpixels} / $width;
2207 elsif ($opts{ypixels}) {
2208 $x_scale = $y_scale = $opts{ypixels}/$height;
2210 elsif ($opts{constrain} && ref $opts{constrain}
2211 && $opts{constrain}->can('constrain')) {
2212 # we've been passed an Image::Math::Constrain object or something
2213 # that looks like one
2215 (undef, undef, $scalefactor)
2216 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2217 unless ($scalefactor) {
2218 $self->_set_error('constrain method failed on constrain parameter');
2221 $x_scale = $y_scale = $scalefactor;
2224 my $new_width = int($x_scale * $width + 0.5);
2225 $new_width > 0 or $new_width = 1;
2226 my $new_height = int($y_scale * $height + 0.5);
2227 $new_height > 0 or $new_height = 1;
2229 return ($x_scale, $y_scale, $new_width, $new_height);
2233 # Scale an image to requested size and return the scaled version
2237 my %opts = (qtype=>'normal' ,@_);
2238 my $img = Imager->new();
2239 my $tmp = Imager->new();
2241 unless (defined wantarray) {
2242 my @caller = caller;
2243 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2247 $self->_valid_image("scale")
2250 my ($x_scale, $y_scale, $new_width, $new_height) =
2251 $self->scale_calculate(%opts)
2254 if ($opts{qtype} eq 'normal') {
2255 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2256 if ( !defined($tmp->{IMG}) ) {
2257 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2260 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2261 if ( !defined($img->{IMG}) ) {
2262 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2268 elsif ($opts{'qtype'} eq 'preview') {
2269 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2270 if ( !defined($img->{IMG}) ) {
2271 $self->{ERRSTR}='unable to scale image';
2276 elsif ($opts{'qtype'} eq 'mixing') {
2277 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2278 unless ($img->{IMG}) {
2279 $self->_set_error(Imager->_error_as_msg);
2285 $self->_set_error('invalid value for qtype parameter');
2290 # Scales only along the X axis
2294 my %opts = ( scalefactor=>0.5, @_ );
2296 unless (defined wantarray) {
2297 my @caller = caller;
2298 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2302 $self->_valid_image("scaleX")
2305 my $img = Imager->new();
2307 my $scalefactor = $opts{scalefactor};
2309 if ($opts{pixels}) {
2310 $scalefactor = $opts{pixels} / $self->getwidth();
2313 unless ($self->{IMG}) {
2314 $self->{ERRSTR}='empty input image';
2318 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2320 if ( !defined($img->{IMG}) ) {
2321 $self->{ERRSTR} = 'unable to scale image';
2328 # Scales only along the Y axis
2332 my %opts = ( scalefactor => 0.5, @_ );
2334 unless (defined wantarray) {
2335 my @caller = caller;
2336 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2340 $self->_valid_image("scaleY")
2343 my $img = Imager->new();
2345 my $scalefactor = $opts{scalefactor};
2347 if ($opts{pixels}) {
2348 $scalefactor = $opts{pixels} / $self->getheight();
2351 unless ($self->{IMG}) {
2352 $self->{ERRSTR} = 'empty input image';
2355 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2357 if ( !defined($img->{IMG}) ) {
2358 $self->{ERRSTR} = 'unable to scale image';
2365 # Transform returns a spatial transformation of the input image
2366 # this moves pixels to a new location in the returned image.
2367 # NOTE - should make a utility function to check transforms for
2373 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2375 # print Dumper(\%opts);
2378 $self->_valid_image("transform")
2381 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2383 eval ("use Affix::Infix2Postfix;");
2386 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2389 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2390 {op=>'-',trans=>'Sub'},
2391 {op=>'*',trans=>'Mult'},
2392 {op=>'/',trans=>'Div'},
2393 {op=>'-','type'=>'unary',trans=>'u-'},
2395 {op=>'func','type'=>'unary'}],
2396 'grouping'=>[qw( \( \) )],
2397 'func'=>[qw( sin cos )],
2402 @xt=$I2P->translate($opts{'xexpr'});
2403 @yt=$I2P->translate($opts{'yexpr'});
2405 $numre=$I2P->{'numre'};
2408 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2409 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2410 @{$opts{'parm'}}=@pt;
2413 # print Dumper(\%opts);
2415 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2416 $self->{ERRSTR}='transform: no xopcodes given.';
2420 @op=@{$opts{'xopcodes'}};
2422 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2423 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2426 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2432 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2433 $self->{ERRSTR}='transform: no yopcodes given.';
2437 @op=@{$opts{'yopcodes'}};
2439 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2440 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2443 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2448 if ( !exists $opts{'parm'}) {
2449 $self->{ERRSTR}='transform: no parameter arg given.';
2453 # print Dumper(\@ropx);
2454 # print Dumper(\@ropy);
2455 # print Dumper(\@ropy);
2457 my $img = Imager->new();
2458 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2459 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2465 my ($opts, @imgs) = @_;
2467 require "Imager/Expr.pm";
2469 $opts->{variables} = [ qw(x y) ];
2470 my ($width, $height) = @{$opts}{qw(width height)};
2473 for my $img (@imgs) {
2474 unless ($img->_valid_image("transform2")) {
2475 Imager->_set_error($img->errstr . " (input image $index)");
2481 $width ||= $imgs[0]->getwidth();
2482 $height ||= $imgs[0]->getheight();
2484 for my $img (@imgs) {
2485 $opts->{constants}{"w$img_num"} = $img->getwidth();
2486 $opts->{constants}{"h$img_num"} = $img->getheight();
2487 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2488 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2493 $opts->{constants}{w} = $width;
2494 $opts->{constants}{cx} = $width/2;
2497 $Imager::ERRSTR = "No width supplied";
2501 $opts->{constants}{h} = $height;
2502 $opts->{constants}{cy} = $height/2;
2505 $Imager::ERRSTR = "No height supplied";
2508 my $code = Imager::Expr->new($opts);
2510 $Imager::ERRSTR = Imager::Expr::error();
2513 my $channels = $opts->{channels} || 3;
2514 unless ($channels >= 1 && $channels <= 4) {
2515 return Imager->_set_error("channels must be an integer between 1 and 4");
2518 my $img = Imager->new();
2519 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2520 $channels, $code->code(),
2521 $code->nregs(), $code->cregs(),
2522 [ map { $_->{IMG} } @imgs ]);
2523 if (!defined $img->{IMG}) {
2524 $Imager::ERRSTR = Imager->_error_as_msg();
2535 $self->_valid_image("rubthrough")
2538 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2539 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2543 %opts = (src_minx => 0,
2545 src_maxx => $opts{src}->getwidth(),
2546 src_maxy => $opts{src}->getheight(),
2550 defined $tx or $tx = $opts{left};
2551 defined $tx or $tx = 0;
2554 defined $ty or $ty = $opts{top};
2555 defined $ty or $ty = 0;
2557 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2558 $opts{src_minx}, $opts{src_miny},
2559 $opts{src_maxx}, $opts{src_maxy})) {
2560 $self->_set_error($self->_error_as_msg());
2577 $self->_valid_image("compose")
2580 unless ($opts{src}) {
2581 $self->_set_error("compose: src parameter missing");
2585 unless ($opts{src}->_valid_image("compose")) {
2586 $self->_set_error($opts{src}->errstr . " (for src)");
2589 my $src = $opts{src};
2591 my $left = $opts{left};
2592 defined $left or $left = $opts{tx};
2593 defined $left or $left = 0;
2595 my $top = $opts{top};
2596 defined $top or $top = $opts{ty};
2597 defined $top or $top = 0;
2599 my $src_left = $opts{src_left};
2600 defined $src_left or $src_left = $opts{src_minx};
2601 defined $src_left or $src_left = 0;
2603 my $src_top = $opts{src_top};
2604 defined $src_top or $src_top = $opts{src_miny};
2605 defined $src_top or $src_top = 0;
2607 my $width = $opts{width};
2608 if (!defined $width && defined $opts{src_maxx}) {
2609 $width = $opts{src_maxx} - $src_left;
2611 defined $width or $width = $src->getwidth() - $src_left;
2613 my $height = $opts{height};
2614 if (!defined $height && defined $opts{src_maxy}) {
2615 $height = $opts{src_maxy} - $src_top;
2617 defined $height or $height = $src->getheight() - $src_top;
2619 my $combine = $self->_combine($opts{combine}, 'normal');
2622 unless ($opts{mask}->_valid_image("compose")) {
2623 $self->_set_error($opts{mask}->errstr . " (for mask)");
2627 my $mask_left = $opts{mask_left};
2628 defined $mask_left or $mask_left = $opts{mask_minx};
2629 defined $mask_left or $mask_left = 0;
2631 my $mask_top = $opts{mask_top};
2632 defined $mask_top or $mask_top = $opts{mask_miny};
2633 defined $mask_top or $mask_top = 0;
2635 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2636 $left, $top, $src_left, $src_top,
2637 $mask_left, $mask_top, $width, $height,
2638 $combine, $opts{opacity})) {
2639 $self->_set_error(Imager->_error_as_msg);
2644 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2645 $width, $height, $combine, $opts{opacity})) {
2646 $self->_set_error(Imager->_error_as_msg);
2658 $self->_valid_image("flip")
2661 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2663 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2664 $dir = $xlate{$opts{'dir'}};
2665 return $self if i_flipxy($self->{IMG}, $dir);
2673 unless (defined wantarray) {
2674 my @caller = caller;
2675 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2679 $self->_valid_image("rotate")
2682 if (defined $opts{right}) {
2683 my $degrees = $opts{right};
2685 $degrees += 360 * int(((-$degrees)+360)/360);
2687 $degrees = $degrees % 360;
2688 if ($degrees == 0) {
2689 return $self->copy();
2691 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2692 my $result = Imager->new();
2693 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2697 $self->{ERRSTR} = $self->_error_as_msg();
2702 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2706 elsif (defined $opts{radians} || defined $opts{degrees}) {
2707 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2709 my $back = $opts{back};
2710 my $result = Imager->new;
2712 $back = _color($back);
2714 $self->_set_error(Imager->errstr);
2718 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2721 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2723 if ($result->{IMG}) {
2727 $self->{ERRSTR} = $self->_error_as_msg();
2732 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2737 sub matrix_transform {
2741 $self->_valid_image("matrix_transform")
2744 unless (defined wantarray) {
2745 my @caller = caller;
2746 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2750 if ($opts{matrix}) {
2751 my $xsize = $opts{xsize} || $self->getwidth;
2752 my $ysize = $opts{ysize} || $self->getheight;
2754 my $result = Imager->new;
2756 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2757 $opts{matrix}, $opts{back})
2761 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2769 $self->{ERRSTR} = "matrix parameter required";
2775 *yatf = \&matrix_transform;
2777 # These two are supported for legacy code only
2780 return Imager::Color->new(@_);
2784 return Imager::Color::set(@_);
2787 # Draws a box between the specified corner points.
2790 my $raw = $self->{IMG};
2792 $self->_valid_image("box")
2797 my ($xmin, $ymin, $xmax, $ymax);
2798 if (exists $opts{'box'}) {
2799 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2800 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2801 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2802 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2805 defined($xmin = $opts{xmin}) or $xmin = 0;
2806 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2807 defined($ymin = $opts{ymin}) or $ymin = 0;
2808 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2811 if ($opts{filled}) {
2812 my $color = $opts{'color'};
2814 if (defined $color) {
2815 unless (_is_color_object($color)) {
2816 $color = _color($color);
2818 $self->{ERRSTR} = $Imager::ERRSTR;
2824 $color = i_color_new(255,255,255,255);
2827 if ($color->isa("Imager::Color")) {
2828 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2831 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2834 elsif ($opts{fill}) {
2835 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2836 # assume it's a hash ref
2837 require 'Imager/Fill.pm';
2838 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2839 $self->{ERRSTR} = $Imager::ERRSTR;
2843 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2846 my $color = $opts{'color'};
2847 if (defined $color) {
2848 unless (_is_color_object($color)) {
2849 $color = _color($color);
2851 $self->{ERRSTR} = $Imager::ERRSTR;
2857 $color = i_color_new(255, 255, 255, 255);
2860 $self->{ERRSTR} = $Imager::ERRSTR;
2863 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2872 $self->_valid_image("arc")
2875 my $dflcl= [ 255, 255, 255, 255];
2880 'r'=>_min($self->getwidth(),$self->getheight())/3,
2881 'x'=>$self->getwidth()/2,
2882 'y'=>$self->getheight()/2,
2889 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2890 # assume it's a hash ref
2891 require 'Imager/Fill.pm';
2892 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2893 $self->{ERRSTR} = $Imager::ERRSTR;
2897 if ($opts{d1} == 0 && $opts{d2} == 361) {
2898 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2902 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2903 $opts{'d2'}, $opts{fill}{fill});
2906 elsif ($opts{filled}) {
2907 my $color = _color($opts{'color'});
2909 $self->{ERRSTR} = $Imager::ERRSTR;
2912 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2913 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2917 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2918 $opts{'d1'}, $opts{'d2'}, $color);
2922 my $color = _color($opts{'color'});
2923 if ($opts{d2} - $opts{d1} >= 360) {
2924 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2927 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2933 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2934 # assume it's a hash ref
2935 require 'Imager/Fill.pm';
2936 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2937 $self->{ERRSTR} = $Imager::ERRSTR;
2941 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2942 $opts{'d2'}, $opts{fill}{fill});
2945 my $color = _color($opts{'color'});
2947 $self->{ERRSTR} = $Imager::ERRSTR;
2950 if ($opts{filled}) {
2951 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2952 $opts{'d1'}, $opts{'d2'}, $color);
2955 if ($opts{d1} == 0 && $opts{d2} == 361) {
2956 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2959 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2965 $self->_set_error($self->_error_as_msg);
2972 # Draws a line from one point to the other
2973 # the endpoint is set if the endp parameter is set which it is by default.
2974 # to turn of the endpoint being set use endp=>0 when calling line.
2978 my $dflcl=i_color_new(0,0,0,0);
2979 my %opts=(color=>$dflcl,
2983 $self->_valid_image("line")
2986 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2987 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2989 my $color = _color($opts{'color'});
2991 $self->{ERRSTR} = $Imager::ERRSTR;
2995 $opts{antialias} = $opts{aa} if defined $opts{aa};
2996 if ($opts{antialias}) {
2997 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2998 $color, $opts{endp});
3000 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3001 $color, $opts{endp});
3006 # Draws a line between an ordered set of points - It more or less just transforms this
3007 # into a list of lines.
3011 my ($pt,$ls,@points);
3012 my $dflcl=i_color_new(0,0,0,0);
3013 my %opts=(color=>$dflcl,@_);
3015 $self->_valid_image("polyline")
3018 if (exists($opts{points})) { @points=@{$opts{points}}; }
3019 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3020 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3023 # print Dumper(\@points);
3025 my $color = _color($opts{'color'});
3027 $self->{ERRSTR} = $Imager::ERRSTR;
3030 $opts{antialias} = $opts{aa} if defined $opts{aa};
3031 if ($opts{antialias}) {
3034 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3041 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3051 my ($pt,$ls,@points);
3052 my $dflcl = i_color_new(0,0,0,0);
3053 my %opts = (color=>$dflcl, @_);
3055 $self->_valid_image("polygon")
3058 if (exists($opts{points})) {
3059 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3060 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3063 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3064 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3067 my $mode = _first($opts{mode}, 0);
3069 if ($opts{'fill'}) {
3070 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3071 # assume it's a hash ref
3072 require 'Imager/Fill.pm';
3073 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3074 $self->{ERRSTR} = $Imager::ERRSTR;
3078 i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3079 $mode, $opts{'fill'}{'fill'});
3082 my $color = _color($opts{'color'});
3084 $self->{ERRSTR} = $Imager::ERRSTR;
3087 i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color);
3094 my ($self, %opts) = @_;
3096 $self->_valid_image("polypolygon")
3099 my $points = $opts{points};
3101 or return $self->_set_error("polypolygon: missing required points");
3103 my $mode = _first($opts{mode}, "evenodd");
3105 if ($opts{filled}) {
3106 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3107 or return $self->_set_error($Imager::ERRSTR);
3109 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3110 or return $self->_set_error($self->_error_as_msg);
3112 elsif ($opts{fill}) {
3113 my $fill = $opts{fill};
3114 $self->_valid_fill($fill, "polypolygon")
3117 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3118 or return $self->_set_error($self->_error_as_msg);
3121 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3122 or return $self->_set_error($Imager::ERRSTR);
3124 my $rimg = $self->{IMG};
3126 if (_first($opts{aa}, 1)) {
3127 for my $poly (@$points) {
3128 my $xp = $poly->[0];
3129 my $yp = $poly->[1];
3130 for my $i (0 .. $#$xp - 1) {
3131 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3134 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3139 for my $poly (@$points) {
3140 my $xp = $poly->[0];
3141 my $yp = $poly->[1];
3142 for my $i (0 .. $#$xp - 1) {
3143 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3146 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3155 # this the multipoint bezier curve
3156 # this is here more for testing that actual usage since
3157 # this is not a good algorithm. Usually the curve would be
3158 # broken into smaller segments and each done individually.
3162 my ($pt,$ls,@points);
3163 my $dflcl=i_color_new(0,0,0,0);
3164 my %opts=(color=>$dflcl,@_);
3166 $self->_valid_image("polybezier")
3169 if (exists $opts{points}) {
3170 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3171 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3174 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3175 $self->{ERRSTR}='Missing or invalid points.';
3179 my $color = _color($opts{'color'});
3181 $self->{ERRSTR} = $Imager::ERRSTR;
3184 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3190 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3193 $self->_valid_image("flood_fill")
3196 unless (exists $opts{'x'} && exists $opts{'y'}) {
3197 $self->{ERRSTR} = "missing seed x and y parameters";
3201 if ($opts{border}) {
3202 my $border = _color($opts{border});
3204 $self->_set_error($Imager::ERRSTR);
3208 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3209 # assume it's a hash ref
3210 require Imager::Fill;
3211 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3212 $self->{ERRSTR} = $Imager::ERRSTR;
3216 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3217 $opts{fill}{fill}, $border);
3220 my $color = _color($opts{'color'});
3222 $self->{ERRSTR} = $Imager::ERRSTR;
3225 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3232 $self->{ERRSTR} = $self->_error_as_msg();
3238 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3239 # assume it's a hash ref
3240 require 'Imager/Fill.pm';
3241 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3242 $self->{ERRSTR} = $Imager::ERRSTR;
3246 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3249 my $color = _color($opts{'color'});
3251 $self->{ERRSTR} = $Imager::ERRSTR;
3254 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3260 $self->{ERRSTR} = $self->_error_as_msg();
3267 my ($self, %opts) = @_;
3269 $self->_valid_image("setpixel")
3272 my $color = $opts{color};
3273 unless (defined $color) {
3274 $color = $self->{fg};
3275 defined $color or $color = NC(255, 255, 255);
3278 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3279 unless ($color = _color($color, 'setpixel')) {
3280 $self->_set_error("setpixel: " . Imager->errstr);
3285 unless (exists $opts{'x'} && exists $opts{'y'}) {
3286 $self->_set_error('setpixel: missing x or y parameter');
3292 if (ref $x || ref $y) {
3293 $x = ref $x ? $x : [ $x ];
3294 $y = ref $y ? $y : [ $y ];
3296 $self->_set_error("setpixel: x is a reference to an empty array");
3300 $self->_set_error("setpixel: y is a reference to an empty array");
3304 # make both the same length, replicating the last element
3306 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3309 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3313 if ($color->isa('Imager::Color')) {
3314 for my $i (0..$#$x) {
3315 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3320 for my $i (0..$#$x) {
3321 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3329 if ($color->isa('Imager::Color')) {
3330 i_ppix($self->{IMG}, $x, $y, $color)
3331 and return "0 but true";
3334 i_ppixf($self->{IMG}, $x, $y, $color)
3335 and return "0 but true";
3345 my %opts = ( "type"=>'8bit', @_);
3347 $self->_valid_image("getpixel")
3350 unless (exists $opts{'x'} && exists $opts{'y'}) {
3351 $self->_set_error('getpixel: missing x or y parameter');
3357 my $type = $opts{'type'};
3358 if (ref $x || ref $y) {
3359 $x = ref $x ? $x : [ $x ];
3360 $y = ref $y ? $y : [ $y ];
3362 $self->_set_error("getpixel: x is a reference to an empty array");
3366 $self->_set_error("getpixel: y is a reference to an empty array");
3370 # make both the same length, replicating the last element
3372 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3375 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3379 if ($type eq '8bit') {
3380 for my $i (0..$#$x) {
3381 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3384 elsif ($type eq 'float' || $type eq 'double') {
3385 for my $i (0..$#$x) {
3386 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3390 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3393 return wantarray ? @result : \@result;
3396 if ($type eq '8bit') {
3397 return i_get_pixel($self->{IMG}, $x, $y);
3399 elsif ($type eq 'float' || $type eq 'double') {
3400 return i_gpixf($self->{IMG}, $x, $y);
3403 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3411 my %opts = ( type => '8bit', x=>0, @_);
3413 $self->_valid_image("getscanline")
3416 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3418 unless (defined $opts{'y'}) {
3419 $self->_set_error("missing y parameter");
3423 if ($opts{type} eq '8bit') {
3424 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3427 elsif ($opts{type} eq 'float') {
3428 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3431 elsif ($opts{type} eq 'index') {
3432 unless (i_img_type($self->{IMG})) {
3433 $self->_set_error("type => index only valid on paletted images");
3436 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3440 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3447 my %opts = ( x=>0, @_);
3449 $self->_valid_image("setscanline")
3452 unless (defined $opts{'y'}) {
3453 $self->_set_error("missing y parameter");
3458 if (ref $opts{pixels} && @{$opts{pixels}}) {
3459 # try to guess the type
3460 if ($opts{pixels}[0]->isa('Imager::Color')) {
3461 $opts{type} = '8bit';
3463 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3464 $opts{type} = 'float';
3467 $self->_set_error("missing type parameter and could not guess from pixels");
3473 $opts{type} = '8bit';
3477 if ($opts{type} eq '8bit') {
3478 if (ref $opts{pixels}) {
3479 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3482 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3485 elsif ($opts{type} eq 'float') {
3486 if (ref $opts{pixels}) {
3487 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3490 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3493 elsif ($opts{type} eq 'index') {
3494 if (ref $opts{pixels}) {
3495 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3498 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3502 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3509 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3511 $self->_valid_image("getsamples")
3514 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3516 unless (defined $opts{'y'}) {
3517 $self->_set_error("missing y parameter");
3521 if ($opts{target}) {
3522 my $target = $opts{target};
3523 my $offset = $opts{offset};
3524 if ($opts{type} eq '8bit') {
3525 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3526 $opts{y}, $opts{channels})
3528 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3529 return scalar(@samples);
3531 elsif ($opts{type} eq 'float') {
3532 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3533 $opts{y}, $opts{channels});
3534 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3535 return scalar(@samples);
3537 elsif ($opts{type} =~ /^(\d+)bit$/) {
3541 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3542 $opts{y}, $bits, $target,
3543 $offset, $opts{channels});
3544 unless (defined $count) {
3545 $self->_set_error(Imager->_error_as_msg);
3552 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3557 if ($opts{type} eq '8bit') {
3558 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3559 $opts{y}, $opts{channels});
3561 elsif ($opts{type} eq 'float') {
3562 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3563 $opts{y}, $opts{channels});
3565 elsif ($opts{type} =~ /^(\d+)bit$/) {
3569 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3570 $opts{y}, $bits, \@data, 0, $opts{channels})
3575 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3584 $self->_valid_image("setsamples")
3587 my %opts = ( x => 0, offset => 0 );
3589 # avoid duplicating the data parameter, it may be a large scalar
3591 while ($i < @_ -1) {
3592 if ($_[$i] eq 'data') {
3596 $opts{$_[$i]} = $_[$i+1];
3602 unless(defined $data_index) {
3603 $self->_set_error('setsamples: data parameter missing');
3606 unless (defined $_[$data_index]) {
3607 $self->_set_error('setsamples: data parameter not defined');
3611 my $type = $opts{type};
3612 defined $type or $type = '8bit';
3614 my $width = defined $opts{width} ? $opts{width}
3615 : $self->getwidth() - $opts{x};
3618 if ($type eq '8bit') {
3619 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3620 $_[$data_index], $opts{offset}, $width);
3622 elsif ($type eq 'float') {
3623 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3624 $_[$data_index], $opts{offset}, $width);
3626 elsif ($type =~ /^([0-9]+)bit$/) {
3629 unless (ref $_[$data_index]) {
3630 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3634 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3635 $opts{channels}, $_[$data_index], $opts{offset},
3639 $self->_set_error('setsamples: type parameter invalid');
3643 unless (defined $count) {
3644 $self->_set_error(Imager->_error_as_msg);
3651 # make an identity matrix of the given size
3655 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3656 for my $c (0 .. ($size-1)) {
3657 $matrix->[$c][$c] = 1;
3662 # general function to convert an image
3664 my ($self, %opts) = @_;
3667 $self->_valid_image("convert")
3670 unless (defined wantarray) {
3671 my @caller = caller;
3672 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3676 # the user can either specify a matrix or preset
3677 # the matrix overrides the preset
3678 if (!exists($opts{matrix})) {
3679 unless (exists($opts{preset})) {
3680 $self->{ERRSTR} = "convert() needs a matrix or preset";
3684 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3685 # convert to greyscale, keeping the alpha channel if any
3686 if ($self->getchannels == 3) {
3687 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3689 elsif ($self->getchannels == 4) {
3690 # preserve the alpha channel
3691 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3696 $matrix = _identity($self->getchannels);
3699 elsif ($opts{preset} eq 'noalpha') {
3700 # strip the alpha channel
3701 if ($self->getchannels == 2 or $self->getchannels == 4) {
3702 $matrix = _identity($self->getchannels);
3703 pop(@$matrix); # lose the alpha entry
3706 $matrix = _identity($self->getchannels);
3709 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3711 $matrix = [ [ 1 ] ];
3713 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3714 $matrix = [ [ 0, 1 ] ];
3716 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3717 $matrix = [ [ 0, 0, 1 ] ];
3719 elsif ($opts{preset} eq 'alpha') {
3720 if ($self->getchannels == 2 or $self->getchannels == 4) {
3721 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3724 # the alpha is just 1 <shrug>
3725 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3728 elsif ($opts{preset} eq 'rgb') {
3729 if ($self->getchannels == 1) {
3730 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3732 elsif ($self->getchannels == 2) {
3733 # preserve the alpha channel
3734 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3737 $matrix = _identity($self->getchannels);
3740 elsif ($opts{preset} eq 'addalpha') {
3741 if ($self->getchannels == 1) {
3742 $matrix = _identity(2);
3744 elsif ($self->getchannels == 3) {
3745 $matrix = _identity(4);
3748 $matrix = _identity($self->getchannels);
3752 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3758 $matrix = $opts{matrix};
3761 my $new = Imager->new;
3762 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3763 unless ($new->{IMG}) {
3764 # most likely a bad matrix
3765 i_push_error(0, "convert");
3766 $self->{ERRSTR} = _error_as_msg();
3772 # combine channels from multiple input images, a class method
3774 my ($class, %opts) = @_;
3776 my $src = delete $opts{src};
3778 $class->_set_error("src parameter missing");
3783 for my $img (@$src) {
3784 unless (eval { $img->isa("Imager") }) {
3785 $class->_set_error("src must contain image objects");
3788 unless ($img->_valid_image("combine")) {
3789 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3792 push @imgs, $img->{IMG};
3795 if (my $channels = delete $opts{channels}) {
3796 $result = i_combine(\@imgs, $channels);
3799 $result = i_combine(\@imgs);
3802 $class->_set_error($class->_error_as_msg);
3806 my $img = $class->new;
3807 $img->{IMG} = $result;
3813 # general function to map an image through lookup tables
3816 my ($self, %opts) = @_;
3817 my @chlist = qw( red green blue alpha );
3819 $self->_valid_image("map")
3822 if (!exists($opts{'maps'})) {
3823 # make maps from channel maps
3825 for $chnum (0..$#chlist) {
3826 if (exists $opts{$chlist[$chnum]}) {
3827 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3828 } elsif (exists $opts{'all'}) {
3829 $opts{'maps'}[$chnum] = $opts{'all'};
3833 if ($opts{'maps'} and $self->{IMG}) {
3834 i_map($self->{IMG}, $opts{'maps'} );
3840 my ($self, %opts) = @_;
3842 $self->_valid_image("difference")
3845 defined $opts{mindist} or $opts{mindist} = 0;
3847 defined $opts{other}
3848 or return $self->_set_error("No 'other' parameter supplied");
3849 unless ($opts{other}->_valid_image("difference")) {
3850 $self->_set_error($opts{other}->errstr . " (other image)");
3854 my $result = Imager->new;
3855 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3857 or return $self->_set_error($self->_error_as_msg());
3862 # destructive border - image is shrunk by one pixel all around
3865 my ($self,%opts)=@_;
3866 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3867 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3871 # Get the width of an image
3876 $self->_valid_image("getwidth")
3879 return i_img_get_width($self->{IMG});
3882 # Get the height of an image
3887 $self->_valid_image("getheight")
3890 return i_img_get_height($self->{IMG});
3893 # Get number of channels in an image
3898 $self->_valid_image("getchannels")
3901 return i_img_getchannels($self->{IMG});
3909 $self->_valid_image("getmask")
3912 return i_img_getmask($self->{IMG});
3921 $self->_valid_image("setmask")
3924 unless (defined $opts{mask}) {
3925 $self->_set_error("mask parameter required");
3929 i_img_setmask( $self->{IMG} , $opts{mask} );
3934 # Get number of colors in an image
3938 my %opts=('maxcolors'=>2**30,@_);
3940 $self->_valid_image("getcolorcount")
3943 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3944 return ($rc==-1? undef : $rc);
3947 # Returns a reference to a hash. The keys are colour named (packed) and the
3948 # values are the number of pixels in this colour.
3949 sub getcolorusagehash {
3952 $self->_valid_image("getcolorusagehash")
3955 my %opts = ( maxcolors => 2**30, @_ );
3956 my $max_colors = $opts{maxcolors};
3957 unless (defined $max_colors && $max_colors > 0) {
3958 $self->_set_error('maxcolors must be a positive integer');
3962 my $channels= $self->getchannels;
3963 # We don't want to look at the alpha channel, because some gifs using it
3964 # doesn't define it for every colour (but only for some)
3965 $channels -= 1 if $channels == 2 or $channels == 4;
3967 my $height = $self->getheight;
3968 for my $y (0 .. $height - 1) {
3969 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3970 while (length $colors) {
3971 $color_use{ substr($colors, 0, $channels, '') }++;
3973 keys %color_use > $max_colors
3979 # This will return a ordered array of the colour usage. Kind of the sorted
3980 # version of the values of the hash returned by getcolorusagehash.
3981 # You might want to add safety checks and change the names, etc...
3985 $self->_valid_image("getcolorusage")
3988 my %opts = ( maxcolors => 2**30, @_ );
3989 my $max_colors = $opts{maxcolors};
3990 unless (defined $max_colors && $max_colors > 0) {
3991 $self->_set_error('maxcolors must be a positive integer');
3995 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3998 # draw string to an image
4003 $self->_valid_image("string")
4006 my %input=('x'=>0, 'y'=>0, @_);
4007 defined($input{string}) or $input{string} = $input{text};
4009 unless(defined $input{string}) {
4010 $self->{ERRSTR}="missing required parameter 'string'";
4014 unless($input{font}) {
4015 $self->{ERRSTR}="missing required parameter 'font'";
4019 unless ($input{font}->draw(image=>$self, %input)) {
4031 $self->_valid_image("align_string")
4040 my %input=('x'=>0, 'y'=>0, @_);
4041 defined $input{string}
4042 or $input{string} = $input{text};
4044 unless(exists $input{string}) {
4045 $self->_set_error("missing required parameter 'string'");
4049 unless($input{font}) {
4050 $self->_set_error("missing required parameter 'font'");
4055 unless (@result = $input{font}->align(image=>$img, %input)) {
4059 return wantarray ? @result : $result[0];
4062 my @file_limit_names = qw/width height bytes/;
4064 sub set_file_limits {
4071 @values{@file_limit_names} = (0) x @file_limit_names;
4074 @values{@file_limit_names} = i_get_image_file_limits();
4077 for my $key (keys %values) {
4078 defined $opts{$key} and $values{$key} = $opts{$key};
4081 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4084 sub get_file_limits {
4085 i_get_image_file_limits();
4088 my @check_args = qw(width height channels sample_size);
4090 sub check_file_limits {
4100 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4101 $opts{sample_size} = length(pack("d", 0));
4104 for my $name (@check_args) {
4105 unless (defined $opts{$name}) {
4106 $class->_set_error("check_file_limits: $name must be defined");
4109 unless ($opts{$name} == int($opts{$name})) {
4110 $class->_set_error("check_file_limits: $name must be a positive integer");
4115 my $result = i_int_check_image_file_limits(@opts{@check_args});
4117 $class->_set_error($class->_error_as_msg());
4123 # Shortcuts that can be exported
4125 sub newcolor { Imager::Color->new(@_); }
4126 sub newfont { Imager::Font->new(@_); }
4128 require Imager::Color::Float;
4129 return Imager::Color::Float->new(@_);
4132 *NC=*newcolour=*newcolor;
4139 #### Utility routines
4142 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4146 my ($self, $msg) = @_;
4149 $self->{ERRSTR} = $msg;
4157 # Default guess for the type of an image from extension
4159 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4163 ( map { $_ => $_ } @simple_types ),
4169 pnm => "pnm", # technically wrong, but historically it works in Imager
4182 sub def_guess_type {
4185 my ($ext) = $name =~ /\.([^.]+)$/
4188 my $type = $ext_types{$ext}
4195 return @combine_types;
4198 # get the minimum of a list
4202 for(@_) { if ($_<$mx) { $mx=$_; }}
4206 # get the maximum of a list
4210 for(@_) { if ($_>$mx) { $mx=$_; }}
4214 # string stuff for iptc headers
4218 $str = substr($str,3);
4219 $str =~ s/[\n\r]//g;
4226 # A little hack to parse iptc headers.
4231 my($caption,$photogr,$headln,$credit);
4233 my $str=$self->{IPTCRAW};
4238 @ar=split(/8BIM/,$str);
4243 @sar=split(/\034\002/);
4244 foreach $item (@sar) {
4245 if ($item =~ m/^x/) {
4246 $caption = _clean($item);
4249 if ($item =~ m/^P/) {
4250 $photogr = _clean($item);
4253 if ($item =~ m/^i/) {
4254 $headln = _clean($item);
4257 if ($item =~ m/^n/) {
4258 $credit = _clean($item);
4264 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4268 # Inline added a new argument at the beginning
4272 or die "Only C language supported";
4274 require Imager::ExtUtils;
4275 return Imager::ExtUtils->inline_config;
4278 # threads shouldn't try to close raw Imager objects
4279 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4282 # this serves two purposes:
4283 # - a class method to load the file support modules included with Imager
4284 # (or were included, once the library dependent modules are split out)
4285 # - something for Module::ScanDeps to analyze
4286 # https://rt.cpan.org/Ticket/Display.html?id=6566
4288 eval { require Imager::File::GIF };
4289 eval { require Imager::File::JPEG };
4290 eval { require Imager::File::PNG };
4291 eval { require Imager::File::SGI };
4292 eval { require Imager::File::TIFF };
4293 eval { require Imager::File::ICO };
4294 eval { require Imager::Font::W32 };
4295 eval { require Imager::Font::FT2 };
4296 eval { require Imager::Font::T1 };
4303 my ($class, $fh) = @_;
4306 return $class->new_cb
4311 return print $fh $_[0];
4315 my $count = CORE::read $fh, $tmp, $_[1];
4323 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4324 unless (CORE::seek $fh, $_[0], $_[1]) {
4335 return $class->_new_perlio($fh);
4339 # backward compatibility for %formats
4340 package Imager::FORMATS;
4342 use constant IX_FORMATS => 0;
4343 use constant IX_LIST => 1;
4344 use constant IX_INDEX => 2;
4345 use constant IX_CLASSES => 3;
4348 my ($class, $formats, $classes) = @_;
4350 return bless [ $formats, [ ], 0, $classes ], $class;
4354 my ($self, $key) = @_;
4356 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4359 my $loaded = Imager::_load_file($file, \$error);
4364 if ($error =~ /^Can't locate /) {
4365 $error = "Can't locate $file";
4367 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4370 $self->[IX_FORMATS]{$key} = $value;
4376 my ($self, $key) = @_;
4378 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4380 $self->[IX_CLASSES]{$key} or return undef;
4382 return $self->_check($key);
4386 die "%Imager::formats is not user monifiable";
4390 die "%Imager::formats is not user monifiable";
4394 die "%Imager::formats is not user monifiable";
4398 my ($self, $key) = @_;
4400 if (exists $self->[IX_FORMATS]{$key}) {
4401 my $value = $self->[IX_FORMATS]{$key}
4406 $self->_check($key) or return 1==0;
4414 unless (@{$self->[IX_LIST]}) {
4416 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4417 keys %{$self->[IX_FORMATS]};
4419 for my $key (keys %{$self->[IX_CLASSES]}) {
4420 $self->[IX_FORMATS]{$key} and next;
4422 and push @{$self->[IX_LIST]}, $key;
4426 @{$self->[IX_LIST]} or return;
4427 $self->[IX_INDEX] = 1;
4428 return $self->[IX_LIST][0];
4434 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4437 return $self->[IX_LIST][$self->[IX_INDEX]++];
4443 return scalar @{$self->[IX_LIST]};
4448 # Below is the stub of documentation for your module. You better edit it!
4452 Imager - Perl extension for Generating 24 bit Images
4462 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4467 # see Imager::Files for information on the read() method
4468 my $img = Imager->new(file=>$file)
4469 or die Imager->errstr();
4471 $file =~ s/\.[^.]*$//;
4473 # Create smaller version
4474 # documented in Imager::Transformations
4475 my $thumb = $img->scale(scalefactor=>.3);
4477 # Autostretch individual channels
4478 $thumb->filter(type=>'autolevels');
4480 # try to save in one of these formats
4483 for $format ( qw( png gif jpeg tiff ppm ) ) {
4484 # Check if given format is supported
4485 if ($Imager::formats{$format}) {
4486 $file.="_low.$format";
4487 print "Storing image as: $file\n";
4488 # documented in Imager::Files
4489 $thumb->write(file=>$file) or
4497 Imager is a module for creating and altering images. It can read and
4498 write various image formats, draw primitive shapes like lines,and
4499 polygons, blend multiple images together in various ways, scale, crop,
4500 render text and more.
4502 =head2 Overview of documentation
4508 Imager - This document - Synopsis, Example, Table of Contents and
4513 L<Imager::Install> - installation notes for Imager.
4517 L<Imager::Tutorial> - a brief introduction to Imager.
4521 L<Imager::Cookbook> - how to do various things with Imager.
4525 L<Imager::ImageTypes> - Basics of constructing image objects with
4526 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4527 8/16/double bits/channel, color maps, channel masks, image tags, color
4528 quantization. Also discusses basic image information methods.
4532 L<Imager::Files> - IO interaction, reading/writing images, format
4537 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4542 L<Imager::Color> - Color specification.
4546 L<Imager::Fill> - Fill pattern specification.
4550 L<Imager::Font> - General font rendering, bounding boxes and font
4555 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4556 blending, pasting, convert and map.
4560 L<Imager::Engines> - Programmable transformations through
4561 C<transform()>, C<transform2()> and C<matrix_transform()>.
4565 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4570 L<Imager::Expr> - Expressions for evaluation engine used by
4575 L<Imager::Matrix2d> - Helper class for affine transformations.
4579 L<Imager::Fountain> - Helper for making gradient profiles.
4583 L<Imager::IO> - Imager I/O abstraction.
4587 L<Imager::API> - using Imager's C API
4591 L<Imager::APIRef> - API function reference
4595 L<Imager::Inline> - using Imager's C API from Inline::C
4599 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4603 L<Imager::Security> - brief security notes.
4607 L<Imager::Threads> - brief information on working with threads.
4611 =head2 Basic Overview
4613 An Image object is created with C<$img = Imager-E<gt>new()>.
4616 $img=Imager->new(); # create empty image
4617 $img->read(file=>'lena.png',type=>'png') or # read image from file
4618 die $img->errstr(); # give an explanation
4619 # if something failed
4621 or if you want to create an empty image:
4623 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4625 This example creates a completely black image of width 400 and height
4628 =head1 ERROR HANDLING
4630 In general a method will return false when it fails, if it does use
4631 the C<errstr()> method to find out why:
4637 Returns the last error message in that context.
4639 If the last error you received was from calling an object method, such
4640 as read, call errstr() as an object method to find out why:
4642 my $image = Imager->new;
4643 $image->read(file => 'somefile.gif')
4644 or die $image->errstr;
4646 If it was a class method then call errstr() as a class method:
4648 my @imgs = Imager->read_multi(file => 'somefile.gif')
4649 or die Imager->errstr;
4651 Note that in some cases object methods are implemented in terms of
4652 class methods so a failing object method may set both.
4656 The C<Imager-E<gt>new> method is described in detail in
4657 L<Imager::ImageTypes>.
4661 Where to find information on methods for Imager class objects.
4663 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4666 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4668 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4671 arc() - L<Imager::Draw/arc()> - draw a filled arc
4673 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4676 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4678 check_file_limits() - L<Imager::Files/check_file_limits()>
4680 circle() - L<Imager::Draw/circle()> - draw a filled circle
4682 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4685 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4686 colors in an image's palette (paletted images only)
4688 combine() - L<Imager::Transformations/combine()> - combine channels
4689 from one or more images.
4691 combines() - L<Imager::Draw/combines()> - return a list of the
4692 different combine type keywords
4694 compose() - L<Imager::Transformations/compose()> - compose one image
4697 convert() - L<Imager::Transformations/convert()> - transform the color
4700 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4703 crop() - L<Imager::Transformations/crop()> - extract part of an image
4705 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4706 used to guess the output file format based on the output file name
4708 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4710 difference() - L<Imager::Filters/difference()> - produce a difference
4711 images from two input images.
4713 errstr() - L</errstr()> - the error from the last failed operation.
4715 filter() - L<Imager::Filters/filter()> - image filtering
4717 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4718 palette, if it has one
4720 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4723 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4726 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4727 samples per pixel for an image
4729 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4730 different colors used by an image (works for direct color images)
4732 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4733 palette, if it has one
4735 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4737 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4739 get_file_limits() - L<Imager::Files/get_file_limits()>
4741 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4744 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4746 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4749 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4750 row or partial row of pixels.
4752 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4753 row or partial row of pixels.
4755 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4758 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4761 init() - L<Imager::ImageTypes/init()>
4763 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4764 image write functions should write the image in their bilevel (blank
4765 and white, no gray levels) format
4767 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4770 line() - L<Imager::Draw/line()> - draw an interval
4772 load_plugin() - L<Imager::Filters/load_plugin()>
4774 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4777 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4778 color palette from one or more input images.
4780 map() - L<Imager::Transformations/map()> - remap color
4783 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4785 matrix_transform() - L<Imager::Engines/matrix_transform()>
4787 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4789 NC() - L<Imager::Handy/NC()>
4791 NCF() - L<Imager::Handy/NCF()>
4793 new() - L<Imager::ImageTypes/new()>
4795 newcolor() - L<Imager::Handy/newcolor()>
4797 newcolour() - L<Imager::Handy/newcolour()>
4799 newfont() - L<Imager::Handy/newfont()>
4801 NF() - L<Imager::Handy/NF()>
4803 open() - L<Imager::Files/read()> - an alias for read()
4805 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4809 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4812 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4815 polygon() - L<Imager::Draw/polygon()>
4817 polyline() - L<Imager::Draw/polyline()>
4819 polypolygon() - L<Imager::Draw/polypolygon()>
4821 preload() - L<Imager::Files/preload()>
4823 read() - L<Imager::Files/read()> - read a single image from an image file
4825 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4828 read_types() - L<Imager::Files/read_types()> - list image types Imager
4831 register_filter() - L<Imager::Filters/register_filter()>
4833 register_reader() - L<Imager::Files/register_reader()>
4835 register_writer() - L<Imager::Files/register_writer()>
4837 rotate() - L<Imager::Transformations/rotate()>
4839 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4840 onto an image and use the alpha channel
4842 scale() - L<Imager::Transformations/scale()>
4844 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4846 scaleX() - L<Imager::Transformations/scaleX()>
4848 scaleY() - L<Imager::Transformations/scaleY()>
4850 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4853 set_file_limits() - L<Imager::Files/set_file_limits()>
4855 setmask() - L<Imager::ImageTypes/setmask()>
4857 setpixel() - L<Imager::Draw/setpixel()>
4859 setsamples() - L<Imager::Draw/setsamples()>
4861 setscanline() - L<Imager::Draw/setscanline()>
4863 settag() - L<Imager::ImageTypes/settag()>
4865 string() - L<Imager::Draw/string()> - draw text on an image
4867 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4869 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4871 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4873 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4875 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4876 double per sample image.
4878 transform() - L<Imager::Engines/"transform()">
4880 transform2() - L<Imager::Engines/"transform2()">
4882 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4884 unload_plugin() - L<Imager::Filters/unload_plugin()>
4886 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4889 write() - L<Imager::Files/write()> - write an image to a file
4891 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4894 write_types() - L<Imager::Files/read_types()> - list image types Imager
4897 =head1 CONCEPT INDEX
4899 animated GIF - L<Imager::Files/"Writing an animated GIF">
4901 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4902 L<Imager::ImageTypes/"Common Tags">.
4904 blend - alpha blending one image onto another
4905 L<Imager::Transformations/rubthrough()>
4907 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4909 boxes, drawing - L<Imager::Draw/box()>
4911 changes between image - L<Imager::Filters/"Image Difference">
4913 channels, combine into one image - L<Imager::Transformations/combine()>
4915 color - L<Imager::Color>
4917 color names - L<Imager::Color>, L<Imager::Color::Table>
4919 combine modes - L<Imager::Draw/"Combine Types">
4921 compare images - L<Imager::Filters/"Image Difference">
4923 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4925 convolution - L<Imager::Filters/conv>
4927 cropping - L<Imager::Transformations/crop()>
4929 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4931 C<diff> images - L<Imager::Filters/"Image Difference">
4933 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4934 L<Imager::Cookbook/"Image spatial resolution">
4936 drawing boxes - L<Imager::Draw/box()>
4938 drawing lines - L<Imager::Draw/line()>
4940 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4942 error message - L</"ERROR HANDLING">
4944 files, font - L<Imager::Font>
4946 files, image - L<Imager::Files>
4948 filling, types of fill - L<Imager::Fill>
4950 filling, boxes - L<Imager::Draw/box()>
4952 filling, flood fill - L<Imager::Draw/flood_fill()>
4954 flood fill - L<Imager::Draw/flood_fill()>
4956 fonts - L<Imager::Font>
4958 fonts, drawing with - L<Imager::Draw/string()>,
4959 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4961 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4963 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4965 fountain fill - L<Imager::Fill/"Fountain fills">,
4966 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4967 L<Imager::Filters/gradgen>
4969 GIF files - L<Imager::Files/"GIF">
4971 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4973 gradient fill - L<Imager::Fill/"Fountain fills">,
4974 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4975 L<Imager::Filters/gradgen>
4977 gray scale, convert image to - L<Imager::Transformations/convert()>
4979 gaussian blur - L<Imager::Filters/gaussian>
4981 hatch fills - L<Imager::Fill/"Hatched fills">
4983 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4985 invert image - L<Imager::Filters/hardinvert>,
4986 L<Imager::Filters/hardinvertall>
4988 JPEG - L<Imager::Files/"JPEG">
4990 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4992 lines, drawing - L<Imager::Draw/line()>
4994 matrix - L<Imager::Matrix2d>,
4995 L<Imager::Engines/"Matrix Transformations">,
4996 L<Imager::Font/transform()>
4998 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5000 mosaic - L<Imager::Filters/mosaic>
5002 noise, filter - L<Imager::Filters/noise>
5004 noise, rendered - L<Imager::Filters/turbnoise>,
5005 L<Imager::Filters/radnoise>
5007 paste - L<Imager::Transformations/paste()>,
5008 L<Imager::Transformations/rubthrough()>
5010 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5011 L<Imager::ImageTypes/new()>
5013 =for stopwords posterize
5015 posterize - L<Imager::Filters/postlevels>
5017 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5019 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5021 rectangles, drawing - L<Imager::Draw/box()>
5023 resizing an image - L<Imager::Transformations/scale()>,
5024 L<Imager::Transformations/crop()>
5026 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5028 saving an image - L<Imager::Files>
5030 scaling - L<Imager::Transformations/scale()>
5032 security - L<Imager::Security>
5034 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5036 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
5038 size, image - L<Imager::ImageTypes/getwidth()>,
5039 L<Imager::ImageTypes/getheight()>
5041 size, text - L<Imager::Font/bounding_box()>
5043 tags, image metadata - L<Imager::ImageTypes/"Tags">
5045 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5046 L<Imager::Font::Wrap>
5048 text, wrapping text in an area - L<Imager::Font::Wrap>
5050 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5052 threads - L<Imager::Threads>
5054 tiles, color - L<Imager::Filters/mosaic>
5056 transparent images - L<Imager::ImageTypes>,
5057 L<Imager::Cookbook/"Transparent PNG">
5059 =for stopwords unsharp
5061 unsharp mask - L<Imager::Filters/unsharpmask>
5063 watermark - L<Imager::Filters/watermark>
5065 writing an image to a file - L<Imager::Files>
5069 The best place to get help with Imager is the mailing list.
5071 To subscribe send a message with C<subscribe> in the body to:
5073 imager-devel+request@molar.is
5079 L<http://www.molar.is/en/lists/imager-devel/>
5083 where you can also find the mailing list archive.
5085 You can report bugs by pointing your browser at:
5089 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5093 or by sending an email to:
5097 bug-Imager@rt.cpan.org
5101 Please remember to include the versions of Imager, perl, supporting
5102 libraries, and any relevant code. If you have specific images that
5103 cause the problems, please include those too.
5105 If you don't want to publish your email address on a mailing list you
5106 can use CPAN::Forum:
5108 http://www.cpanforum.com/dist/Imager
5110 You will need to register to post.
5112 =head1 CONTRIBUTING TO IMAGER
5118 If you like or dislike Imager, you can add a public review of Imager
5121 http://cpanratings.perl.org/dist/Imager
5123 =for stopwords Bitcard
5125 This requires a Bitcard account (http://www.bitcard.org).
5127 You can also send email to the maintainer below.
5129 If you send me a bug report via email, it will be copied to Request
5134 I accept patches, preferably against the master branch in git. Please
5135 include an explanation of the reason for why the patch is needed or
5138 Your patch should include regression tests where possible, otherwise
5139 it will be delayed until I get a chance to write them.
5141 To browse Imager's git repository:
5143 http://git.imager.perl.org/imager.git
5147 git clone git://git.imager.perl.org/imager.git
5149 My preference is that patches are provided in the format produced by
5150 C<git format-patch>, for example, if you made your changes in a branch
5151 from master you might do:
5153 git format-patch -k --stdout master >my-patch.txt
5155 and then attach that to your bug report, either by adding it as an
5156 attachment in your email client, or by using the Request Tracker
5157 attachment mechanism.
5161 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5163 Arnar M. Hrafnkelsson is the original author of Imager.
5165 Many others have contributed to Imager, please see the C<README> for a
5170 Imager is licensed under the same terms as perl itself.
5173 makeblendedfont Fontforge
5175 A test font, generated by the Debian packaged Fontforge,
5176 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5177 copyrighted by Adobe. See F<adobe.txt> in the source for license
5182 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5183 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5184 L<Imager::Font>(3), L<Imager::Transformations>(3),
5185 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5186 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5188 L<http://imager.perl.org/>
5190 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5192 Other perl imaging modules include:
5194 L<GD>(3), L<Image::Magick>(3),
5195 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5196 L<Prima::Image>, L<IPA>.
5198 For manipulating image metadata see L<Image::ExifTool>.
5200 If you're trying to use Imager for array processing, you should
5201 probably using L<PDL>.