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{file} ||
677 defined $hsh{callback} ||
678 defined $hsh{readcb} ||
679 defined $hsh{data} ||
681 # allow $img = Imager->new(file => $filename)
684 # type is already used as a parameter to new(), rename it for the
686 if ($hsh{filetype}) {
687 $extras{type} = $hsh{filetype};
689 unless ($self->read(%hsh, %extras)) {
690 $Imager::ERRSTR = $self->{ERRSTR};
694 elsif (defined $hsh{xsize} || defined $hsh{ysize}) {
695 unless ($self->img_set(%hsh)) {
696 $Imager::ERRSTR = $self->{ERRSTR};
701 Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
708 # Copy an entire image with no changes
709 # - if an image has magic the copy of it will not be magical
714 $self->_valid_image("copy")
717 unless (defined wantarray) {
719 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
723 my $newcopy=Imager->new();
724 $newcopy->{IMG} = i_copy($self->{IMG});
733 $self->_valid_image("paste")
736 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
737 my $src = $input{img} || $input{src};
739 $self->_set_error("no source image");
742 unless ($src->_valid_image("paste")) {
743 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
746 $input{left}=0 if $input{left} <= 0;
747 $input{top}=0 if $input{top} <= 0;
749 my($r,$b)=i_img_info($src->{IMG});
750 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
751 my ($src_right, $src_bottom);
752 if ($input{src_coords}) {
753 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
756 if (defined $input{src_maxx}) {
757 $src_right = $input{src_maxx};
759 elsif (defined $input{width}) {
760 if ($input{width} <= 0) {
761 $self->_set_error("paste: width must me positive");
764 $src_right = $src_left + $input{width};
769 if (defined $input{src_maxy}) {
770 $src_bottom = $input{src_maxy};
772 elsif (defined $input{height}) {
773 if ($input{height} < 0) {
774 $self->_set_error("paste: height must be positive");
777 $src_bottom = $src_top + $input{height};
784 $src_right > $r and $src_right = $r;
785 $src_bottom > $b and $src_bottom = $b;
787 if ($src_right <= $src_left
788 || $src_bottom < $src_top) {
789 $self->_set_error("nothing to paste");
793 i_copyto($self->{IMG}, $src->{IMG},
794 $src_left, $src_top, $src_right, $src_bottom,
795 $input{left}, $input{top});
797 return $self; # What should go here??
800 # Crop an image - i.e. return a new image that is smaller
805 $self->_valid_image("crop")
808 unless (defined wantarray) {
810 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
816 my ($w, $h, $l, $r, $b, $t) =
817 @hsh{qw(width height left right bottom top)};
819 # work through the various possibilities
824 elsif (!defined $r) {
825 $r = $self->getwidth;
837 $l = int(0.5+($self->getwidth()-$w)/2);
842 $r = $self->getwidth;
848 elsif (!defined $b) {
849 $b = $self->getheight;
861 $t=int(0.5+($self->getheight()-$h)/2);
866 $b = $self->getheight;
869 ($l,$r)=($r,$l) if $l>$r;
870 ($t,$b)=($b,$t) if $t>$b;
873 $r > $self->getwidth and $r = $self->getwidth;
875 $b > $self->getheight and $b = $self->getheight;
877 if ($l == $r || $t == $b) {
878 $self->_set_error("resulting image would have no content");
881 if( $r < $l or $b < $t ) {
882 $self->_set_error("attempting to crop outside of the image");
885 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
887 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
892 my ($self, %opts) = @_;
897 my $x = $opts{xsize} || $self->getwidth;
898 my $y = $opts{ysize} || $self->getheight;
899 my $channels = $opts{channels} || $self->getchannels;
901 my $out = Imager->new;
902 if ($channels == $self->getchannels) {
903 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
906 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
908 unless ($out->{IMG}) {
909 $self->{ERRSTR} = $self->_error_as_msg;
916 # Sets an image to a certain size and channel number
917 # if there was previously data in the image it is discarded
930 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
935 if (my $channels = $model_channels{$hsh{model}}) {
936 $hsh{channels} = $channels;
939 $self->_set_error("new: unknown value for model '$hsh{model}'");
944 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
945 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
946 $hsh{maxcolors} || 256);
948 elsif ($hsh{bits} eq 'double') {
949 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
951 elsif ($hsh{bits} == 16) {
952 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
955 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
959 unless ($self->{IMG}) {
960 $self->_set_error(Imager->_error_as_msg());
967 # created a masked version of the current image
971 $self->_valid_image("masked")
974 my %opts = (left => 0,
976 right => $self->getwidth,
977 bottom => $self->getheight,
979 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
981 my $result = Imager->new;
982 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
983 $opts{top}, $opts{right} - $opts{left},
984 $opts{bottom} - $opts{top});
985 unless ($result->{IMG}) {
986 $self->_set_error(Imager->_error_as_msg);
990 # keep references to the mask and base images so they don't
992 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
997 # convert an RGB image into a paletted image
1001 if (@_ != 1 && !ref $_[0]) {
1008 unless (defined wantarray) {
1009 my @caller = caller;
1010 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
1014 $self->_valid_image("to_paletted")
1017 my $result = Imager->new;
1018 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1019 $self->_set_error(Imager->_error_as_msg);
1027 my ($class, $quant, @images) = @_;
1030 Imager->_set_error("make_palette: supply at least one image");
1034 for my $img (@images) {
1035 unless ($img->{IMG}) {
1036 Imager->_set_error("make_palette: image $index is empty");
1042 return i_img_make_palette($quant, map $_->{IMG}, @images);
1045 # convert a paletted (or any image) to an 8-bit/channel RGB image
1049 unless (defined wantarray) {
1050 my @caller = caller;
1051 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1055 $self->_valid_image("to_rgb8")
1058 my $result = Imager->new;
1059 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1060 $self->_set_error(Imager->_error_as_msg());
1067 # convert a paletted (or any image) to a 16-bit/channel RGB image
1071 unless (defined wantarray) {
1072 my @caller = caller;
1073 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1077 $self->_valid_image("to_rgb16")
1080 my $result = Imager->new;
1081 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1082 $self->_set_error(Imager->_error_as_msg());
1089 # convert a paletted (or any image) to an double/channel RGB image
1093 unless (defined wantarray) {
1094 my @caller = caller;
1095 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1099 $self->_valid_image("to_rgb_double")
1102 my $result = Imager->new;
1103 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1104 $self->_set_error(Imager->_error_as_msg());
1113 my %opts = (colors=>[], @_);
1115 $self->_valid_image("addcolors")
1118 my @colors = @{$opts{colors}}
1121 for my $color (@colors) {
1122 $color = _color($color);
1124 $self->_set_error($Imager::ERRSTR);
1129 return i_addcolors($self->{IMG}, @colors);
1134 my %opts = (start=>0, colors=>[], @_);
1136 $self->_valid_image("setcolors")
1139 my @colors = @{$opts{colors}}
1142 for my $color (@colors) {
1143 $color = _color($color);
1145 $self->_set_error($Imager::ERRSTR);
1150 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1157 $self->_valid_image("getcolors")
1160 if (!exists $opts{start} && !exists $opts{count}) {
1163 $opts{count} = $self->colorcount;
1165 elsif (!exists $opts{count}) {
1168 elsif (!exists $opts{start}) {
1172 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1178 $self->_valid_image("colorcount")
1181 return i_colorcount($self->{IMG});
1187 $self->_valid_image("maxcolors")
1190 i_maxcolors($self->{IMG});
1197 $self->_valid_image("findcolor")
1200 unless ($opts{color}) {
1201 $self->_set_error("findcolor: no color parameter");
1205 my $color = _color($opts{color})
1208 return i_findcolor($self->{IMG}, $color);
1214 $self->_valid_image("bits")
1217 my $bits = i_img_bits($self->{IMG});
1218 if ($bits && $bits == length(pack("d", 1)) * 8) {
1227 $self->_valid_image("type")
1230 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1236 $self->_valid_image("virtual")
1239 return i_img_virtual($self->{IMG});
1245 $self->_valid_image("is_bilevel")
1248 return i_img_is_monochrome($self->{IMG});
1252 my ($self, %opts) = @_;
1254 $self->_valid_image("tags")
1257 if (defined $opts{name}) {
1261 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1262 push @result, (i_tags_get($self->{IMG}, $found))[1];
1265 return wantarray ? @result : $result[0];
1267 elsif (defined $opts{code}) {
1271 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1272 push @result, (i_tags_get($self->{IMG}, $found))[1];
1279 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1282 return i_tags_count($self->{IMG});
1291 $self->_valid_image("addtag")
1295 if (defined $opts{value}) {
1296 if ($opts{value} =~ /^\d+$/) {
1298 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1301 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1304 elsif (defined $opts{data}) {
1305 # force addition as a string
1306 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1309 $self->{ERRSTR} = "No value supplied";
1313 elsif ($opts{code}) {
1314 if (defined $opts{value}) {
1315 if ($opts{value} =~ /^\d+$/) {
1317 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1320 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1323 elsif (defined $opts{data}) {
1324 # force addition as a string
1325 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1328 $self->{ERRSTR} = "No value supplied";
1341 $self->_valid_image("deltag")
1344 if (defined $opts{'index'}) {
1345 return i_tags_delete($self->{IMG}, $opts{'index'});
1347 elsif (defined $opts{name}) {
1348 return i_tags_delbyname($self->{IMG}, $opts{name});
1350 elsif (defined $opts{code}) {
1351 return i_tags_delbycode($self->{IMG}, $opts{code});
1354 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1360 my ($self, %opts) = @_;
1362 $self->_valid_image("settag")
1366 $self->deltag(name=>$opts{name});
1367 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1369 elsif (defined $opts{code}) {
1370 $self->deltag(code=>$opts{code});
1371 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1379 sub _get_reader_io {
1380 my ($self, $input) = @_;
1383 return $input->{io}, undef;
1385 elsif ($input->{fd}) {
1386 return io_new_fd($input->{fd});
1388 elsif ($input->{fh}) {
1389 unless (Scalar::Util::openhandle($input->{fh})) {
1390 $self->_set_error("Handle in fh option not opened");
1393 return Imager::IO->new_fh($input->{fh});
1395 elsif ($input->{file}) {
1396 my $file = IO::File->new($input->{file}, "r");
1398 $self->_set_error("Could not open $input->{file}: $!");
1402 return (io_new_fd(fileno($file)), $file);
1404 elsif ($input->{data}) {
1405 return io_new_buffer($input->{data});
1407 elsif ($input->{callback} || $input->{readcb}) {
1408 if (!$input->{seekcb}) {
1409 $self->_set_error("Need a seekcb parameter");
1411 if ($input->{maxbuffer}) {
1412 return io_new_cb($input->{writecb},
1413 $input->{callback} || $input->{readcb},
1414 $input->{seekcb}, $input->{closecb},
1415 $input->{maxbuffer});
1418 return io_new_cb($input->{writecb},
1419 $input->{callback} || $input->{readcb},
1420 $input->{seekcb}, $input->{closecb});
1424 $self->_set_error("file/fd/fh/data/callback parameter missing");
1429 sub _get_writer_io {
1430 my ($self, $input) = @_;
1432 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1439 elsif ($input->{fd}) {
1440 $io = io_new_fd($input->{fd});
1442 elsif ($input->{fh}) {
1443 unless (Scalar::Util::openhandle($input->{fh})) {
1444 $self->_set_error("Handle in fh option not opened");
1447 $io = Imager::IO->new_fh($input->{fh});
1449 elsif ($input->{file}) {
1450 my $fh = new IO::File($input->{file},"w+");
1452 $self->_set_error("Could not open file $input->{file}: $!");
1455 binmode($fh) or die;
1456 $io = io_new_fd(fileno($fh));
1459 elsif ($input->{data}) {
1460 $io = io_new_bufchain();
1462 elsif ($input->{callback} || $input->{writecb}) {
1463 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1466 $io = io_new_cb($input->{callback} || $input->{writecb},
1468 $input->{seekcb}, $input->{closecb});
1471 $self->_set_error("file/fd/fh/data/callback parameter missing");
1475 unless ($buffered) {
1476 $io->set_buffered(0);
1479 return ($io, @extras);
1482 # Read an image from file
1488 if (defined($self->{IMG})) {
1489 # let IIM_DESTROY do the destruction, since the image may be
1490 # referenced from elsewhere
1491 #i_img_destroy($self->{IMG});
1492 undef($self->{IMG});
1495 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1497 my $type = $input{'type'};
1499 $type = i_test_format_probe($IO, -1);
1502 if ($input{file} && !$type) {
1504 $type = $FORMATGUESS->($input{file});
1508 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1509 $input{file} and $msg .= " or file name";
1510 $self->_set_error($msg);
1514 _reader_autoload($type);
1516 if ($readers{$type} && $readers{$type}{single}) {
1517 return $readers{$type}{single}->($self, $IO, %input);
1520 unless ($formats_low{$type}) {
1521 my $read_types = join ', ', sort Imager->read_types();
1522 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1526 my $allow_incomplete = $input{allow_incomplete};
1527 defined $allow_incomplete or $allow_incomplete = 0;
1529 if ( $type eq 'pnm' ) {
1530 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1531 if ( !defined($self->{IMG}) ) {
1532 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1535 $self->{DEBUG} && print "loading a pnm file\n";
1539 if ( $type eq 'bmp' ) {
1540 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1541 if ( !defined($self->{IMG}) ) {
1542 $self->{ERRSTR}=$self->_error_as_msg();
1545 $self->{DEBUG} && print "loading a bmp file\n";
1548 if ( $type eq 'tga' ) {
1549 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1550 if ( !defined($self->{IMG}) ) {
1551 $self->{ERRSTR}=$self->_error_as_msg();
1554 $self->{DEBUG} && print "loading a tga file\n";
1557 if ( $type eq 'raw' ) {
1558 unless ( $input{xsize} && $input{ysize} ) {
1559 $self->_set_error('missing xsize or ysize parameter for raw');
1563 my $interleave = _first($input{raw_interleave}, $input{interleave});
1564 unless (defined $interleave) {
1565 my @caller = caller;
1566 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1569 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1570 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1572 $self->{IMG} = i_readraw_wiol( $IO,
1578 if ( !defined($self->{IMG}) ) {
1579 $self->{ERRSTR}=$self->_error_as_msg();
1582 $self->{DEBUG} && print "loading a raw file\n";
1588 sub register_reader {
1589 my ($class, %opts) = @_;
1592 or die "register_reader called with no type parameter\n";
1594 my $type = $opts{type};
1596 defined $opts{single} || defined $opts{multiple}
1597 or die "register_reader called with no single or multiple parameter\n";
1599 $readers{$type} = { };
1600 if ($opts{single}) {
1601 $readers{$type}{single} = $opts{single};
1603 if ($opts{multiple}) {
1604 $readers{$type}{multiple} = $opts{multiple};
1610 sub register_writer {
1611 my ($class, %opts) = @_;
1614 or die "register_writer called with no type parameter\n";
1616 my $type = $opts{type};
1618 defined $opts{single} || defined $opts{multiple}
1619 or die "register_writer called with no single or multiple parameter\n";
1621 $writers{$type} = { };
1622 if ($opts{single}) {
1623 $writers{$type}{single} = $opts{single};
1625 if ($opts{multiple}) {
1626 $writers{$type}{multiple} = $opts{multiple};
1637 grep($file_formats{$_}, keys %formats),
1638 qw(ico sgi), # formats not handled directly, but supplied with Imager
1649 grep($file_formats{$_}, keys %formats),
1650 qw(ico sgi), # formats not handled directly, but supplied with Imager
1657 my ($file, $error) = @_;
1659 if ($attempted_to_load{$file}) {
1660 if ($file_load_errors{$file}) {
1661 $$error = $file_load_errors{$file};
1669 local $SIG{__DIE__};
1672 pop @INC if $INC[-1] eq '.';
1673 ++$attempted_to_load{$file};
1681 my $work = $@ || "Unknown error";
1683 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1684 $work =~ s/\n/\\n/g;
1685 $work =~ s/\s*\.?\z/ loading $file/;
1686 $file_load_errors{$file} = $work;
1693 # probes for an Imager::File::whatever module
1694 sub _reader_autoload {
1697 return if $formats_low{$type} || $readers{$type};
1699 return unless $type =~ /^\w+$/;
1701 my $file = "Imager/File/\U$type\E.pm";
1704 my $loaded = _load_file($file, \$error);
1705 if (!$loaded && $error =~ /^Can't locate /) {
1706 my $filer = "Imager/File/\U$type\EReader.pm";
1707 $loaded = _load_file($filer, \$error);
1708 if ($error =~ /^Can't locate /) {
1709 $error = "Can't locate $file or $filer";
1713 $reader_load_errors{$type} = $error;
1717 # probes for an Imager::File::whatever module
1718 sub _writer_autoload {
1721 return if $formats_low{$type} || $writers{$type};
1723 return unless $type =~ /^\w+$/;
1725 my $file = "Imager/File/\U$type\E.pm";
1728 my $loaded = _load_file($file, \$error);
1729 if (!$loaded && $error =~ /^Can't locate /) {
1730 my $filew = "Imager/File/\U$type\EWriter.pm";
1731 $loaded = _load_file($filew, \$error);
1732 if ($error =~ /^Can't locate /) {
1733 $error = "Can't locate $file or $filew";
1737 $writer_load_errors{$type} = $error;
1741 sub _fix_gif_positions {
1742 my ($opts, $opt, $msg, @imgs) = @_;
1744 my $positions = $opts->{'gif_positions'};
1746 for my $pos (@$positions) {
1747 my ($x, $y) = @$pos;
1748 my $img = $imgs[$index++];
1749 $img->settag(name=>'gif_left', value=>$x);
1750 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1752 $$msg .= "replaced with the gif_left and gif_top tags";
1757 gif_each_palette=>'gif_local_map',
1758 interlace => 'gif_interlace',
1759 gif_delays => 'gif_delay',
1760 gif_positions => \&_fix_gif_positions,
1761 gif_loop_count => 'gif_loop',
1764 # options that should be converted to colors
1765 my %color_opts = map { $_ => 1 } qw/i_background/;
1768 my ($self, $opts, $prefix, @imgs) = @_;
1770 for my $opt (keys %$opts) {
1772 if ($obsolete_opts{$opt}) {
1773 my $new = $obsolete_opts{$opt};
1774 my $msg = "Obsolete option $opt ";
1776 $new->($opts, $opt, \$msg, @imgs);
1779 $msg .= "replaced with the $new tag ";
1782 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1783 warn $msg if $warn_obsolete && $^W;
1785 next unless $tagname =~ /^\Q$prefix/;
1786 my $value = $opts->{$opt};
1787 if ($color_opts{$opt}) {
1788 $value = _color($value);
1790 $self->_set_error($Imager::ERRSTR);
1795 if (UNIVERSAL::isa($value, "Imager::Color")) {
1796 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1797 for my $img (@imgs) {
1798 $img->settag(name=>$tagname, value=>$tag);
1801 elsif (ref($value) eq 'ARRAY') {
1802 for my $i (0..$#$value) {
1803 my $val = $value->[$i];
1805 if (UNIVERSAL::isa($val, "Imager::Color")) {
1806 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1808 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1811 $self->_set_error("Unknown reference type " . ref($value) .
1812 " supplied in array for $opt");
1818 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1823 $self->_set_error("Unknown reference type " . ref($value) .
1824 " supplied for $opt");
1829 # set it as a tag for every image
1830 for my $img (@imgs) {
1831 $img->settag(name=>$tagname, value=>$value);
1839 # Write an image to file
1842 my %input=(jpegquality=>75,
1852 $self->_valid_image("write")
1855 $self->_set_opts(\%input, "i_", $self)
1858 my $type = $input{'type'};
1859 if (!$type and $input{file}) {
1860 $type = $FORMATGUESS->($input{file});
1863 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1867 _writer_autoload($type);
1870 if ($writers{$type} && $writers{$type}{single}) {
1871 ($IO, $fh) = $self->_get_writer_io(\%input)
1874 $writers{$type}{single}->($self, $IO, %input, type => $type)
1878 if (!$formats_low{$type}) {
1879 my $write_types = join ', ', sort Imager->write_types();
1880 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1884 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1887 if ( $type eq 'pnm' ) {
1888 $self->_set_opts(\%input, "pnm_", $self)
1890 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1891 $self->{ERRSTR} = $self->_error_as_msg();
1894 $self->{DEBUG} && print "writing a pnm file\n";
1896 elsif ( $type eq 'raw' ) {
1897 $self->_set_opts(\%input, "raw_", $self)
1899 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1900 $self->{ERRSTR} = $self->_error_as_msg();
1903 $self->{DEBUG} && print "writing a raw file\n";
1905 elsif ( $type eq 'bmp' ) {
1906 $self->_set_opts(\%input, "bmp_", $self)
1908 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1909 $self->{ERRSTR} = $self->_error_as_msg;
1912 $self->{DEBUG} && print "writing a bmp file\n";
1914 elsif ( $type eq 'tga' ) {
1915 $self->_set_opts(\%input, "tga_", $self)
1918 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1919 $self->{ERRSTR}=$self->_error_as_msg();
1922 $self->{DEBUG} && print "writing a tga file\n";
1926 if (exists $input{'data'}) {
1927 my $data = io_slurp($IO);
1929 $self->{ERRSTR}='Could not slurp from buffer';
1932 ${$input{data}} = $data;
1938 my ($class, $opts, @images) = @_;
1940 my $type = $opts->{type};
1942 if (!$type && $opts->{'file'}) {
1943 $type = $FORMATGUESS->($opts->{'file'});
1946 $class->_set_error('type parameter missing and not possible to guess from extension');
1949 # translate to ImgRaw
1951 for my $img (@images) {
1952 unless ($img->_valid_image("write_multi")) {
1953 $class->_set_error($img->errstr . " (image $index)");
1958 $class->_set_opts($opts, "i_", @images)
1960 my @work = map $_->{IMG}, @images;
1962 _writer_autoload($type);
1965 if ($writers{$type} && $writers{$type}{multiple}) {
1966 ($IO, $file) = $class->_get_writer_io($opts, $type)
1969 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1973 if (!$formats{$type}) {
1974 my $write_types = join ', ', sort Imager->write_types();
1975 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1979 ($IO, $file) = $class->_get_writer_io($opts, $type)
1982 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1986 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1991 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1997 if (exists $opts->{'data'}) {
1998 my $data = io_slurp($IO);
2000 Imager->_set_error('Could not slurp from buffer');
2003 ${$opts->{data}} = $data;
2008 # read multiple images from a file
2010 my ($class, %opts) = @_;
2012 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2015 my $type = $opts{'type'};
2017 $type = i_test_format_probe($IO, -1);
2020 if ($opts{file} && !$type) {
2022 $type = $FORMATGUESS->($opts{file});
2026 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2027 $opts{file} and $msg .= " or file name";
2028 Imager->_set_error($msg);
2032 _reader_autoload($type);
2034 if ($readers{$type} && $readers{$type}{multiple}) {
2035 return $readers{$type}{multiple}->($IO, %opts);
2038 unless ($formats{$type}) {
2039 my $read_types = join ', ', sort Imager->read_types();
2040 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2045 if ($type eq 'pnm') {
2046 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2049 my $img = Imager->new;
2050 if ($img->read(%opts, io => $IO, type => $type)) {
2053 Imager->_set_error($img->errstr);
2058 $ERRSTR = _error_as_msg();
2062 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2066 # Destroy an Imager object
2070 # delete $instances{$self};
2071 if (defined($self->{IMG})) {
2072 # the following is now handled by the XS DESTROY method for
2073 # Imager::ImgRaw object
2074 # Re-enabling this will break virtual images
2075 # tested for in t/t020masked.t
2076 # i_img_destroy($self->{IMG});
2077 undef($self->{IMG});
2079 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2083 # Perform an inplace filter of an image
2084 # that is the image will be overwritten with the data
2091 $self->_valid_image("filter")
2094 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2096 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2097 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2100 if ($filters{$input{'type'}}{names}) {
2101 my $names = $filters{$input{'type'}}{names};
2102 for my $name (keys %$names) {
2103 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2104 $input{$name} = $names->{$name}{$input{$name}};
2108 if (defined($filters{$input{'type'}}{defaults})) {
2109 %hsh=( image => $self->{IMG},
2111 %{$filters{$input{'type'}}{defaults}},
2114 %hsh=( image => $self->{IMG},
2119 my @cs=@{$filters{$input{'type'}}{callseq}};
2122 if (!defined($hsh{$_})) {
2123 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2128 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2129 &{$filters{$input{'type'}}{callsub}}(%hsh);
2132 chomp($self->{ERRSTR} = $@);
2138 $self->{DEBUG} && print "callseq is: @cs\n";
2139 $self->{DEBUG} && print "matching callseq is: @b\n";
2144 sub register_filter {
2146 my %hsh = ( defaults => {}, @_ );
2149 or die "register_filter() with no type\n";
2150 defined $hsh{callsub}
2151 or die "register_filter() with no callsub\n";
2152 defined $hsh{callseq}
2153 or die "register_filter() with no callseq\n";
2155 exists $filters{$hsh{type}}
2158 $filters{$hsh{type}} = \%hsh;
2163 sub scale_calculate {
2166 my %opts = ('type'=>'max', @_);
2168 # none of these should be references
2169 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2170 if (defined $opts{$name} && ref $opts{$name}) {
2171 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2176 my ($x_scale, $y_scale);
2177 my $width = $opts{width};
2178 my $height = $opts{height};
2180 defined $width or $width = $self->getwidth;
2181 defined $height or $height = $self->getheight;
2184 unless (defined $width && defined $height) {
2185 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2190 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2191 $x_scale = $opts{'xscalefactor'};
2192 $y_scale = $opts{'yscalefactor'};
2194 elsif ($opts{'xscalefactor'}) {
2195 $x_scale = $opts{'xscalefactor'};
2196 $y_scale = $opts{'scalefactor'} || $x_scale;
2198 elsif ($opts{'yscalefactor'}) {
2199 $y_scale = $opts{'yscalefactor'};
2200 $x_scale = $opts{'scalefactor'} || $y_scale;
2203 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2206 # work out the scaling
2207 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2208 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2209 $opts{ypixels} / $height );
2210 if ($opts{'type'} eq 'min') {
2211 $x_scale = $y_scale = _min($xpix,$ypix);
2213 elsif ($opts{'type'} eq 'max') {
2214 $x_scale = $y_scale = _max($xpix,$ypix);
2216 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2221 $self->_set_error('invalid value for type parameter');
2224 } elsif ($opts{xpixels}) {
2225 $x_scale = $y_scale = $opts{xpixels} / $width;
2227 elsif ($opts{ypixels}) {
2228 $x_scale = $y_scale = $opts{ypixels}/$height;
2230 elsif ($opts{constrain} && ref $opts{constrain}
2231 && $opts{constrain}->can('constrain')) {
2232 # we've been passed an Image::Math::Constrain object or something
2233 # that looks like one
2235 (undef, undef, $scalefactor)
2236 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2237 unless ($scalefactor) {
2238 $self->_set_error('constrain method failed on constrain parameter');
2241 $x_scale = $y_scale = $scalefactor;
2244 my $new_width = int($x_scale * $width + 0.5);
2245 $new_width > 0 or $new_width = 1;
2246 my $new_height = int($y_scale * $height + 0.5);
2247 $new_height > 0 or $new_height = 1;
2249 return ($x_scale, $y_scale, $new_width, $new_height);
2253 # Scale an image to requested size and return the scaled version
2257 my %opts = (qtype=>'normal' ,@_);
2258 my $img = Imager->new();
2259 my $tmp = Imager->new();
2261 unless (defined wantarray) {
2262 my @caller = caller;
2263 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2267 $self->_valid_image("scale")
2270 my ($x_scale, $y_scale, $new_width, $new_height) =
2271 $self->scale_calculate(%opts)
2274 if ($opts{qtype} eq 'normal') {
2275 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2276 if ( !defined($tmp->{IMG}) ) {
2277 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2280 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2281 if ( !defined($img->{IMG}) ) {
2282 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2288 elsif ($opts{'qtype'} eq 'preview') {
2289 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2290 if ( !defined($img->{IMG}) ) {
2291 $self->{ERRSTR}='unable to scale image';
2296 elsif ($opts{'qtype'} eq 'mixing') {
2297 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2298 unless ($img->{IMG}) {
2299 $self->_set_error(Imager->_error_as_msg);
2305 $self->_set_error('invalid value for qtype parameter');
2310 # Scales only along the X axis
2314 my %opts = ( scalefactor=>0.5, @_ );
2316 unless (defined wantarray) {
2317 my @caller = caller;
2318 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2322 $self->_valid_image("scaleX")
2325 my $img = Imager->new();
2327 my $scalefactor = $opts{scalefactor};
2329 if ($opts{pixels}) {
2330 $scalefactor = $opts{pixels} / $self->getwidth();
2333 unless ($self->{IMG}) {
2334 $self->{ERRSTR}='empty input image';
2338 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2340 if ( !defined($img->{IMG}) ) {
2341 $self->{ERRSTR} = 'unable to scale image';
2348 # Scales only along the Y axis
2352 my %opts = ( scalefactor => 0.5, @_ );
2354 unless (defined wantarray) {
2355 my @caller = caller;
2356 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2360 $self->_valid_image("scaleY")
2363 my $img = Imager->new();
2365 my $scalefactor = $opts{scalefactor};
2367 if ($opts{pixels}) {
2368 $scalefactor = $opts{pixels} / $self->getheight();
2371 unless ($self->{IMG}) {
2372 $self->{ERRSTR} = 'empty input image';
2375 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2377 if ( !defined($img->{IMG}) ) {
2378 $self->{ERRSTR} = 'unable to scale image';
2385 # Transform returns a spatial transformation of the input image
2386 # this moves pixels to a new location in the returned image.
2387 # NOTE - should make a utility function to check transforms for
2393 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2395 # print Dumper(\%opts);
2398 $self->_valid_image("transform")
2401 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2405 pop @INC if $INC[-1] eq '.';
2406 eval ("use Affix::Infix2Postfix;");
2410 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2413 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2414 {op=>'-',trans=>'Sub'},
2415 {op=>'*',trans=>'Mult'},
2416 {op=>'/',trans=>'Div'},
2417 {op=>'-','type'=>'unary',trans=>'u-'},
2419 {op=>'func','type'=>'unary'}],
2420 'grouping'=>[qw( \( \) )],
2421 'func'=>[qw( sin cos )],
2426 @xt=$I2P->translate($opts{'xexpr'});
2427 @yt=$I2P->translate($opts{'yexpr'});
2429 $numre=$I2P->{'numre'};
2432 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2433 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2434 @{$opts{'parm'}}=@pt;
2437 # print Dumper(\%opts);
2439 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2440 $self->{ERRSTR}='transform: no xopcodes given.';
2444 @op=@{$opts{'xopcodes'}};
2446 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2447 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2450 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2456 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2457 $self->{ERRSTR}='transform: no yopcodes given.';
2461 @op=@{$opts{'yopcodes'}};
2463 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2464 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2467 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2472 if ( !exists $opts{'parm'}) {
2473 $self->{ERRSTR}='transform: no parameter arg given.';
2477 # print Dumper(\@ropx);
2478 # print Dumper(\@ropy);
2479 # print Dumper(\@ropy);
2481 my $img = Imager->new();
2482 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2483 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2489 my ($opts, @imgs) = @_;
2491 require "Imager/Expr.pm";
2493 $opts->{variables} = [ qw(x y) ];
2494 my ($width, $height) = @{$opts}{qw(width height)};
2497 for my $img (@imgs) {
2498 unless ($img->_valid_image("transform2")) {
2499 Imager->_set_error($img->errstr . " (input image $index)");
2505 $width ||= $imgs[0]->getwidth();
2506 $height ||= $imgs[0]->getheight();
2508 for my $img (@imgs) {
2509 $opts->{constants}{"w$img_num"} = $img->getwidth();
2510 $opts->{constants}{"h$img_num"} = $img->getheight();
2511 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2512 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2517 $opts->{constants}{w} = $width;
2518 $opts->{constants}{cx} = $width/2;
2521 $Imager::ERRSTR = "No width supplied";
2525 $opts->{constants}{h} = $height;
2526 $opts->{constants}{cy} = $height/2;
2529 $Imager::ERRSTR = "No height supplied";
2532 my $code = Imager::Expr->new($opts);
2534 $Imager::ERRSTR = Imager::Expr::error();
2537 my $channels = $opts->{channels} || 3;
2538 unless ($channels >= 1 && $channels <= 4) {
2539 return Imager->_set_error("channels must be an integer between 1 and 4");
2542 my $img = Imager->new();
2543 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2544 $channels, $code->code(),
2545 $code->nregs(), $code->cregs(),
2546 [ map { $_->{IMG} } @imgs ]);
2547 if (!defined $img->{IMG}) {
2548 $Imager::ERRSTR = Imager->_error_as_msg();
2559 $self->_valid_image("rubthrough")
2562 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2563 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2567 %opts = (src_minx => 0,
2569 src_maxx => $opts{src}->getwidth(),
2570 src_maxy => $opts{src}->getheight(),
2574 defined $tx or $tx = $opts{left};
2575 defined $tx or $tx = 0;
2578 defined $ty or $ty = $opts{top};
2579 defined $ty or $ty = 0;
2581 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2582 $opts{src_minx}, $opts{src_miny},
2583 $opts{src_maxx}, $opts{src_maxy})) {
2584 $self->_set_error($self->_error_as_msg());
2601 $self->_valid_image("compose")
2604 unless ($opts{src}) {
2605 $self->_set_error("compose: src parameter missing");
2609 unless ($opts{src}->_valid_image("compose")) {
2610 $self->_set_error($opts{src}->errstr . " (for src)");
2613 my $src = $opts{src};
2615 my $left = $opts{left};
2616 defined $left or $left = $opts{tx};
2617 defined $left or $left = 0;
2619 my $top = $opts{top};
2620 defined $top or $top = $opts{ty};
2621 defined $top or $top = 0;
2623 my $src_left = $opts{src_left};
2624 defined $src_left or $src_left = $opts{src_minx};
2625 defined $src_left or $src_left = 0;
2627 my $src_top = $opts{src_top};
2628 defined $src_top or $src_top = $opts{src_miny};
2629 defined $src_top or $src_top = 0;
2631 my $width = $opts{width};
2632 if (!defined $width && defined $opts{src_maxx}) {
2633 $width = $opts{src_maxx} - $src_left;
2635 defined $width or $width = $src->getwidth() - $src_left;
2637 my $height = $opts{height};
2638 if (!defined $height && defined $opts{src_maxy}) {
2639 $height = $opts{src_maxy} - $src_top;
2641 defined $height or $height = $src->getheight() - $src_top;
2643 my $combine = $self->_combine($opts{combine}, 'normal');
2646 unless ($opts{mask}->_valid_image("compose")) {
2647 $self->_set_error($opts{mask}->errstr . " (for mask)");
2651 my $mask_left = $opts{mask_left};
2652 defined $mask_left or $mask_left = $opts{mask_minx};
2653 defined $mask_left or $mask_left = 0;
2655 my $mask_top = $opts{mask_top};
2656 defined $mask_top or $mask_top = $opts{mask_miny};
2657 defined $mask_top or $mask_top = 0;
2659 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2660 $left, $top, $src_left, $src_top,
2661 $mask_left, $mask_top, $width, $height,
2662 $combine, $opts{opacity})) {
2663 $self->_set_error(Imager->_error_as_msg);
2668 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2669 $width, $height, $combine, $opts{opacity})) {
2670 $self->_set_error(Imager->_error_as_msg);
2682 $self->_valid_image("flip")
2685 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2687 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2688 $dir = $xlate{$opts{'dir'}};
2689 return $self if i_flipxy($self->{IMG}, $dir);
2697 unless (defined wantarray) {
2698 my @caller = caller;
2699 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2703 $self->_valid_image("rotate")
2706 if (defined $opts{right}) {
2707 my $degrees = $opts{right};
2709 $degrees += 360 * int(((-$degrees)+360)/360);
2711 $degrees = $degrees % 360;
2712 if ($degrees == 0) {
2713 return $self->copy();
2715 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2716 my $result = Imager->new();
2717 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2721 $self->{ERRSTR} = $self->_error_as_msg();
2726 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2730 elsif (defined $opts{radians} || defined $opts{degrees}) {
2731 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2733 my $back = $opts{back};
2734 my $result = Imager->new;
2736 $back = _color($back);
2738 $self->_set_error(Imager->errstr);
2742 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2745 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2747 if ($result->{IMG}) {
2751 $self->{ERRSTR} = $self->_error_as_msg();
2756 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2761 sub matrix_transform {
2765 $self->_valid_image("matrix_transform")
2768 unless (defined wantarray) {
2769 my @caller = caller;
2770 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2774 if ($opts{matrix}) {
2775 my $xsize = $opts{xsize} || $self->getwidth;
2776 my $ysize = $opts{ysize} || $self->getheight;
2778 my $result = Imager->new;
2780 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2781 $opts{matrix}, $opts{back})
2785 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2793 $self->{ERRSTR} = "matrix parameter required";
2799 *yatf = \&matrix_transform;
2801 # These two are supported for legacy code only
2804 return Imager::Color->new(@_);
2808 return Imager::Color::set(@_);
2811 # Draws a box between the specified corner points.
2814 my $raw = $self->{IMG};
2816 $self->_valid_image("box")
2821 my ($xmin, $ymin, $xmax, $ymax);
2822 if (exists $opts{'box'}) {
2823 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2824 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2825 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2826 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2829 defined($xmin = $opts{xmin}) or $xmin = 0;
2830 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2831 defined($ymin = $opts{ymin}) or $ymin = 0;
2832 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2835 if ($opts{filled}) {
2836 my $color = $opts{'color'};
2838 if (defined $color) {
2839 unless (_is_color_object($color)) {
2840 $color = _color($color);
2842 $self->{ERRSTR} = $Imager::ERRSTR;
2848 $color = i_color_new(255,255,255,255);
2851 if ($color->isa("Imager::Color")) {
2852 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2855 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2858 elsif ($opts{fill}) {
2859 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2860 # assume it's a hash ref
2861 require 'Imager/Fill.pm';
2862 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2863 $self->{ERRSTR} = $Imager::ERRSTR;
2867 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2870 my $color = $opts{'color'};
2871 if (defined $color) {
2872 unless (_is_color_object($color)) {
2873 $color = _color($color);
2875 $self->{ERRSTR} = $Imager::ERRSTR;
2881 $color = i_color_new(255, 255, 255, 255);
2884 $self->{ERRSTR} = $Imager::ERRSTR;
2887 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2896 $self->_valid_image("arc")
2899 my $dflcl= [ 255, 255, 255, 255];
2904 'r'=>_min($self->getwidth(),$self->getheight())/3,
2905 'x'=>$self->getwidth()/2,
2906 'y'=>$self->getheight()/2,
2913 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2914 # assume it's a hash ref
2915 require 'Imager/Fill.pm';
2916 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2917 $self->{ERRSTR} = $Imager::ERRSTR;
2921 if ($opts{d1} == 0 && $opts{d2} == 361) {
2922 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2926 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2927 $opts{'d2'}, $opts{fill}{fill});
2930 elsif ($opts{filled}) {
2931 my $color = _color($opts{'color'});
2933 $self->{ERRSTR} = $Imager::ERRSTR;
2936 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2937 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2941 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2942 $opts{'d1'}, $opts{'d2'}, $color);
2946 my $color = _color($opts{'color'});
2947 if ($opts{d2} - $opts{d1} >= 360) {
2948 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2951 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2957 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2958 # assume it's a hash ref
2959 require 'Imager/Fill.pm';
2960 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2961 $self->{ERRSTR} = $Imager::ERRSTR;
2965 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2966 $opts{'d2'}, $opts{fill}{fill});
2969 my $color = _color($opts{'color'});
2971 $self->{ERRSTR} = $Imager::ERRSTR;
2974 if ($opts{filled}) {
2975 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2976 $opts{'d1'}, $opts{'d2'}, $color);
2979 if ($opts{d1} == 0 && $opts{d2} == 361) {
2980 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2983 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2989 $self->_set_error($self->_error_as_msg);
2996 # Draws a line from one point to the other
2997 # the endpoint is set if the endp parameter is set which it is by default.
2998 # to turn of the endpoint being set use endp=>0 when calling line.
3002 my $dflcl=i_color_new(0,0,0,0);
3003 my %opts=(color=>$dflcl,
3007 $self->_valid_image("line")
3010 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
3011 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
3013 my $color = _color($opts{'color'});
3015 $self->{ERRSTR} = $Imager::ERRSTR;
3019 $opts{antialias} = $opts{aa} if defined $opts{aa};
3020 if ($opts{antialias}) {
3021 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3022 $color, $opts{endp});
3024 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3025 $color, $opts{endp});
3030 # Draws a line between an ordered set of points - It more or less just transforms this
3031 # into a list of lines.
3035 my ($pt,$ls,@points);
3036 my $dflcl=i_color_new(0,0,0,0);
3037 my %opts=(color=>$dflcl,@_);
3039 $self->_valid_image("polyline")
3042 if (exists($opts{points})) { @points=@{$opts{points}}; }
3043 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3044 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3047 # print Dumper(\@points);
3049 my $color = _color($opts{'color'});
3051 $self->{ERRSTR} = $Imager::ERRSTR;
3054 $opts{antialias} = $opts{aa} if defined $opts{aa};
3055 if ($opts{antialias}) {
3058 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3065 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3075 my ($pt,$ls,@points);
3076 my $dflcl = i_color_new(0,0,0,0);
3077 my %opts = (color=>$dflcl, @_);
3079 $self->_valid_image("polygon")
3082 if (exists($opts{points})) {
3083 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3084 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3087 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3088 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3091 my $mode = _first($opts{mode}, 0);
3093 if ($opts{'fill'}) {
3094 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3095 # assume it's a hash ref
3096 require 'Imager/Fill.pm';
3097 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3098 $self->{ERRSTR} = $Imager::ERRSTR;
3102 i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3103 $mode, $opts{'fill'}{'fill'});
3106 my $color = _color($opts{'color'});
3108 $self->{ERRSTR} = $Imager::ERRSTR;
3111 i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color);
3118 my ($self, %opts) = @_;
3120 $self->_valid_image("polypolygon")
3123 my $points = $opts{points};
3125 or return $self->_set_error("polypolygon: missing required points");
3127 my $mode = _first($opts{mode}, "evenodd");
3129 if ($opts{filled}) {
3130 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3131 or return $self->_set_error($Imager::ERRSTR);
3133 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3134 or return $self->_set_error($self->_error_as_msg);
3136 elsif ($opts{fill}) {
3137 my $fill = $opts{fill};
3138 $self->_valid_fill($fill, "polypolygon")
3141 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3142 or return $self->_set_error($self->_error_as_msg);
3145 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3146 or return $self->_set_error($Imager::ERRSTR);
3148 my $rimg = $self->{IMG};
3150 if (_first($opts{aa}, 1)) {
3151 for my $poly (@$points) {
3152 my $xp = $poly->[0];
3153 my $yp = $poly->[1];
3154 for my $i (0 .. $#$xp - 1) {
3155 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3158 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3163 for my $poly (@$points) {
3164 my $xp = $poly->[0];
3165 my $yp = $poly->[1];
3166 for my $i (0 .. $#$xp - 1) {
3167 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3170 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3179 # this the multipoint bezier curve
3180 # this is here more for testing that actual usage since
3181 # this is not a good algorithm. Usually the curve would be
3182 # broken into smaller segments and each done individually.
3186 my ($pt,$ls,@points);
3187 my $dflcl=i_color_new(0,0,0,0);
3188 my %opts=(color=>$dflcl,@_);
3190 $self->_valid_image("polybezier")
3193 if (exists $opts{points}) {
3194 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3195 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3198 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3199 $self->{ERRSTR}='Missing or invalid points.';
3203 my $color = _color($opts{'color'});
3205 $self->{ERRSTR} = $Imager::ERRSTR;
3208 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3214 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3217 $self->_valid_image("flood_fill")
3220 unless (exists $opts{'x'} && exists $opts{'y'}) {
3221 $self->{ERRSTR} = "missing seed x and y parameters";
3225 if ($opts{border}) {
3226 my $border = _color($opts{border});
3228 $self->_set_error($Imager::ERRSTR);
3232 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3233 # assume it's a hash ref
3234 require Imager::Fill;
3235 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3236 $self->{ERRSTR} = $Imager::ERRSTR;
3240 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3241 $opts{fill}{fill}, $border);
3244 my $color = _color($opts{'color'});
3246 $self->{ERRSTR} = $Imager::ERRSTR;
3249 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3256 $self->{ERRSTR} = $self->_error_as_msg();
3262 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3263 # assume it's a hash ref
3264 require 'Imager/Fill.pm';
3265 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3266 $self->{ERRSTR} = $Imager::ERRSTR;
3270 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3273 my $color = _color($opts{'color'});
3275 $self->{ERRSTR} = $Imager::ERRSTR;
3278 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3284 $self->{ERRSTR} = $self->_error_as_msg();
3291 my ($self, %opts) = @_;
3293 $self->_valid_image("setpixel")
3296 my $color = $opts{color};
3297 unless (defined $color) {
3298 $color = $self->{fg};
3299 defined $color or $color = NC(255, 255, 255);
3302 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3303 unless ($color = _color($color, 'setpixel')) {
3304 $self->_set_error("setpixel: " . Imager->errstr);
3309 unless (exists $opts{'x'} && exists $opts{'y'}) {
3310 $self->_set_error('setpixel: missing x or y parameter');
3316 if (ref $x || ref $y) {
3317 $x = ref $x ? $x : [ $x ];
3318 $y = ref $y ? $y : [ $y ];
3320 $self->_set_error("setpixel: x is a reference to an empty array");
3324 $self->_set_error("setpixel: y is a reference to an empty array");
3328 # make both the same length, replicating the last element
3330 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3333 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3337 if ($color->isa('Imager::Color')) {
3338 for my $i (0..$#$x) {
3339 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3344 for my $i (0..$#$x) {
3345 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3353 if ($color->isa('Imager::Color')) {
3354 i_ppix($self->{IMG}, $x, $y, $color)
3355 and return "0 but true";
3358 i_ppixf($self->{IMG}, $x, $y, $color)
3359 and return "0 but true";
3369 my %opts = ( "type"=>'8bit', @_);
3371 $self->_valid_image("getpixel")
3374 unless (exists $opts{'x'} && exists $opts{'y'}) {
3375 $self->_set_error('getpixel: missing x or y parameter');
3381 my $type = $opts{'type'};
3382 if (ref $x || ref $y) {
3383 $x = ref $x ? $x : [ $x ];
3384 $y = ref $y ? $y : [ $y ];
3386 $self->_set_error("getpixel: x is a reference to an empty array");
3390 $self->_set_error("getpixel: y is a reference to an empty array");
3394 # make both the same length, replicating the last element
3396 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3399 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3403 if ($type eq '8bit') {
3404 for my $i (0..$#$x) {
3405 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3408 elsif ($type eq 'float' || $type eq 'double') {
3409 for my $i (0..$#$x) {
3410 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3414 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3417 return wantarray ? @result : \@result;
3420 if ($type eq '8bit') {
3421 return i_get_pixel($self->{IMG}, $x, $y);
3423 elsif ($type eq 'float' || $type eq 'double') {
3424 return i_gpixf($self->{IMG}, $x, $y);
3427 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3435 my %opts = ( type => '8bit', x=>0, @_);
3437 $self->_valid_image("getscanline")
3440 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3442 unless (defined $opts{'y'}) {
3443 $self->_set_error("missing y parameter");
3447 if ($opts{type} eq '8bit') {
3448 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3451 elsif ($opts{type} eq 'float') {
3452 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3455 elsif ($opts{type} eq 'index') {
3456 unless (i_img_type($self->{IMG})) {
3457 $self->_set_error("type => index only valid on paletted images");
3460 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3464 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3471 my %opts = ( x=>0, @_);
3473 $self->_valid_image("setscanline")
3476 unless (defined $opts{'y'}) {
3477 $self->_set_error("missing y parameter");
3482 if (ref $opts{pixels} && @{$opts{pixels}}) {
3483 # try to guess the type
3484 if ($opts{pixels}[0]->isa('Imager::Color')) {
3485 $opts{type} = '8bit';
3487 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3488 $opts{type} = 'float';
3491 $self->_set_error("missing type parameter and could not guess from pixels");
3497 $opts{type} = '8bit';
3501 if ($opts{type} eq '8bit') {
3502 if (ref $opts{pixels}) {
3503 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3506 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3509 elsif ($opts{type} eq 'float') {
3510 if (ref $opts{pixels}) {
3511 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3514 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3517 elsif ($opts{type} eq 'index') {
3518 if (ref $opts{pixels}) {
3519 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3522 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3526 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3533 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3535 $self->_valid_image("getsamples")
3538 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3540 unless (defined $opts{'y'}) {
3541 $self->_set_error("missing y parameter");
3545 if ($opts{target}) {
3546 my $target = $opts{target};
3547 my $offset = $opts{offset};
3548 if ($opts{type} eq '8bit') {
3549 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3550 $opts{y}, $opts{channels})
3552 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3553 return scalar(@samples);
3555 elsif ($opts{type} eq 'float') {
3556 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3557 $opts{y}, $opts{channels});
3558 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3559 return scalar(@samples);
3561 elsif ($opts{type} =~ /^(\d+)bit$/) {
3565 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3566 $opts{y}, $bits, $target,
3567 $offset, $opts{channels});
3568 unless (defined $count) {
3569 $self->_set_error(Imager->_error_as_msg);
3576 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3581 if ($opts{type} eq '8bit') {
3582 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3583 $opts{y}, $opts{channels});
3585 elsif ($opts{type} eq 'float') {
3586 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3587 $opts{y}, $opts{channels});
3589 elsif ($opts{type} =~ /^(\d+)bit$/) {
3593 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3594 $opts{y}, $bits, \@data, 0, $opts{channels})
3599 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3608 $self->_valid_image("setsamples")
3611 my %opts = ( x => 0, offset => 0 );
3613 # avoid duplicating the data parameter, it may be a large scalar
3615 while ($i < @_ -1) {
3616 if ($_[$i] eq 'data') {
3620 $opts{$_[$i]} = $_[$i+1];
3626 unless(defined $data_index) {
3627 $self->_set_error('setsamples: data parameter missing');
3630 unless (defined $_[$data_index]) {
3631 $self->_set_error('setsamples: data parameter not defined');
3635 my $type = $opts{type};
3636 defined $type or $type = '8bit';
3638 my $width = defined $opts{width} ? $opts{width}
3639 : $self->getwidth() - $opts{x};
3642 if ($type eq '8bit') {
3643 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3644 $_[$data_index], $opts{offset}, $width);
3646 elsif ($type eq 'float') {
3647 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3648 $_[$data_index], $opts{offset}, $width);
3650 elsif ($type =~ /^([0-9]+)bit$/) {
3653 unless (ref $_[$data_index]) {
3654 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3658 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3659 $opts{channels}, $_[$data_index], $opts{offset},
3663 $self->_set_error('setsamples: type parameter invalid');
3667 unless (defined $count) {
3668 $self->_set_error(Imager->_error_as_msg);
3675 # make an identity matrix of the given size
3679 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3680 for my $c (0 .. ($size-1)) {
3681 $matrix->[$c][$c] = 1;
3686 # general function to convert an image
3688 my ($self, %opts) = @_;
3691 $self->_valid_image("convert")
3694 unless (defined wantarray) {
3695 my @caller = caller;
3696 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3700 # the user can either specify a matrix or preset
3701 # the matrix overrides the preset
3702 if (!exists($opts{matrix})) {
3703 unless (exists($opts{preset})) {
3704 $self->{ERRSTR} = "convert() needs a matrix or preset";
3708 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3709 # convert to greyscale, keeping the alpha channel if any
3710 if ($self->getchannels == 3) {
3711 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3713 elsif ($self->getchannels == 4) {
3714 # preserve the alpha channel
3715 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3720 $matrix = _identity($self->getchannels);
3723 elsif ($opts{preset} eq 'noalpha') {
3724 # strip the alpha channel
3725 if ($self->getchannels == 2 or $self->getchannels == 4) {
3726 $matrix = _identity($self->getchannels);
3727 pop(@$matrix); # lose the alpha entry
3730 $matrix = _identity($self->getchannels);
3733 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3735 $matrix = [ [ 1 ] ];
3737 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3738 $matrix = [ [ 0, 1 ] ];
3740 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3741 $matrix = [ [ 0, 0, 1 ] ];
3743 elsif ($opts{preset} eq 'alpha') {
3744 if ($self->getchannels == 2 or $self->getchannels == 4) {
3745 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3748 # the alpha is just 1 <shrug>
3749 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3752 elsif ($opts{preset} eq 'rgb') {
3753 if ($self->getchannels == 1) {
3754 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3756 elsif ($self->getchannels == 2) {
3757 # preserve the alpha channel
3758 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3761 $matrix = _identity($self->getchannels);
3764 elsif ($opts{preset} eq 'addalpha') {
3765 if ($self->getchannels == 1) {
3766 $matrix = _identity(2);
3768 elsif ($self->getchannels == 3) {
3769 $matrix = _identity(4);
3772 $matrix = _identity($self->getchannels);
3776 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3782 $matrix = $opts{matrix};
3785 my $new = Imager->new;
3786 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3787 unless ($new->{IMG}) {
3788 # most likely a bad matrix
3789 i_push_error(0, "convert");
3790 $self->{ERRSTR} = _error_as_msg();
3796 # combine channels from multiple input images, a class method
3798 my ($class, %opts) = @_;
3800 my $src = delete $opts{src};
3802 $class->_set_error("src parameter missing");
3807 for my $img (@$src) {
3808 unless (eval { $img->isa("Imager") }) {
3809 $class->_set_error("src must contain image objects");
3812 unless ($img->_valid_image("combine")) {
3813 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3816 push @imgs, $img->{IMG};
3819 if (my $channels = delete $opts{channels}) {
3820 $result = i_combine(\@imgs, $channels);
3823 $result = i_combine(\@imgs);
3826 $class->_set_error($class->_error_as_msg);
3830 my $img = $class->new;
3831 $img->{IMG} = $result;
3837 # general function to map an image through lookup tables
3840 my ($self, %opts) = @_;
3841 my @chlist = qw( red green blue alpha );
3843 $self->_valid_image("map")
3846 if (!exists($opts{'maps'})) {
3847 # make maps from channel maps
3849 for $chnum (0..$#chlist) {
3850 if (exists $opts{$chlist[$chnum]}) {
3851 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3852 } elsif (exists $opts{'all'}) {
3853 $opts{'maps'}[$chnum] = $opts{'all'};
3857 if ($opts{'maps'} and $self->{IMG}) {
3858 i_map($self->{IMG}, $opts{'maps'} );
3864 my ($self, %opts) = @_;
3866 $self->_valid_image("difference")
3869 defined $opts{mindist} or $opts{mindist} = 0;
3871 defined $opts{other}
3872 or return $self->_set_error("No 'other' parameter supplied");
3873 unless ($opts{other}->_valid_image("difference")) {
3874 $self->_set_error($opts{other}->errstr . " (other image)");
3878 my $result = Imager->new;
3879 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3881 or return $self->_set_error($self->_error_as_msg());
3886 # destructive border - image is shrunk by one pixel all around
3889 my ($self,%opts)=@_;
3890 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3891 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3895 # Get the width of an image
3900 $self->_valid_image("getwidth")
3903 return i_img_get_width($self->{IMG});
3906 # Get the height of an image
3911 $self->_valid_image("getheight")
3914 return i_img_get_height($self->{IMG});
3917 # Get number of channels in an image
3922 $self->_valid_image("getchannels")
3925 return i_img_getchannels($self->{IMG});
3928 my @model_names = qw(unknown gray graya rgb rgba);
3931 my ($self, %opts) = @_;
3933 $self->_valid_image("colormodel")
3936 my $model = i_img_color_model($self->{IMG});
3938 return $opts{numeric} ? $model : $model_names[$model];
3944 $self->_valid_image("colorchannels")
3947 return i_img_color_channels($self->{IMG});
3953 $self->_valid_image("alphachannel")
3956 return scalar(i_img_alpha_channel($self->{IMG}));
3964 $self->_valid_image("getmask")
3967 return i_img_getmask($self->{IMG});
3976 $self->_valid_image("setmask")
3979 unless (defined $opts{mask}) {
3980 $self->_set_error("mask parameter required");
3984 i_img_setmask( $self->{IMG} , $opts{mask} );
3989 # Get number of colors in an image
3993 my %opts=('maxcolors'=>2**30,@_);
3995 $self->_valid_image("getcolorcount")
3998 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3999 return ($rc==-1? undef : $rc);
4002 # Returns a reference to a hash. The keys are colour named (packed) and the
4003 # values are the number of pixels in this colour.
4004 sub getcolorusagehash {
4007 $self->_valid_image("getcolorusagehash")
4010 my %opts = ( maxcolors => 2**30, @_ );
4011 my $max_colors = $opts{maxcolors};
4012 unless (defined $max_colors && $max_colors > 0) {
4013 $self->_set_error('maxcolors must be a positive integer');
4017 my $channels= $self->getchannels;
4018 # We don't want to look at the alpha channel, because some gifs using it
4019 # doesn't define it for every colour (but only for some)
4020 $channels -= 1 if $channels == 2 or $channels == 4;
4022 my $height = $self->getheight;
4023 for my $y (0 .. $height - 1) {
4024 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4025 while (length $colors) {
4026 $color_use{ substr($colors, 0, $channels, '') }++;
4028 keys %color_use > $max_colors
4034 # This will return a ordered array of the colour usage. Kind of the sorted
4035 # version of the values of the hash returned by getcolorusagehash.
4036 # You might want to add safety checks and change the names, etc...
4040 $self->_valid_image("getcolorusage")
4043 my %opts = ( maxcolors => 2**30, @_ );
4044 my $max_colors = $opts{maxcolors};
4045 unless (defined $max_colors && $max_colors > 0) {
4046 $self->_set_error('maxcolors must be a positive integer');
4050 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4053 # draw string to an image
4058 $self->_valid_image("string")
4061 my %input=('x'=>0, 'y'=>0, @_);
4062 defined($input{string}) or $input{string} = $input{text};
4064 unless(defined $input{string}) {
4065 $self->{ERRSTR}="missing required parameter 'string'";
4069 unless($input{font}) {
4070 $self->{ERRSTR}="missing required parameter 'font'";
4074 unless ($input{font}->draw(image=>$self, %input)) {
4086 $self->_valid_image("align_string")
4095 my %input=('x'=>0, 'y'=>0, @_);
4096 defined $input{string}
4097 or $input{string} = $input{text};
4099 unless(exists $input{string}) {
4100 $self->_set_error("missing required parameter 'string'");
4104 unless($input{font}) {
4105 $self->_set_error("missing required parameter 'font'");
4110 unless (@result = $input{font}->align(image=>$img, %input)) {
4114 return wantarray ? @result : $result[0];
4117 my @file_limit_names = qw/width height bytes/;
4119 sub set_file_limits {
4126 @values{@file_limit_names} = (0) x @file_limit_names;
4129 @values{@file_limit_names} = i_get_image_file_limits();
4132 for my $key (keys %values) {
4133 defined $opts{$key} and $values{$key} = $opts{$key};
4136 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4139 sub get_file_limits {
4140 i_get_image_file_limits();
4143 my @check_args = qw(width height channels sample_size);
4145 sub check_file_limits {
4155 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4156 $opts{sample_size} = length(pack("d", 0));
4159 for my $name (@check_args) {
4160 unless (defined $opts{$name}) {
4161 $class->_set_error("check_file_limits: $name must be defined");
4164 unless ($opts{$name} == int($opts{$name})) {
4165 $class->_set_error("check_file_limits: $name must be a positive integer");
4170 my $result = i_int_check_image_file_limits(@opts{@check_args});
4172 $class->_set_error($class->_error_as_msg());
4178 # Shortcuts that can be exported
4180 sub newcolor { Imager::Color->new(@_); }
4181 sub newfont { Imager::Font->new(@_); }
4183 require Imager::Color::Float;
4184 return Imager::Color::Float->new(@_);
4187 *NC=*newcolour=*newcolor;
4194 #### Utility routines
4197 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4201 my ($self, $msg) = @_;
4204 $self->{ERRSTR} = $msg;
4212 # Default guess for the type of an image from extension
4214 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4218 ( map { $_ => $_ } @simple_types ),
4224 pnm => "pnm", # technically wrong, but historically it works in Imager
4237 sub def_guess_type {
4240 my ($ext) = $name =~ /\.([^.]+)$/
4243 my $type = $ext_types{$ext}
4250 return @combine_types;
4253 # get the minimum of a list
4257 for(@_) { if ($_<$mx) { $mx=$_; }}
4261 # get the maximum of a list
4265 for(@_) { if ($_>$mx) { $mx=$_; }}
4269 # string stuff for iptc headers
4273 $str = substr($str,3);
4274 $str =~ s/[\n\r]//g;
4281 # A little hack to parse iptc headers.
4286 my($caption,$photogr,$headln,$credit);
4288 my $str=$self->{IPTCRAW};
4293 @ar=split(/8BIM/,$str);
4298 @sar=split(/\034\002/);
4299 foreach $item (@sar) {
4300 if ($item =~ m/^x/) {
4301 $caption = _clean($item);
4304 if ($item =~ m/^P/) {
4305 $photogr = _clean($item);
4308 if ($item =~ m/^i/) {
4309 $headln = _clean($item);
4312 if ($item =~ m/^n/) {
4313 $credit = _clean($item);
4319 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4323 # Inline added a new argument at the beginning
4327 or die "Only C language supported";
4329 require Imager::ExtUtils;
4330 return Imager::ExtUtils->inline_config;
4333 # threads shouldn't try to close raw Imager objects
4334 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4337 # this serves two purposes:
4338 # - a class method to load the file support modules included with Imager
4339 # (or were included, once the library dependent modules are split out)
4340 # - something for Module::ScanDeps to analyze
4341 # https://rt.cpan.org/Ticket/Display.html?id=6566
4344 pop @INC if $INC[-1] eq '.';
4345 eval { require Imager::File::GIF };
4346 eval { require Imager::File::JPEG };
4347 eval { require Imager::File::PNG };
4348 eval { require Imager::File::SGI };
4349 eval { require Imager::File::TIFF };
4350 eval { require Imager::File::ICO };
4351 eval { require Imager::Font::W32 };
4352 eval { require Imager::Font::FT2 };
4353 eval { require Imager::Font::T1 };
4354 eval { require Imager::Color::Table };
4363 my ($class, $fh) = @_;
4366 return $class->new_cb
4371 return print $fh $_[0];
4375 my $count = CORE::read $fh, $tmp, $_[1];
4383 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4384 unless (CORE::seek $fh, $_[0], $_[1]) {
4395 return $class->_new_perlio($fh);
4399 # backward compatibility for %formats
4400 package Imager::FORMATS;
4402 use constant IX_FORMATS => 0;
4403 use constant IX_LIST => 1;
4404 use constant IX_INDEX => 2;
4405 use constant IX_CLASSES => 3;
4408 my ($class, $formats, $classes) = @_;
4410 return bless [ $formats, [ ], 0, $classes ], $class;
4414 my ($self, $key) = @_;
4416 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4419 my $loaded = Imager::_load_file($file, \$error);
4424 if ($error =~ /^Can't locate /) {
4425 $error = "Can't locate $file";
4427 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4430 $self->[IX_FORMATS]{$key} = $value;
4436 my ($self, $key) = @_;
4438 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4440 $self->[IX_CLASSES]{$key} or return undef;
4442 return $self->_check($key);
4446 die "%Imager::formats is not user monifiable";
4450 die "%Imager::formats is not user monifiable";
4454 die "%Imager::formats is not user monifiable";
4458 my ($self, $key) = @_;
4460 if (exists $self->[IX_FORMATS]{$key}) {
4461 my $value = $self->[IX_FORMATS]{$key}
4466 $self->_check($key) or return 1==0;
4474 unless (@{$self->[IX_LIST]}) {
4476 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4477 keys %{$self->[IX_FORMATS]};
4479 for my $key (keys %{$self->[IX_CLASSES]}) {
4480 $self->[IX_FORMATS]{$key} and next;
4482 and push @{$self->[IX_LIST]}, $key;
4486 @{$self->[IX_LIST]} or return;
4487 $self->[IX_INDEX] = 1;
4488 return $self->[IX_LIST][0];
4494 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4497 return $self->[IX_LIST][$self->[IX_INDEX]++];
4503 return scalar @{$self->[IX_LIST]};
4508 # Below is the stub of documentation for your module. You better edit it!
4512 Imager - Perl extension for Generating 24 bit Images
4522 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4527 # see Imager::Files for information on the read() method
4528 my $img = Imager->new(file=>$file)
4529 or die Imager->errstr();
4531 $file =~ s/\.[^.]*$//;
4533 # Create smaller version
4534 # documented in Imager::Transformations
4535 my $thumb = $img->scale(scalefactor=>.3);
4537 # Autostretch individual channels
4538 $thumb->filter(type=>'autolevels');
4540 # try to save in one of these formats
4543 for $format ( qw( png gif jpeg tiff ppm ) ) {
4544 # Check if given format is supported
4545 if ($Imager::formats{$format}) {
4546 $file.="_low.$format";
4547 print "Storing image as: $file\n";
4548 # documented in Imager::Files
4549 $thumb->write(file=>$file) or
4557 Imager is a module for creating and altering images. It can read and
4558 write various image formats, draw primitive shapes like lines,and
4559 polygons, blend multiple images together in various ways, scale, crop,
4560 render text and more.
4562 =head2 Overview of documentation
4568 Imager - This document - Synopsis, Example, Table of Contents and
4573 L<Imager::Install> - installation notes for Imager.
4577 L<Imager::Tutorial> - a brief introduction to Imager.
4581 L<Imager::Cookbook> - how to do various things with Imager.
4585 L<Imager::ImageTypes> - Basics of constructing image objects with
4586 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4587 8/16/double bits/channel, color maps, channel masks, image tags, color
4588 quantization. Also discusses basic image information methods.
4592 L<Imager::Files> - IO interaction, reading/writing images, format
4597 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4602 L<Imager::Color> - Color specification.
4606 L<Imager::Fill> - Fill pattern specification.
4610 L<Imager::Font> - General font rendering, bounding boxes and font
4615 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4616 blending, pasting, convert and map.
4620 L<Imager::Engines> - Programmable transformations through
4621 C<transform()>, C<transform2()> and C<matrix_transform()>.
4625 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4630 L<Imager::Expr> - Expressions for evaluation engine used by
4635 L<Imager::Matrix2d> - Helper class for affine transformations.
4639 L<Imager::Fountain> - Helper for making gradient profiles.
4643 L<Imager::IO> - Imager I/O abstraction.
4647 L<Imager::API> - using Imager's C API
4651 L<Imager::APIRef> - API function reference
4655 L<Imager::Inline> - using Imager's C API from Inline::C
4659 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4663 L<Imager::Security> - brief security notes.
4667 L<Imager::Threads> - brief information on working with threads.
4671 =head2 Basic Overview
4673 An Image object is created with C<$img = Imager-E<gt>new()>.
4676 $img=Imager->new(); # create empty image
4677 $img->read(file=>'lena.png',type=>'png') or # read image from file
4678 die $img->errstr(); # give an explanation
4679 # if something failed
4681 or if you want to create an empty image:
4683 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4685 This example creates a completely black image of width 400 and height
4688 =head1 ERROR HANDLING
4690 In general a method will return false when it fails, if it does use
4691 the C<errstr()> method to find out why:
4697 Returns the last error message in that context.
4699 If the last error you received was from calling an object method, such
4700 as read, call errstr() as an object method to find out why:
4702 my $image = Imager->new;
4703 $image->read(file => 'somefile.gif')
4704 or die $image->errstr;
4706 If it was a class method then call errstr() as a class method:
4708 my @imgs = Imager->read_multi(file => 'somefile.gif')
4709 or die Imager->errstr;
4711 Note that in some cases object methods are implemented in terms of
4712 class methods so a failing object method may set both.
4716 The C<Imager-E<gt>new> method is described in detail in
4717 L<Imager::ImageTypes>.
4721 Where to find information on methods for Imager class objects.
4723 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4726 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4728 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4731 alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
4732 channel index of the alpha channel (if any).
4734 arc() - L<Imager::Draw/arc()> - draw a filled arc
4736 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4739 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4741 check_file_limits() - L<Imager::Files/check_file_limits()>
4743 circle() - L<Imager::Draw/circle()> - draw a filled circle
4745 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4748 colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
4749 of channels used for color.
4751 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4752 colors in an image's palette (paletted images only)
4754 colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
4757 combine() - L<Imager::Transformations/combine()> - combine channels
4758 from one or more images.
4760 combines() - L<Imager::Draw/combines()> - return a list of the
4761 different combine type keywords
4763 compose() - L<Imager::Transformations/compose()> - compose one image
4766 convert() - L<Imager::Transformations/convert()> - transform the color
4769 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4772 crop() - L<Imager::Transformations/crop()> - extract part of an image
4774 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4775 used to guess the output file format based on the output file name
4777 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4779 difference() - L<Imager::Filters/difference()> - produce a difference
4780 images from two input images.
4782 errstr() - L</errstr()> - the error from the last failed operation.
4784 filter() - L<Imager::Filters/filter()> - image filtering
4786 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4787 palette, if it has one
4789 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4792 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4795 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4796 samples per pixel for an image
4798 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4799 different colors used by an image (works for direct color images)
4801 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4802 palette, if it has one
4804 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4806 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4808 get_file_limits() - L<Imager::Files/get_file_limits()>
4810 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4813 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4815 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4818 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4819 row or partial row of pixels.
4821 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4822 row or partial row of pixels.
4824 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4827 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4830 init() - L<Imager::ImageTypes/init()>
4832 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4833 image write functions should write the image in their bilevel (blank
4834 and white, no gray levels) format
4836 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4839 line() - L<Imager::Draw/line()> - draw an interval
4841 load_plugin() - L<Imager::Filters/load_plugin()>
4843 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4846 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4847 color palette from one or more input images.
4849 map() - L<Imager::Transformations/map()> - remap color
4852 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4854 matrix_transform() - L<Imager::Engines/matrix_transform()>
4856 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4858 NC() - L<Imager::Handy/NC()>
4860 NCF() - L<Imager::Handy/NCF()>
4862 new() - L<Imager::ImageTypes/new()>
4864 newcolor() - L<Imager::Handy/newcolor()>
4866 newcolour() - L<Imager::Handy/newcolour()>
4868 newfont() - L<Imager::Handy/newfont()>
4870 NF() - L<Imager::Handy/NF()>
4872 open() - L<Imager::Files/read()> - an alias for read()
4874 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4878 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4881 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4884 polygon() - L<Imager::Draw/polygon()>
4886 polyline() - L<Imager::Draw/polyline()>
4888 polypolygon() - L<Imager::Draw/polypolygon()>
4890 preload() - L<Imager::Files/preload()>
4892 read() - L<Imager::Files/read()> - read a single image from an image file
4894 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4897 read_types() - L<Imager::Files/read_types()> - list image types Imager
4900 register_filter() - L<Imager::Filters/register_filter()>
4902 register_reader() - L<Imager::Files/register_reader()>
4904 register_writer() - L<Imager::Files/register_writer()>
4906 rotate() - L<Imager::Transformations/rotate()>
4908 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4909 onto an image and use the alpha channel
4911 scale() - L<Imager::Transformations/scale()>
4913 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4915 scaleX() - L<Imager::Transformations/scaleX()>
4917 scaleY() - L<Imager::Transformations/scaleY()>
4919 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4922 set_file_limits() - L<Imager::Files/set_file_limits()>
4924 setmask() - L<Imager::ImageTypes/setmask()>
4926 setpixel() - L<Imager::Draw/setpixel()>
4928 setsamples() - L<Imager::Draw/setsamples()>
4930 setscanline() - L<Imager::Draw/setscanline()>
4932 settag() - L<Imager::ImageTypes/settag()>
4934 string() - L<Imager::Draw/string()> - draw text on an image
4936 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4938 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4940 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4942 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4944 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4945 double per sample image.
4947 transform() - L<Imager::Engines/"transform()">
4949 transform2() - L<Imager::Engines/"transform2()">
4951 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4953 unload_plugin() - L<Imager::Filters/unload_plugin()>
4955 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4958 write() - L<Imager::Files/write()> - write an image to a file
4960 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4963 write_types() - L<Imager::Files/read_types()> - list image types Imager
4966 =head1 CONCEPT INDEX
4968 animated GIF - L<Imager::Files/"Writing an animated GIF">
4970 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4971 L<Imager::ImageTypes/"Common Tags">.
4973 blend - alpha blending one image onto another
4974 L<Imager::Transformations/rubthrough()>
4976 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4978 boxes, drawing - L<Imager::Draw/box()>
4980 changes between image - L<Imager::Filters/"Image Difference">
4982 channels, combine into one image - L<Imager::Transformations/combine()>
4984 color - L<Imager::Color>
4986 color names - L<Imager::Color>, L<Imager::Color::Table>
4988 combine modes - L<Imager::Draw/"Combine Types">
4990 compare images - L<Imager::Filters/"Image Difference">
4992 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4994 convolution - L<Imager::Filters/conv>
4996 cropping - L<Imager::Transformations/crop()>
4998 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5000 C<diff> images - L<Imager::Filters/"Image Difference">
5002 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
5003 L<Imager::Cookbook/"Image spatial resolution">
5005 drawing boxes - L<Imager::Draw/box()>
5007 drawing lines - L<Imager::Draw/line()>
5009 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
5011 error message - L</"ERROR HANDLING">
5013 files, font - L<Imager::Font>
5015 files, image - L<Imager::Files>
5017 filling, types of fill - L<Imager::Fill>
5019 filling, boxes - L<Imager::Draw/box()>
5021 filling, flood fill - L<Imager::Draw/flood_fill()>
5023 flood fill - L<Imager::Draw/flood_fill()>
5025 fonts - L<Imager::Font>
5027 fonts, drawing with - L<Imager::Draw/string()>,
5028 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
5030 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5032 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
5034 fountain fill - L<Imager::Fill/"Fountain fills">,
5035 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5036 L<Imager::Filters/gradgen>
5038 GIF files - L<Imager::Files/"GIF">
5040 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
5042 gradient fill - L<Imager::Fill/"Fountain fills">,
5043 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5044 L<Imager::Filters/gradgen>
5046 gray scale, convert image to - L<Imager::Transformations/convert()>
5048 gaussian blur - L<Imager::Filters/gaussian>
5050 hatch fills - L<Imager::Fill/"Hatched fills">
5052 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5054 invert image - L<Imager::Filters/hardinvert>,
5055 L<Imager::Filters/hardinvertall>
5057 JPEG - L<Imager::Files/"JPEG">
5059 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
5061 lines, drawing - L<Imager::Draw/line()>
5063 matrix - L<Imager::Matrix2d>,
5064 L<Imager::Engines/"Matrix Transformations">,
5065 L<Imager::Font/transform()>
5067 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5069 mosaic - L<Imager::Filters/mosaic>
5071 noise, filter - L<Imager::Filters/noise>
5073 noise, rendered - L<Imager::Filters/turbnoise>,
5074 L<Imager::Filters/radnoise>
5076 paste - L<Imager::Transformations/paste()>,
5077 L<Imager::Transformations/rubthrough()>
5079 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5080 L<Imager::ImageTypes/new()>
5082 =for stopwords posterize
5084 posterize - L<Imager::Filters/postlevels>
5086 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5088 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5090 rectangles, drawing - L<Imager::Draw/box()>
5092 resizing an image - L<Imager::Transformations/scale()>,
5093 L<Imager::Transformations/crop()>
5095 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5097 saving an image - L<Imager::Files>
5099 scaling - L<Imager::Transformations/scale()>
5101 security - L<Imager::Security>
5103 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5105 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
5107 size, image - L<Imager::ImageTypes/getwidth()>,
5108 L<Imager::ImageTypes/getheight()>
5110 size, text - L<Imager::Font/bounding_box()>
5112 tags, image metadata - L<Imager::ImageTypes/"Tags">
5114 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5115 L<Imager::Font::Wrap>
5117 text, wrapping text in an area - L<Imager::Font::Wrap>
5119 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5121 threads - L<Imager::Threads>
5123 tiles, color - L<Imager::Filters/mosaic>
5125 transparent images - L<Imager::ImageTypes>,
5126 L<Imager::Cookbook/"Transparent PNG">
5128 =for stopwords unsharp
5130 unsharp mask - L<Imager::Filters/unsharpmask>
5132 watermark - L<Imager::Filters/watermark>
5134 writing an image to a file - L<Imager::Files>
5138 The best place to get help with Imager is the mailing list.
5140 To subscribe send a message with C<subscribe> in the body to:
5142 imager-devel+request@molar.is
5148 L<http://www.molar.is/en/lists/imager-devel/>
5152 where you can also find the mailing list archive.
5154 You can report bugs by pointing your browser at:
5158 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5162 or by sending an email to:
5166 bug-Imager@rt.cpan.org
5170 Please remember to include the versions of Imager, perl, supporting
5171 libraries, and any relevant code. If you have specific images that
5172 cause the problems, please include those too.
5174 If you don't want to publish your email address on a mailing list you
5175 can use CPAN::Forum:
5177 http://www.cpanforum.com/dist/Imager
5179 You will need to register to post.
5181 =head1 CONTRIBUTING TO IMAGER
5187 If you like or dislike Imager, you can add a public review of Imager
5190 http://cpanratings.perl.org/dist/Imager
5192 =for stopwords Bitcard
5194 This requires a Bitcard account (http://www.bitcard.org).
5196 You can also send email to the maintainer below.
5198 If you send me a bug report via email, it will be copied to Request
5203 I accept patches, preferably against the master branch in git. Please
5204 include an explanation of the reason for why the patch is needed or
5207 Your patch should include regression tests where possible, otherwise
5208 it will be delayed until I get a chance to write them.
5210 To browse Imager's git repository:
5212 http://git.imager.perl.org/imager.git
5216 git clone git://git.imager.perl.org/imager.git
5218 My preference is that patches are provided in the format produced by
5219 C<git format-patch>, for example, if you made your changes in a branch
5220 from master you might do:
5222 git format-patch -k --stdout master >my-patch.txt
5224 and then attach that to your bug report, either by adding it as an
5225 attachment in your email client, or by using the Request Tracker
5226 attachment mechanism.
5230 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5232 Arnar M. Hrafnkelsson is the original author of Imager.
5234 Many others have contributed to Imager, please see the C<README> for a
5239 Imager is licensed under the same terms as perl itself.
5242 makeblendedfont Fontforge
5244 A test font, generated by the Debian packaged Fontforge,
5245 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5246 copyrighted by Adobe. See F<adobe.txt> in the source for license
5251 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5252 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5253 L<Imager::Font>(3), L<Imager::Transformations>(3),
5254 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5255 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5257 L<http://imager.perl.org/>
5259 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5261 Other perl imaging modules include:
5263 L<GD>(3), L<Image::Magick>(3),
5264 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5265 L<Prima::Image>, L<IPA>.
5267 For manipulating image metadata see L<Image::ExifTool>.
5269 If you're trying to use Imager for array processing, you should
5270 probably using L<PDL>.