4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
109 # registered file readers
112 # registered file writers
115 # modules we attempted to autoload
116 my %attempted_to_load;
118 # errors from loading files
119 my %file_load_errors;
121 # what happened when we tried to load
122 my %reader_load_errors;
123 my %writer_load_errors;
125 # library keys that are image file formats
126 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
128 # image pixel combine types
130 qw/none normal multiply dissolve add subtract diff lighten darken
131 hue saturation value color/;
133 @combine_types{@combine_types} = 0 .. $#combine_types;
134 $combine_types{mult} = $combine_types{multiply};
135 $combine_types{'sub'} = $combine_types{subtract};
136 $combine_types{sat} = $combine_types{saturation};
138 # this will be used to store global defaults at some point
143 my $ex_version = eval $Exporter::VERSION;
144 if ($ex_version < 5.57) {
149 XSLoader::load(Imager => $VERSION);
155 png => "Imager::File::PNG",
156 gif => "Imager::File::GIF",
157 tiff => "Imager::File::TIFF",
158 jpeg => "Imager::File::JPEG",
159 w32 => "Imager::Font::W32",
160 ft2 => "Imager::Font::FT2",
161 t1 => "Imager::Font::T1",
164 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
167 for(i_list_formats()) { $formats_low{$_}++; }
169 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
173 # the members of the subhashes under %filters are:
174 # callseq - a list of the parameters to the underlying filter in the
175 # order they are passed
176 # callsub - a code ref that takes a named parameter list and calls the
178 # defaults - a hash of default values
179 # names - defines names for value of given parameters so if the names
180 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
181 # foo parameter, the filter will receive 1 for the foo
184 callseq => ['image','intensity'],
185 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
189 callseq => ['image', 'amount', 'subtype'],
190 defaults => { amount=>3,subtype=>0 },
191 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
194 $filters{hardinvert} ={
195 callseq => ['image'],
197 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
200 $filters{hardinvertall} =
202 callseq => ['image'],
204 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
207 $filters{autolevels_skew} ={
208 callseq => ['image','lsat','usat','skew'],
209 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
210 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
213 $filters{autolevels} ={
214 callseq => ['image','lsat','usat'],
215 defaults => { lsat=>0.1,usat=>0.1 },
216 callsub => sub { my %hsh=@_; i_autolevels_mono($hsh{image},$hsh{lsat},$hsh{usat}); }
219 $filters{turbnoise} ={
220 callseq => ['image'],
221 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
222 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
225 $filters{radnoise} ={
226 callseq => ['image'],
227 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
228 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
233 callseq => ['image', 'coef'],
238 i_conv($hsh{image},$hsh{coef})
239 or die Imager->_error_as_msg() . "\n";
245 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
246 defaults => { dist => 0 },
250 my @colors = @{$hsh{colors}};
253 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
257 $filters{nearest_color} =
259 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
264 # make sure the segments are specified with colors
266 for my $color (@{$hsh{colors}}) {
267 my $new_color = _color($color)
268 or die $Imager::ERRSTR."\n";
269 push @colors, $new_color;
272 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
274 or die Imager->_error_as_msg() . "\n";
277 $filters{gaussian} = {
278 callseq => [ 'image', 'stddev' ],
280 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
284 callseq => [ qw(image size) ],
285 defaults => { size => 20 },
286 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
290 callseq => [ qw(image bump elevation lightx lighty st) ],
291 defaults => { elevation=>0, st=> 2 },
294 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
295 $hsh{lightx}, $hsh{lighty}, $hsh{st});
298 $filters{bumpmap_complex} =
300 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
317 for my $cname (qw/Ia Il Is/) {
318 my $old = $hsh{$cname};
319 my $new_color = _color($old)
320 or die $Imager::ERRSTR, "\n";
321 $hsh{$cname} = $new_color;
323 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
324 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
325 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
329 $filters{postlevels} =
331 callseq => [ qw(image levels) ],
332 defaults => { levels => 10 },
333 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
335 $filters{watermark} =
337 callseq => [ qw(image wmark tx ty pixdiff) ],
338 defaults => { pixdiff=>10, tx=>0, ty=>0 },
342 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
348 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
350 ftype => { linear => 0,
356 repeat => { none => 0,
371 multiply => 2, mult => 2,
374 subtract => 5, 'sub' => 5,
384 defaults => { ftype => 0, repeat => 0, combine => 0,
385 super_sample => 0, ssample_param => 4,
398 # make sure the segments are specified with colors
400 for my $segment (@{$hsh{segments}}) {
401 my @new_segment = @$segment;
403 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
404 push @segments, \@new_segment;
407 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
408 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
409 $hsh{ssample_param}, \@segments)
410 or die Imager->_error_as_msg() . "\n";
413 $filters{unsharpmask} =
415 callseq => [ qw(image stddev scale) ],
416 defaults => { stddev=>2.0, scale=>1.0 },
420 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
424 $FORMATGUESS=\&def_guess_type;
434 # NOTE: this might be moved to an import override later on
439 if ($_[$i] eq '-log-stderr') {
447 goto &Exporter::import;
451 Imager->open_log(log => $_[0], level => $_[1]);
456 my %parms=(loglevel=>1,@_);
458 if (exists $parms{'warn_obsolete'}) {
459 $warn_obsolete = $parms{'warn_obsolete'};
463 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
467 if (exists $parms{'t1log'}) {
469 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
470 Imager->_set_error(Imager->_error_as_msg);
484 my (%opts) = ( loglevel => 1, @_ );
486 $is_logging = i_init_log($opts{log}, $opts{loglevel});
487 unless ($is_logging) {
488 Imager->_set_error(Imager->_error_as_msg());
492 Imager->log("Imager $VERSION starting\n", 1);
498 i_init_log(undef, -1);
503 my ($class, $message, $level) = @_;
505 defined $level or $level = 1;
507 i_log_entry($message, $level);
517 print "shutdown code\n";
518 # for(keys %instances) { $instances{$_}->DESTROY(); }
519 malloc_state(); # how do decide if this should be used? -- store something from the import
520 print "Imager exiting\n";
524 # Load a filter plugin
530 if ($^O eq 'android') {
532 $filename = File::Spec->rel2abs($filename);
535 my ($DSO_handle,$str)=DSO_open($filename);
536 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
537 my %funcs=DSO_funclist($DSO_handle);
538 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
540 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
542 $DSOs{$filename}=[$DSO_handle,\%funcs];
545 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
546 $DEBUG && print "eval string:\n",$evstr,"\n";
558 if ($^O eq 'android') {
560 $filename = File::Spec->rel2abs($filename);
563 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
564 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
565 for(keys %{$funcref}) {
567 $DEBUG && print "unloading: $_\n";
569 my $rc=DSO_close($DSO_handle);
570 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
574 # take the results of i_error() and make a message out of it
576 return join(": ", map $_->[0], i_errors());
579 # this function tries to DWIM for color parameters
580 # color objects are used as is
581 # simple scalars are simply treated as single parameters to Imager::Color->new
582 # hashrefs are treated as named argument lists to Imager::Color->new
583 # arrayrefs are treated as list arguments to Imager::Color->new iff any
585 # other arrayrefs are treated as list arguments to Imager::Color::Float
589 # perl 5.6.0 seems to do weird things to $arg if we don't make an
590 # explicitly stringified copy
591 # I vaguely remember a bug on this on p5p, but couldn't find it
592 # through bugs.perl.org (I had trouble getting it to find any bugs)
593 my $copy = $arg . "";
597 if (UNIVERSAL::isa($arg, "Imager::Color")
598 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
602 if ($copy =~ /^HASH\(/) {
603 $result = Imager::Color->new(%$arg);
605 elsif ($copy =~ /^ARRAY\(/) {
606 $result = Imager::Color->new(@$arg);
609 $Imager::ERRSTR = "Not a color";
614 # assume Imager::Color::new knows how to handle it
615 $result = Imager::Color->new($arg);
622 my ($self, $combine, $default) = @_;
624 if (!defined $combine && ref $self) {
625 $combine = $self->{combine};
627 defined $combine or $combine = $defaults{combine};
628 defined $combine or $combine = $default;
630 if (exists $combine_types{$combine}) {
631 $combine = $combine_types{$combine};
638 my ($self, $method) = @_;
641 or return Imager->_set_error("$method needs an image object");
643 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
645 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
646 $msg = "$method: $msg" if $method;
647 $self->_set_error($msg);
652 # returns first defined parameter
655 return $_ if defined $_;
661 # Methods to be called on objects.
664 # Create a new Imager object takes very few parameters.
665 # usually you call this method and then call open from
666 # the resulting object
673 $self->{IMG}=undef; # Just to indicate what exists
674 $self->{ERRSTR}=undef; #
675 $self->{DEBUG}=$DEBUG;
676 $self->{DEBUG} and print "Initialized Imager\n";
677 if (defined $hsh{file} ||
680 defined $hsh{callback} ||
681 defined $hsh{readcb} ||
682 defined $hsh{data} ||
684 # allow $img = Imager->new(file => $filename)
687 # type is already used as a parameter to new(), rename it for the
689 if ($hsh{filetype}) {
690 $extras{type} = $hsh{filetype};
692 unless ($self->read(%hsh, %extras)) {
693 $Imager::ERRSTR = $self->{ERRSTR};
697 elsif (defined $hsh{xsize} || defined $hsh{ysize}) {
698 unless ($self->img_set(%hsh)) {
699 $Imager::ERRSTR = $self->{ERRSTR};
704 Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
711 # Copy an entire image with no changes
712 # - if an image has magic the copy of it will not be magical
717 $self->_valid_image("copy")
720 unless (defined wantarray) {
722 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
726 my $newcopy=Imager->new();
727 $newcopy->{IMG} = i_copy($self->{IMG});
736 $self->_valid_image("paste")
739 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
740 my $src = $input{img} || $input{src};
742 $self->_set_error("no source image");
745 unless ($src->_valid_image("paste")) {
746 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
749 $input{left}=0 if $input{left} <= 0;
750 $input{top}=0 if $input{top} <= 0;
752 my($r,$b)=i_img_info($src->{IMG});
753 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
754 my ($src_right, $src_bottom);
755 if ($input{src_coords}) {
756 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
759 if (defined $input{src_maxx}) {
760 $src_right = $input{src_maxx};
762 elsif (defined $input{width}) {
763 if ($input{width} <= 0) {
764 $self->_set_error("paste: width must me positive");
767 $src_right = $src_left + $input{width};
772 if (defined $input{src_maxy}) {
773 $src_bottom = $input{src_maxy};
775 elsif (defined $input{height}) {
776 if ($input{height} < 0) {
777 $self->_set_error("paste: height must be positive");
780 $src_bottom = $src_top + $input{height};
787 $src_right > $r and $src_right = $r;
788 $src_bottom > $b and $src_bottom = $b;
790 if ($src_right <= $src_left
791 || $src_bottom < $src_top) {
792 $self->_set_error("nothing to paste");
796 i_copyto($self->{IMG}, $src->{IMG},
797 $src_left, $src_top, $src_right, $src_bottom,
798 $input{left}, $input{top});
800 return $self; # What should go here??
803 # Crop an image - i.e. return a new image that is smaller
808 $self->_valid_image("crop")
811 unless (defined wantarray) {
813 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
819 my ($w, $h, $l, $r, $b, $t) =
820 @hsh{qw(width height left right bottom top)};
822 # work through the various possibilities
827 elsif (!defined $r) {
828 $r = $self->getwidth;
840 $l = int(0.5+($self->getwidth()-$w)/2);
845 $r = $self->getwidth;
851 elsif (!defined $b) {
852 $b = $self->getheight;
864 $t=int(0.5+($self->getheight()-$h)/2);
869 $b = $self->getheight;
872 ($l,$r)=($r,$l) if $l>$r;
873 ($t,$b)=($b,$t) if $t>$b;
876 $r > $self->getwidth and $r = $self->getwidth;
878 $b > $self->getheight and $b = $self->getheight;
880 if ($l == $r || $t == $b) {
881 $self->_set_error("resulting image would have no content");
884 if( $r < $l or $b < $t ) {
885 $self->_set_error("attempting to crop outside of the image");
888 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
890 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
895 my ($self, %opts) = @_;
900 my $x = $opts{xsize} || $self->getwidth;
901 my $y = $opts{ysize} || $self->getheight;
902 my $channels = $opts{channels} || $self->getchannels;
904 my $out = Imager->new;
905 if ($channels == $self->getchannels) {
906 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
909 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
911 unless ($out->{IMG}) {
912 $self->{ERRSTR} = $self->_error_as_msg;
919 # Sets an image to a certain size and channel number
920 # if there was previously data in the image it is discarded
933 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
938 if (my $channels = $model_channels{$hsh{model}}) {
939 $hsh{channels} = $channels;
942 $self->_set_error("new: unknown value for model '$hsh{model}'");
947 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
948 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
949 $hsh{maxcolors} || 256);
951 elsif ($hsh{bits} eq 'double') {
952 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
954 elsif ($hsh{bits} == 16) {
955 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
958 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
962 unless ($self->{IMG}) {
963 $self->_set_error(Imager->_error_as_msg());
970 # created a masked version of the current image
974 $self->_valid_image("masked")
977 my %opts = (left => 0,
979 right => $self->getwidth,
980 bottom => $self->getheight,
982 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
984 my $result = Imager->new;
985 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
986 $opts{top}, $opts{right} - $opts{left},
987 $opts{bottom} - $opts{top});
988 unless ($result->{IMG}) {
989 $self->_set_error(Imager->_error_as_msg);
993 # keep references to the mask and base images so they don't
995 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
1000 # convert an RGB image into a paletted image
1004 if (@_ != 1 && !ref $_[0]) {
1011 unless (defined wantarray) {
1012 my @caller = caller;
1013 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
1017 $self->_valid_image("to_paletted")
1020 my $result = Imager->new;
1021 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1022 $self->_set_error(Imager->_error_as_msg);
1030 my ($class, $quant, @images) = @_;
1033 Imager->_set_error("make_palette: supply at least one image");
1037 for my $img (@images) {
1038 unless ($img->{IMG}) {
1039 Imager->_set_error("make_palette: image $index is empty");
1045 return i_img_make_palette($quant, map $_->{IMG}, @images);
1048 # convert a paletted (or any image) to an 8-bit/channel RGB image
1052 unless (defined wantarray) {
1053 my @caller = caller;
1054 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1058 $self->_valid_image("to_rgb8")
1061 my $result = Imager->new;
1062 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1063 $self->_set_error(Imager->_error_as_msg());
1070 # convert a paletted (or any image) to a 16-bit/channel RGB image
1074 unless (defined wantarray) {
1075 my @caller = caller;
1076 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1080 $self->_valid_image("to_rgb16")
1083 my $result = Imager->new;
1084 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1085 $self->_set_error(Imager->_error_as_msg());
1092 # convert a paletted (or any image) to an double/channel RGB image
1096 unless (defined wantarray) {
1097 my @caller = caller;
1098 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1102 $self->_valid_image("to_rgb_double")
1105 my $result = Imager->new;
1106 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1107 $self->_set_error(Imager->_error_as_msg());
1116 my %opts = (colors=>[], @_);
1118 $self->_valid_image("addcolors")
1121 my @colors = @{$opts{colors}}
1124 for my $color (@colors) {
1125 $color = _color($color);
1127 $self->_set_error($Imager::ERRSTR);
1132 return i_addcolors($self->{IMG}, @colors);
1137 my %opts = (start=>0, colors=>[], @_);
1139 $self->_valid_image("setcolors")
1142 my @colors = @{$opts{colors}}
1145 for my $color (@colors) {
1146 $color = _color($color);
1148 $self->_set_error($Imager::ERRSTR);
1153 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1160 $self->_valid_image("getcolors")
1163 if (!exists $opts{start} && !exists $opts{count}) {
1166 $opts{count} = $self->colorcount;
1168 elsif (!exists $opts{count}) {
1171 elsif (!exists $opts{start}) {
1175 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1181 $self->_valid_image("colorcount")
1184 return i_colorcount($self->{IMG});
1190 $self->_valid_image("maxcolors")
1193 i_maxcolors($self->{IMG});
1200 $self->_valid_image("findcolor")
1203 unless ($opts{color}) {
1204 $self->_set_error("findcolor: no color parameter");
1208 my $color = _color($opts{color})
1211 return i_findcolor($self->{IMG}, $color);
1217 $self->_valid_image("bits")
1220 my $bits = i_img_bits($self->{IMG});
1221 if ($bits && $bits == length(pack("d", 1)) * 8) {
1230 $self->_valid_image("type")
1233 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1239 $self->_valid_image("virtual")
1242 return i_img_virtual($self->{IMG});
1248 $self->_valid_image("is_bilevel")
1251 return i_img_is_monochrome($self->{IMG});
1255 my ($self, %opts) = @_;
1257 $self->_valid_image("tags")
1260 if (defined $opts{name}) {
1264 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1265 push @result, (i_tags_get($self->{IMG}, $found))[1];
1268 return wantarray ? @result : $result[0];
1270 elsif (defined $opts{code}) {
1274 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1275 push @result, (i_tags_get($self->{IMG}, $found))[1];
1282 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1285 return i_tags_count($self->{IMG});
1294 $self->_valid_image("addtag")
1298 if (defined $opts{value}) {
1299 if ($opts{value} =~ /^\d+$/) {
1301 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1304 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1307 elsif (defined $opts{data}) {
1308 # force addition as a string
1309 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1312 $self->{ERRSTR} = "No value supplied";
1316 elsif ($opts{code}) {
1317 if (defined $opts{value}) {
1318 if ($opts{value} =~ /^\d+$/) {
1320 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1323 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1326 elsif (defined $opts{data}) {
1327 # force addition as a string
1328 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1331 $self->{ERRSTR} = "No value supplied";
1344 $self->_valid_image("deltag")
1347 if (defined $opts{'index'}) {
1348 return i_tags_delete($self->{IMG}, $opts{'index'});
1350 elsif (defined $opts{name}) {
1351 return i_tags_delbyname($self->{IMG}, $opts{name});
1353 elsif (defined $opts{code}) {
1354 return i_tags_delbycode($self->{IMG}, $opts{code});
1357 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1363 my ($self, %opts) = @_;
1365 $self->_valid_image("settag")
1369 $self->deltag(name=>$opts{name});
1370 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1372 elsif (defined $opts{code}) {
1373 $self->deltag(code=>$opts{code});
1374 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1382 sub _get_reader_io {
1383 my ($self, $input) = @_;
1386 return $input->{io}, undef;
1388 elsif ($input->{fd}) {
1389 return io_new_fd($input->{fd});
1391 elsif ($input->{fh}) {
1392 unless (Scalar::Util::openhandle($input->{fh})) {
1393 $self->_set_error("Handle in fh option not opened");
1396 return Imager::IO->new_fh($input->{fh});
1398 elsif ($input->{file}) {
1399 my $file = IO::File->new($input->{file}, "r");
1401 $self->_set_error("Could not open $input->{file}: $!");
1405 return (io_new_fd(fileno($file)), $file);
1407 elsif ($input->{data}) {
1408 return io_new_buffer($input->{data});
1410 elsif ($input->{callback} || $input->{readcb}) {
1411 if (!$input->{seekcb}) {
1412 $self->_set_error("Need a seekcb parameter");
1414 if ($input->{maxbuffer}) {
1415 return io_new_cb($input->{writecb},
1416 $input->{callback} || $input->{readcb},
1417 $input->{seekcb}, $input->{closecb},
1418 $input->{maxbuffer});
1421 return io_new_cb($input->{writecb},
1422 $input->{callback} || $input->{readcb},
1423 $input->{seekcb}, $input->{closecb});
1427 $self->_set_error("file/fd/fh/data/callback parameter missing");
1432 sub _get_writer_io {
1433 my ($self, $input) = @_;
1435 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1442 elsif ($input->{fd}) {
1443 $io = io_new_fd($input->{fd});
1445 elsif ($input->{fh}) {
1446 unless (Scalar::Util::openhandle($input->{fh})) {
1447 $self->_set_error("Handle in fh option not opened");
1450 $io = Imager::IO->new_fh($input->{fh});
1452 elsif ($input->{file}) {
1453 my $fh = new IO::File($input->{file},"w+");
1455 $self->_set_error("Could not open file $input->{file}: $!");
1458 binmode($fh) or die;
1459 $io = io_new_fd(fileno($fh));
1462 elsif ($input->{data}) {
1463 $io = io_new_bufchain();
1465 elsif ($input->{callback} || $input->{writecb}) {
1466 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1469 $io = io_new_cb($input->{callback} || $input->{writecb},
1471 $input->{seekcb}, $input->{closecb});
1474 $self->_set_error("file/fd/fh/data/callback parameter missing");
1478 unless ($buffered) {
1479 $io->set_buffered(0);
1482 return ($io, @extras);
1485 # Read an image from file
1491 if (defined($self->{IMG})) {
1492 # let IIM_DESTROY do the destruction, since the image may be
1493 # referenced from elsewhere
1494 #i_img_destroy($self->{IMG});
1495 undef($self->{IMG});
1498 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1500 my $type = $input{'type'};
1502 $type = i_test_format_probe($IO, -1);
1505 if ($input{file} && !$type) {
1507 $type = $FORMATGUESS->($input{file});
1511 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1512 $input{file} and $msg .= " or file name";
1513 $self->_set_error($msg);
1517 _reader_autoload($type);
1519 if ($readers{$type} && $readers{$type}{single}) {
1520 return $readers{$type}{single}->($self, $IO, %input);
1523 unless ($formats_low{$type}) {
1524 my $read_types = join ', ', sort Imager->read_types();
1525 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1529 my $allow_incomplete = $input{allow_incomplete};
1530 defined $allow_incomplete or $allow_incomplete = 0;
1532 if ( $type eq 'pnm' ) {
1533 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1534 if ( !defined($self->{IMG}) ) {
1535 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1538 $self->{DEBUG} && print "loading a pnm file\n";
1542 if ( $type eq 'bmp' ) {
1543 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1544 if ( !defined($self->{IMG}) ) {
1545 $self->{ERRSTR}=$self->_error_as_msg();
1548 $self->{DEBUG} && print "loading a bmp file\n";
1551 if ( $type eq 'tga' ) {
1552 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1553 if ( !defined($self->{IMG}) ) {
1554 $self->{ERRSTR}=$self->_error_as_msg();
1557 $self->{DEBUG} && print "loading a tga file\n";
1560 if ( $type eq 'raw' ) {
1561 unless ( $input{xsize} && $input{ysize} ) {
1562 $self->_set_error('missing xsize or ysize parameter for raw');
1566 my $interleave = _first($input{raw_interleave}, $input{interleave});
1567 unless (defined $interleave) {
1568 my @caller = caller;
1569 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1572 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1573 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1575 $self->{IMG} = i_readraw_wiol( $IO,
1581 if ( !defined($self->{IMG}) ) {
1582 $self->{ERRSTR}=$self->_error_as_msg();
1585 $self->{DEBUG} && print "loading a raw file\n";
1591 sub register_reader {
1592 my ($class, %opts) = @_;
1595 or die "register_reader called with no type parameter\n";
1597 my $type = $opts{type};
1599 defined $opts{single} || defined $opts{multiple}
1600 or die "register_reader called with no single or multiple parameter\n";
1602 $readers{$type} = { };
1603 if ($opts{single}) {
1604 $readers{$type}{single} = $opts{single};
1606 if ($opts{multiple}) {
1607 $readers{$type}{multiple} = $opts{multiple};
1613 sub register_writer {
1614 my ($class, %opts) = @_;
1617 or die "register_writer called with no type parameter\n";
1619 my $type = $opts{type};
1621 defined $opts{single} || defined $opts{multiple}
1622 or die "register_writer called with no single or multiple parameter\n";
1624 $writers{$type} = { };
1625 if ($opts{single}) {
1626 $writers{$type}{single} = $opts{single};
1628 if ($opts{multiple}) {
1629 $writers{$type}{multiple} = $opts{multiple};
1640 grep($file_formats{$_}, keys %formats),
1641 qw(ico sgi), # formats not handled directly, but supplied with Imager
1652 grep($file_formats{$_}, keys %formats),
1653 qw(ico sgi), # formats not handled directly, but supplied with Imager
1660 my ($file, $error) = @_;
1662 if ($attempted_to_load{$file}) {
1663 if ($file_load_errors{$file}) {
1664 $$error = $file_load_errors{$file};
1672 local $SIG{__DIE__};
1675 pop @INC if $INC[-1] eq '.';
1676 ++$attempted_to_load{$file};
1684 my $work = $@ || "Unknown error";
1686 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1687 $work =~ s/\n/\\n/g;
1688 $work =~ s/\s*\.?\z/ loading $file/;
1689 $file_load_errors{$file} = $work;
1696 # probes for an Imager::File::whatever module
1697 sub _reader_autoload {
1700 return if $formats_low{$type} || $readers{$type};
1702 return unless $type =~ /^\w+$/;
1704 my $file = "Imager/File/\U$type\E.pm";
1707 my $loaded = _load_file($file, \$error);
1708 if (!$loaded && $error =~ /^Can't locate /) {
1709 my $filer = "Imager/File/\U$type\EReader.pm";
1710 $loaded = _load_file($filer, \$error);
1711 if ($error =~ /^Can't locate /) {
1712 $error = "Can't locate $file or $filer";
1716 $reader_load_errors{$type} = $error;
1720 # probes for an Imager::File::whatever module
1721 sub _writer_autoload {
1724 return if $formats_low{$type} || $writers{$type};
1726 return unless $type =~ /^\w+$/;
1728 my $file = "Imager/File/\U$type\E.pm";
1731 my $loaded = _load_file($file, \$error);
1732 if (!$loaded && $error =~ /^Can't locate /) {
1733 my $filew = "Imager/File/\U$type\EWriter.pm";
1734 $loaded = _load_file($filew, \$error);
1735 if ($error =~ /^Can't locate /) {
1736 $error = "Can't locate $file or $filew";
1740 $writer_load_errors{$type} = $error;
1744 sub _fix_gif_positions {
1745 my ($opts, $opt, $msg, @imgs) = @_;
1747 my $positions = $opts->{'gif_positions'};
1749 for my $pos (@$positions) {
1750 my ($x, $y) = @$pos;
1751 my $img = $imgs[$index++];
1752 $img->settag(name=>'gif_left', value=>$x);
1753 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1755 $$msg .= "replaced with the gif_left and gif_top tags";
1760 gif_each_palette=>'gif_local_map',
1761 interlace => 'gif_interlace',
1762 gif_delays => 'gif_delay',
1763 gif_positions => \&_fix_gif_positions,
1764 gif_loop_count => 'gif_loop',
1767 # options that should be converted to colors
1768 my %color_opts = map { $_ => 1 } qw/i_background/;
1771 my ($self, $opts, $prefix, @imgs) = @_;
1773 for my $opt (keys %$opts) {
1775 if ($obsolete_opts{$opt}) {
1776 my $new = $obsolete_opts{$opt};
1777 my $msg = "Obsolete option $opt ";
1779 $new->($opts, $opt, \$msg, @imgs);
1782 $msg .= "replaced with the $new tag ";
1785 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1786 warn $msg if $warn_obsolete && $^W;
1788 next unless $tagname =~ /^\Q$prefix/;
1789 my $value = $opts->{$opt};
1790 if ($color_opts{$opt}) {
1791 $value = _color($value);
1793 $self->_set_error($Imager::ERRSTR);
1798 if (UNIVERSAL::isa($value, "Imager::Color")) {
1799 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1800 for my $img (@imgs) {
1801 $img->settag(name=>$tagname, value=>$tag);
1804 elsif (ref($value) eq 'ARRAY') {
1805 for my $i (0..$#$value) {
1806 my $val = $value->[$i];
1808 if (UNIVERSAL::isa($val, "Imager::Color")) {
1809 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1811 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1814 $self->_set_error("Unknown reference type " . ref($value) .
1815 " supplied in array for $opt");
1821 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1826 $self->_set_error("Unknown reference type " . ref($value) .
1827 " supplied for $opt");
1832 # set it as a tag for every image
1833 for my $img (@imgs) {
1834 $img->settag(name=>$tagname, value=>$value);
1842 # Write an image to file
1845 my %input=(jpegquality=>75,
1855 $self->_valid_image("write")
1858 $self->_set_opts(\%input, "i_", $self)
1861 my $type = $input{'type'};
1862 if (!$type and $input{file}) {
1863 $type = $FORMATGUESS->($input{file});
1866 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1870 _writer_autoload($type);
1873 if ($writers{$type} && $writers{$type}{single}) {
1874 ($IO, $fh) = $self->_get_writer_io(\%input)
1877 $writers{$type}{single}->($self, $IO, %input, type => $type)
1881 if (!$formats_low{$type}) {
1882 my $write_types = join ', ', sort Imager->write_types();
1883 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1887 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1890 if ( $type eq 'pnm' ) {
1891 $self->_set_opts(\%input, "pnm_", $self)
1893 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1894 $self->{ERRSTR} = $self->_error_as_msg();
1897 $self->{DEBUG} && print "writing a pnm file\n";
1899 elsif ( $type eq 'raw' ) {
1900 $self->_set_opts(\%input, "raw_", $self)
1902 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1903 $self->{ERRSTR} = $self->_error_as_msg();
1906 $self->{DEBUG} && print "writing a raw file\n";
1908 elsif ( $type eq 'bmp' ) {
1909 $self->_set_opts(\%input, "bmp_", $self)
1911 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1912 $self->{ERRSTR} = $self->_error_as_msg;
1915 $self->{DEBUG} && print "writing a bmp file\n";
1917 elsif ( $type eq 'tga' ) {
1918 $self->_set_opts(\%input, "tga_", $self)
1921 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1922 $self->{ERRSTR}=$self->_error_as_msg();
1925 $self->{DEBUG} && print "writing a tga file\n";
1929 if (exists $input{'data'}) {
1930 my $data = io_slurp($IO);
1932 $self->{ERRSTR}='Could not slurp from buffer';
1935 ${$input{data}} = $data;
1941 my ($class, $opts, @images) = @_;
1943 my $type = $opts->{type};
1945 if (!$type && $opts->{'file'}) {
1946 $type = $FORMATGUESS->($opts->{'file'});
1949 $class->_set_error('type parameter missing and not possible to guess from extension');
1952 # translate to ImgRaw
1954 for my $img (@images) {
1955 unless (ref $img && Scalar::Util::blessed($img) && $img->isa("Imager")) {
1956 $class->_set_error("write_multi: image $index is not an Imager image object");
1959 unless ($img->_valid_image("write_multi")) {
1960 $class->_set_error($img->errstr . " (image $index)");
1965 $class->_set_opts($opts, "i_", @images)
1967 my @work = map $_->{IMG}, @images;
1969 _writer_autoload($type);
1972 if ($writers{$type} && $writers{$type}{multiple}) {
1973 ($IO, $file) = $class->_get_writer_io($opts, $type)
1976 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1980 if (!$formats{$type}) {
1981 my $write_types = join ', ', sort Imager->write_types();
1982 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1986 ($IO, $file) = $class->_get_writer_io($opts, $type)
1989 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1993 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1998 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
2004 if (exists $opts->{'data'}) {
2005 my $data = io_slurp($IO);
2007 Imager->_set_error('Could not slurp from buffer');
2010 ${$opts->{data}} = $data;
2015 # read multiple images from a file
2017 my ($class, %opts) = @_;
2019 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2022 my $type = $opts{'type'};
2024 $type = i_test_format_probe($IO, -1);
2027 if ($opts{file} && !$type) {
2029 $type = $FORMATGUESS->($opts{file});
2033 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2034 $opts{file} and $msg .= " or file name";
2035 Imager->_set_error($msg);
2039 _reader_autoload($type);
2041 if ($readers{$type} && $readers{$type}{multiple}) {
2042 return $readers{$type}{multiple}->($IO, %opts);
2045 unless ($formats{$type}) {
2046 my $read_types = join ', ', sort Imager->read_types();
2047 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2052 if ($type eq 'pnm') {
2053 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2056 my $img = Imager->new;
2057 if ($img->read(%opts, io => $IO, type => $type)) {
2060 Imager->_set_error($img->errstr);
2065 $ERRSTR = _error_as_msg();
2069 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2073 # Destroy an Imager object
2077 # delete $instances{$self};
2078 if (defined($self->{IMG})) {
2079 # the following is now handled by the XS DESTROY method for
2080 # Imager::ImgRaw object
2081 # Re-enabling this will break virtual images
2082 # tested for in t/t020masked.t
2083 # i_img_destroy($self->{IMG});
2084 undef($self->{IMG});
2086 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2090 # Perform an inplace filter of an image
2091 # that is the image will be overwritten with the data
2098 $self->_valid_image("filter")
2101 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2103 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2104 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2107 if ($filters{$input{'type'}}{names}) {
2108 my $names = $filters{$input{'type'}}{names};
2109 for my $name (keys %$names) {
2110 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2111 $input{$name} = $names->{$name}{$input{$name}};
2115 if (defined($filters{$input{'type'}}{defaults})) {
2116 %hsh=( image => $self->{IMG},
2118 %{$filters{$input{'type'}}{defaults}},
2121 %hsh=( image => $self->{IMG},
2126 my @cs=@{$filters{$input{'type'}}{callseq}};
2129 if (!defined($hsh{$_})) {
2130 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2135 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2136 &{$filters{$input{'type'}}{callsub}}(%hsh);
2139 chomp($self->{ERRSTR} = $@);
2145 $self->{DEBUG} && print "callseq is: @cs\n";
2146 $self->{DEBUG} && print "matching callseq is: @b\n";
2151 sub register_filter {
2153 my %hsh = ( defaults => {}, @_ );
2156 or die "register_filter() with no type\n";
2157 defined $hsh{callsub}
2158 or die "register_filter() with no callsub\n";
2159 defined $hsh{callseq}
2160 or die "register_filter() with no callseq\n";
2162 exists $filters{$hsh{type}}
2165 $filters{$hsh{type}} = \%hsh;
2170 sub scale_calculate {
2173 my %opts = ('type'=>'max', @_);
2175 # none of these should be references
2176 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2177 if (defined $opts{$name} && ref $opts{$name}) {
2178 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2183 my ($x_scale, $y_scale);
2184 my $width = $opts{width};
2185 my $height = $opts{height};
2187 defined $width or $width = $self->getwidth;
2188 defined $height or $height = $self->getheight;
2191 unless (defined $width && defined $height) {
2192 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2197 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2198 $x_scale = $opts{'xscalefactor'};
2199 $y_scale = $opts{'yscalefactor'};
2201 elsif ($opts{'xscalefactor'}) {
2202 $x_scale = $opts{'xscalefactor'};
2203 $y_scale = $opts{'scalefactor'} || $x_scale;
2205 elsif ($opts{'yscalefactor'}) {
2206 $y_scale = $opts{'yscalefactor'};
2207 $x_scale = $opts{'scalefactor'} || $y_scale;
2210 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2213 # work out the scaling
2214 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2215 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2216 $opts{ypixels} / $height );
2217 if ($opts{'type'} eq 'min') {
2218 $x_scale = $y_scale = _min($xpix,$ypix);
2220 elsif ($opts{'type'} eq 'max') {
2221 $x_scale = $y_scale = _max($xpix,$ypix);
2223 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2228 $self->_set_error('invalid value for type parameter');
2231 } elsif ($opts{xpixels}) {
2232 $x_scale = $y_scale = $opts{xpixels} / $width;
2234 elsif ($opts{ypixels}) {
2235 $x_scale = $y_scale = $opts{ypixels}/$height;
2237 elsif ($opts{constrain} && ref $opts{constrain}
2238 && $opts{constrain}->can('constrain')) {
2239 # we've been passed an Image::Math::Constrain object or something
2240 # that looks like one
2242 (undef, undef, $scalefactor)
2243 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2244 unless ($scalefactor) {
2245 $self->_set_error('constrain method failed on constrain parameter');
2248 $x_scale = $y_scale = $scalefactor;
2251 my $new_width = int($x_scale * $width + 0.5);
2252 $new_width > 0 or $new_width = 1;
2253 my $new_height = int($y_scale * $height + 0.5);
2254 $new_height > 0 or $new_height = 1;
2256 return ($x_scale, $y_scale, $new_width, $new_height);
2260 # Scale an image to requested size and return the scaled version
2264 my %opts = (qtype=>'normal' ,@_);
2265 my $img = Imager->new();
2266 my $tmp = Imager->new();
2268 unless (defined wantarray) {
2269 my @caller = caller;
2270 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2274 $self->_valid_image("scale")
2277 my ($x_scale, $y_scale, $new_width, $new_height) =
2278 $self->scale_calculate(%opts)
2281 if ($opts{qtype} eq 'normal') {
2282 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2283 if ( !defined($tmp->{IMG}) ) {
2284 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2287 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2288 if ( !defined($img->{IMG}) ) {
2289 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2295 elsif ($opts{'qtype'} eq 'preview') {
2296 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2297 if ( !defined($img->{IMG}) ) {
2298 $self->{ERRSTR}='unable to scale image';
2303 elsif ($opts{'qtype'} eq 'mixing') {
2304 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2305 unless ($img->{IMG}) {
2306 $self->_set_error(Imager->_error_as_msg);
2312 $self->_set_error('invalid value for qtype parameter');
2317 # Scales only along the X axis
2321 my %opts = ( scalefactor=>0.5, @_ );
2323 unless (defined wantarray) {
2324 my @caller = caller;
2325 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2329 $self->_valid_image("scaleX")
2332 my $img = Imager->new();
2334 my $scalefactor = $opts{scalefactor};
2336 if ($opts{pixels}) {
2337 $scalefactor = $opts{pixels} / $self->getwidth();
2340 unless ($self->{IMG}) {
2341 $self->{ERRSTR}='empty input image';
2345 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2347 if ( !defined($img->{IMG}) ) {
2348 $self->{ERRSTR} = 'unable to scale image';
2355 # Scales only along the Y axis
2359 my %opts = ( scalefactor => 0.5, @_ );
2361 unless (defined wantarray) {
2362 my @caller = caller;
2363 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2367 $self->_valid_image("scaleY")
2370 my $img = Imager->new();
2372 my $scalefactor = $opts{scalefactor};
2374 if ($opts{pixels}) {
2375 $scalefactor = $opts{pixels} / $self->getheight();
2378 unless ($self->{IMG}) {
2379 $self->{ERRSTR} = 'empty input image';
2382 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2384 if ( !defined($img->{IMG}) ) {
2385 $self->{ERRSTR} = 'unable to scale image';
2392 # Transform returns a spatial transformation of the input image
2393 # this moves pixels to a new location in the returned image.
2394 # NOTE - should make a utility function to check transforms for
2400 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2402 # print Dumper(\%opts);
2405 $self->_valid_image("transform")
2408 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2412 pop @INC if $INC[-1] eq '.';
2413 eval ("use Affix::Infix2Postfix;");
2417 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2420 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2421 {op=>'-',trans=>'Sub'},
2422 {op=>'*',trans=>'Mult'},
2423 {op=>'/',trans=>'Div'},
2424 {op=>'-','type'=>'unary',trans=>'u-'},
2426 {op=>'func','type'=>'unary'}],
2427 'grouping'=>[qw( \( \) )],
2428 'func'=>[qw( sin cos )],
2433 @xt=$I2P->translate($opts{'xexpr'});
2434 @yt=$I2P->translate($opts{'yexpr'});
2436 $numre=$I2P->{'numre'};
2439 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2440 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2441 @{$opts{'parm'}}=@pt;
2444 # print Dumper(\%opts);
2446 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2447 $self->{ERRSTR}='transform: no xopcodes given.';
2451 @op=@{$opts{'xopcodes'}};
2453 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2454 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2457 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2463 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2464 $self->{ERRSTR}='transform: no yopcodes given.';
2468 @op=@{$opts{'yopcodes'}};
2470 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2471 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2474 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2479 if ( !exists $opts{'parm'}) {
2480 $self->{ERRSTR}='transform: no parameter arg given.';
2484 # print Dumper(\@ropx);
2485 # print Dumper(\@ropy);
2486 # print Dumper(\@ropy);
2488 my $img = Imager->new();
2489 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2490 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2496 my ($opts, @imgs) = @_;
2498 require "Imager/Expr.pm";
2500 $opts->{variables} = [ qw(x y) ];
2501 my ($width, $height) = @{$opts}{qw(width height)};
2504 for my $img (@imgs) {
2505 unless ($img->_valid_image("transform2")) {
2506 Imager->_set_error($img->errstr . " (input image $index)");
2512 $width ||= $imgs[0]->getwidth();
2513 $height ||= $imgs[0]->getheight();
2515 for my $img (@imgs) {
2516 $opts->{constants}{"w$img_num"} = $img->getwidth();
2517 $opts->{constants}{"h$img_num"} = $img->getheight();
2518 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2519 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2524 $opts->{constants}{w} = $width;
2525 $opts->{constants}{cx} = $width/2;
2528 $Imager::ERRSTR = "No width supplied";
2532 $opts->{constants}{h} = $height;
2533 $opts->{constants}{cy} = $height/2;
2536 $Imager::ERRSTR = "No height supplied";
2539 my $code = Imager::Expr->new($opts);
2541 $Imager::ERRSTR = Imager::Expr::error();
2544 my $channels = $opts->{channels} || 3;
2545 unless ($channels >= 1 && $channels <= 4) {
2546 return Imager->_set_error("channels must be an integer between 1 and 4");
2549 my $img = Imager->new();
2550 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2551 $channels, $code->code(),
2552 $code->nregs(), $code->cregs(),
2553 [ map { $_->{IMG} } @imgs ]);
2554 if (!defined $img->{IMG}) {
2555 $Imager::ERRSTR = Imager->_error_as_msg();
2566 $self->_valid_image("rubthrough")
2569 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2570 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2574 %opts = (src_minx => 0,
2576 src_maxx => $opts{src}->getwidth(),
2577 src_maxy => $opts{src}->getheight(),
2581 defined $tx or $tx = $opts{left};
2582 defined $tx or $tx = 0;
2585 defined $ty or $ty = $opts{top};
2586 defined $ty or $ty = 0;
2588 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2589 $opts{src_minx}, $opts{src_miny},
2590 $opts{src_maxx}, $opts{src_maxy})) {
2591 $self->_set_error($self->_error_as_msg());
2608 $self->_valid_image("compose")
2611 unless ($opts{src}) {
2612 $self->_set_error("compose: src parameter missing");
2616 unless ($opts{src}->_valid_image("compose")) {
2617 $self->_set_error($opts{src}->errstr . " (for src)");
2620 my $src = $opts{src};
2622 my $left = $opts{left};
2623 defined $left or $left = $opts{tx};
2624 defined $left or $left = 0;
2626 my $top = $opts{top};
2627 defined $top or $top = $opts{ty};
2628 defined $top or $top = 0;
2630 my $src_left = $opts{src_left};
2631 defined $src_left or $src_left = $opts{src_minx};
2632 defined $src_left or $src_left = 0;
2634 my $src_top = $opts{src_top};
2635 defined $src_top or $src_top = $opts{src_miny};
2636 defined $src_top or $src_top = 0;
2638 my $width = $opts{width};
2639 if (!defined $width && defined $opts{src_maxx}) {
2640 $width = $opts{src_maxx} - $src_left;
2642 defined $width or $width = $src->getwidth() - $src_left;
2644 my $height = $opts{height};
2645 if (!defined $height && defined $opts{src_maxy}) {
2646 $height = $opts{src_maxy} - $src_top;
2648 defined $height or $height = $src->getheight() - $src_top;
2650 my $combine = $self->_combine($opts{combine}, 'normal');
2653 unless ($opts{mask}->_valid_image("compose")) {
2654 $self->_set_error($opts{mask}->errstr . " (for mask)");
2658 my $mask_left = $opts{mask_left};
2659 defined $mask_left or $mask_left = $opts{mask_minx};
2660 defined $mask_left or $mask_left = 0;
2662 my $mask_top = $opts{mask_top};
2663 defined $mask_top or $mask_top = $opts{mask_miny};
2664 defined $mask_top or $mask_top = 0;
2666 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2667 $left, $top, $src_left, $src_top,
2668 $mask_left, $mask_top, $width, $height,
2669 $combine, $opts{opacity})) {
2670 $self->_set_error(Imager->_error_as_msg);
2675 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2676 $width, $height, $combine, $opts{opacity})) {
2677 $self->_set_error(Imager->_error_as_msg);
2689 $self->_valid_image("flip")
2692 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2694 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2695 $dir = $xlate{$opts{'dir'}};
2696 return $self if i_flipxy($self->{IMG}, $dir);
2704 unless (defined wantarray) {
2705 my @caller = caller;
2706 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2710 $self->_valid_image("rotate")
2713 if (defined $opts{right}) {
2714 my $degrees = $opts{right};
2716 $degrees += 360 * int(((-$degrees)+360)/360);
2718 $degrees = $degrees % 360;
2719 if ($degrees == 0) {
2720 return $self->copy();
2722 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2723 my $result = Imager->new();
2724 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2728 $self->{ERRSTR} = $self->_error_as_msg();
2733 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2737 elsif (defined $opts{radians} || defined $opts{degrees}) {
2738 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2740 my $back = $opts{back};
2741 my $result = Imager->new;
2743 $back = _color($back);
2745 $self->_set_error(Imager->errstr);
2749 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2752 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2754 if ($result->{IMG}) {
2758 $self->{ERRSTR} = $self->_error_as_msg();
2763 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2768 sub matrix_transform {
2772 $self->_valid_image("matrix_transform")
2775 unless (defined wantarray) {
2776 my @caller = caller;
2777 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2781 if ($opts{matrix}) {
2782 my $xsize = $opts{xsize} || $self->getwidth;
2783 my $ysize = $opts{ysize} || $self->getheight;
2785 my $result = Imager->new;
2787 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2788 $opts{matrix}, $opts{back})
2792 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2800 $self->{ERRSTR} = "matrix parameter required";
2806 *yatf = \&matrix_transform;
2808 # These two are supported for legacy code only
2811 return Imager::Color->new(@_);
2815 return Imager::Color::set(@_);
2818 # Draws a box between the specified corner points.
2821 my $raw = $self->{IMG};
2823 $self->_valid_image("box")
2828 my ($xmin, $ymin, $xmax, $ymax);
2829 if (exists $opts{'box'}) {
2830 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2831 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2832 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2833 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2836 defined($xmin = $opts{xmin}) or $xmin = 0;
2837 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2838 defined($ymin = $opts{ymin}) or $ymin = 0;
2839 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2842 if ($opts{filled}) {
2843 my $color = $opts{'color'};
2845 if (defined $color) {
2846 unless (_is_color_object($color)) {
2847 $color = _color($color);
2849 $self->{ERRSTR} = $Imager::ERRSTR;
2855 $color = i_color_new(255,255,255,255);
2858 if ($color->isa("Imager::Color")) {
2859 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2862 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2865 elsif ($opts{fill}) {
2866 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2867 # assume it's a hash ref
2868 require 'Imager/Fill.pm';
2869 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2870 $self->{ERRSTR} = $Imager::ERRSTR;
2874 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2877 my $color = $opts{'color'};
2878 if (defined $color) {
2879 unless (_is_color_object($color)) {
2880 $color = _color($color);
2882 $self->{ERRSTR} = $Imager::ERRSTR;
2888 $color = i_color_new(255, 255, 255, 255);
2891 $self->{ERRSTR} = $Imager::ERRSTR;
2894 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2903 $self->_valid_image("arc")
2906 my $dflcl= [ 255, 255, 255, 255];
2911 'r'=>_min($self->getwidth(),$self->getheight())/3,
2912 'x'=>$self->getwidth()/2,
2913 'y'=>$self->getheight()/2,
2920 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2921 # assume it's a hash ref
2922 require 'Imager/Fill.pm';
2923 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2924 $self->{ERRSTR} = $Imager::ERRSTR;
2928 if ($opts{d1} == 0 && $opts{d2} == 361) {
2929 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2933 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2934 $opts{'d2'}, $opts{fill}{fill});
2937 elsif ($opts{filled}) {
2938 my $color = _color($opts{'color'});
2940 $self->{ERRSTR} = $Imager::ERRSTR;
2943 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2944 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2948 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2949 $opts{'d1'}, $opts{'d2'}, $color);
2953 my $color = _color($opts{'color'});
2954 if ($opts{d2} - $opts{d1} >= 360) {
2955 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2958 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2964 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2965 # assume it's a hash ref
2966 require 'Imager/Fill.pm';
2967 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2968 $self->{ERRSTR} = $Imager::ERRSTR;
2972 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2973 $opts{'d2'}, $opts{fill}{fill});
2976 my $color = _color($opts{'color'});
2978 $self->{ERRSTR} = $Imager::ERRSTR;
2981 if ($opts{filled}) {
2982 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2983 $opts{'d1'}, $opts{'d2'}, $color);
2986 if ($opts{d1} == 0 && $opts{d2} == 361) {
2987 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2990 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2996 $self->_set_error($self->_error_as_msg);
3003 # Draws a line from one point to the other
3004 # the endpoint is set if the endp parameter is set which it is by default.
3005 # to turn of the endpoint being set use endp=>0 when calling line.
3009 my $dflcl=i_color_new(0,0,0,0);
3010 my %opts=(color=>$dflcl,
3014 $self->_valid_image("line")
3017 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
3018 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
3020 my $color = _color($opts{'color'});
3022 $self->{ERRSTR} = $Imager::ERRSTR;
3026 $opts{antialias} = $opts{aa} if defined $opts{aa};
3027 if ($opts{antialias}) {
3028 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3029 $color, $opts{endp});
3031 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3032 $color, $opts{endp});
3037 # Draws a line between an ordered set of points - It more or less just transforms this
3038 # into a list of lines.
3042 my ($pt,$ls,@points);
3043 my $dflcl=i_color_new(0,0,0,0);
3044 my %opts=(color=>$dflcl,@_);
3046 $self->_valid_image("polyline")
3049 if (exists($opts{points})) { @points=@{$opts{points}}; }
3050 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3051 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3054 # print Dumper(\@points);
3056 my $color = _color($opts{'color'});
3058 $self->{ERRSTR} = $Imager::ERRSTR;
3061 $opts{antialias} = $opts{aa} if defined $opts{aa};
3062 if ($opts{antialias}) {
3065 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3072 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3082 my ($pt,$ls,@points);
3083 my $dflcl = i_color_new(0,0,0,0);
3084 my %opts = (color=>$dflcl, @_);
3086 $self->_valid_image("polygon")
3089 if (exists($opts{points})) {
3090 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3091 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3094 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3095 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3098 my $mode = _first($opts{mode}, 0);
3100 if ($opts{'fill'}) {
3101 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3102 # assume it's a hash ref
3103 require 'Imager/Fill.pm';
3104 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3105 $self->{ERRSTR} = $Imager::ERRSTR;
3109 i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3110 $mode, $opts{'fill'}{'fill'});
3113 my $color = _color($opts{'color'});
3115 $self->{ERRSTR} = $Imager::ERRSTR;
3118 i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color);
3125 my ($self, %opts) = @_;
3127 $self->_valid_image("polypolygon")
3130 my $points = $opts{points};
3132 or return $self->_set_error("polypolygon: missing required points");
3134 my $mode = _first($opts{mode}, "evenodd");
3136 if ($opts{filled}) {
3137 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3138 or return $self->_set_error($Imager::ERRSTR);
3140 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3141 or return $self->_set_error($self->_error_as_msg);
3143 elsif ($opts{fill}) {
3144 my $fill = $opts{fill};
3145 $self->_valid_fill($fill, "polypolygon")
3148 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3149 or return $self->_set_error($self->_error_as_msg);
3152 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3153 or return $self->_set_error($Imager::ERRSTR);
3155 my $rimg = $self->{IMG};
3157 if (_first($opts{aa}, 1)) {
3158 for my $poly (@$points) {
3159 my $xp = $poly->[0];
3160 my $yp = $poly->[1];
3161 for my $i (0 .. $#$xp - 1) {
3162 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3165 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3170 for my $poly (@$points) {
3171 my $xp = $poly->[0];
3172 my $yp = $poly->[1];
3173 for my $i (0 .. $#$xp - 1) {
3174 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3177 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3186 # this the multipoint bezier curve
3187 # this is here more for testing that actual usage since
3188 # this is not a good algorithm. Usually the curve would be
3189 # broken into smaller segments and each done individually.
3193 my ($pt,$ls,@points);
3194 my $dflcl=i_color_new(0,0,0,0);
3195 my %opts=(color=>$dflcl,@_);
3197 $self->_valid_image("polybezier")
3200 if (exists $opts{points}) {
3201 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3202 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3205 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3206 $self->{ERRSTR}='Missing or invalid points.';
3210 my $color = _color($opts{'color'});
3212 $self->{ERRSTR} = $Imager::ERRSTR;
3215 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3221 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3224 $self->_valid_image("flood_fill")
3227 unless (exists $opts{'x'} && exists $opts{'y'}) {
3228 $self->{ERRSTR} = "missing seed x and y parameters";
3232 if ($opts{border}) {
3233 my $border = _color($opts{border});
3235 $self->_set_error($Imager::ERRSTR);
3239 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3240 # assume it's a hash ref
3241 require Imager::Fill;
3242 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3243 $self->{ERRSTR} = $Imager::ERRSTR;
3247 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3248 $opts{fill}{fill}, $border);
3251 my $color = _color($opts{'color'});
3253 $self->{ERRSTR} = $Imager::ERRSTR;
3256 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3263 $self->{ERRSTR} = $self->_error_as_msg();
3269 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3270 # assume it's a hash ref
3271 require 'Imager/Fill.pm';
3272 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3273 $self->{ERRSTR} = $Imager::ERRSTR;
3277 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3280 my $color = _color($opts{'color'});
3282 $self->{ERRSTR} = $Imager::ERRSTR;
3285 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3291 $self->{ERRSTR} = $self->_error_as_msg();
3298 my ($self, %opts) = @_;
3300 $self->_valid_image("setpixel")
3303 my $color = $opts{color};
3304 unless (defined $color) {
3305 $color = $self->{fg};
3306 defined $color or $color = NC(255, 255, 255);
3309 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3310 unless ($color = _color($color, 'setpixel')) {
3311 $self->_set_error("setpixel: " . Imager->errstr);
3316 unless (exists $opts{'x'} && exists $opts{'y'}) {
3317 $self->_set_error('setpixel: missing x or y parameter');
3323 if (ref $x || ref $y) {
3324 $x = ref $x ? $x : [ $x ];
3325 $y = ref $y ? $y : [ $y ];
3327 $self->_set_error("setpixel: x is a reference to an empty array");
3331 $self->_set_error("setpixel: y is a reference to an empty array");
3335 # make both the same length, replicating the last element
3337 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3340 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3344 if ($color->isa('Imager::Color')) {
3345 for my $i (0..$#$x) {
3346 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3351 for my $i (0..$#$x) {
3352 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3360 if ($color->isa('Imager::Color')) {
3361 i_ppix($self->{IMG}, $x, $y, $color)
3362 and return "0 but true";
3365 i_ppixf($self->{IMG}, $x, $y, $color)
3366 and return "0 but true";
3376 my %opts = ( "type"=>'8bit', @_);
3378 $self->_valid_image("getpixel")
3381 unless (exists $opts{'x'} && exists $opts{'y'}) {
3382 $self->_set_error('getpixel: missing x or y parameter');
3388 my $type = $opts{'type'};
3389 if (ref $x || ref $y) {
3390 $x = ref $x ? $x : [ $x ];
3391 $y = ref $y ? $y : [ $y ];
3393 $self->_set_error("getpixel: x is a reference to an empty array");
3397 $self->_set_error("getpixel: y is a reference to an empty array");
3401 # make both the same length, replicating the last element
3403 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3406 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3410 if ($type eq '8bit') {
3411 for my $i (0..$#$x) {
3412 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3415 elsif ($type eq 'float' || $type eq 'double') {
3416 for my $i (0..$#$x) {
3417 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3421 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3424 return wantarray ? @result : \@result;
3427 if ($type eq '8bit') {
3428 return i_get_pixel($self->{IMG}, $x, $y);
3430 elsif ($type eq 'float' || $type eq 'double') {
3431 return i_gpixf($self->{IMG}, $x, $y);
3434 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3442 my %opts = ( type => '8bit', x=>0, @_);
3444 $self->_valid_image("getscanline")
3447 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3449 unless (defined $opts{'y'}) {
3450 $self->_set_error("missing y parameter");
3454 if ($opts{type} eq '8bit') {
3455 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3458 elsif ($opts{type} eq 'float') {
3459 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3462 elsif ($opts{type} eq 'index') {
3463 unless (i_img_type($self->{IMG})) {
3464 $self->_set_error("type => index only valid on paletted images");
3467 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3471 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3478 my %opts = ( x=>0, @_);
3480 $self->_valid_image("setscanline")
3483 unless (defined $opts{'y'}) {
3484 $self->_set_error("missing y parameter");
3489 if (ref $opts{pixels} && @{$opts{pixels}}) {
3490 # try to guess the type
3491 if ($opts{pixels}[0]->isa('Imager::Color')) {
3492 $opts{type} = '8bit';
3494 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3495 $opts{type} = 'float';
3498 $self->_set_error("missing type parameter and could not guess from pixels");
3504 $opts{type} = '8bit';
3508 if ($opts{type} eq '8bit') {
3509 if (ref $opts{pixels}) {
3510 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3513 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3516 elsif ($opts{type} eq 'float') {
3517 if (ref $opts{pixels}) {
3518 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3521 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3524 elsif ($opts{type} eq 'index') {
3525 if (ref $opts{pixels}) {
3526 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3529 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3533 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3540 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3542 $self->_valid_image("getsamples")
3545 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3547 unless (defined $opts{'y'}) {
3548 $self->_set_error("missing y parameter");
3552 if ($opts{target}) {
3553 my $target = $opts{target};
3554 my $offset = $opts{offset};
3555 if ($opts{type} eq '8bit') {
3556 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3557 $opts{y}, $opts{channels})
3559 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3560 return scalar(@samples);
3562 elsif ($opts{type} eq 'float') {
3563 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3564 $opts{y}, $opts{channels});
3565 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3566 return scalar(@samples);
3568 elsif ($opts{type} =~ /^(\d+)bit$/) {
3572 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3573 $opts{y}, $bits, $target,
3574 $offset, $opts{channels});
3575 unless (defined $count) {
3576 $self->_set_error(Imager->_error_as_msg);
3583 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3588 if ($opts{type} eq '8bit') {
3589 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3590 $opts{y}, $opts{channels});
3592 elsif ($opts{type} eq 'float') {
3593 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3594 $opts{y}, $opts{channels});
3596 elsif ($opts{type} =~ /^(\d+)bit$/) {
3600 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3601 $opts{y}, $bits, \@data, 0, $opts{channels})
3606 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3615 $self->_valid_image("setsamples")
3618 my %opts = ( x => 0, offset => 0 );
3620 # avoid duplicating the data parameter, it may be a large scalar
3622 while ($i < @_ -1) {
3623 if ($_[$i] eq 'data') {
3627 $opts{$_[$i]} = $_[$i+1];
3633 unless(defined $data_index) {
3634 $self->_set_error('setsamples: data parameter missing');
3637 unless (defined $_[$data_index]) {
3638 $self->_set_error('setsamples: data parameter not defined');
3642 my $type = $opts{type};
3643 defined $type or $type = '8bit';
3645 my $width = defined $opts{width} ? $opts{width}
3646 : $self->getwidth() - $opts{x};
3649 if ($type eq '8bit') {
3650 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3651 $_[$data_index], $opts{offset}, $width);
3653 elsif ($type eq 'float') {
3654 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3655 $_[$data_index], $opts{offset}, $width);
3657 elsif ($type =~ /^([0-9]+)bit$/) {
3660 unless (ref $_[$data_index]) {
3661 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3665 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3666 $opts{channels}, $_[$data_index], $opts{offset},
3670 $self->_set_error('setsamples: type parameter invalid');
3674 unless (defined $count) {
3675 $self->_set_error(Imager->_error_as_msg);
3682 # make an identity matrix of the given size
3686 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3687 for my $c (0 .. ($size-1)) {
3688 $matrix->[$c][$c] = 1;
3693 # general function to convert an image
3695 my ($self, %opts) = @_;
3698 $self->_valid_image("convert")
3701 unless (defined wantarray) {
3702 my @caller = caller;
3703 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3707 # the user can either specify a matrix or preset
3708 # the matrix overrides the preset
3709 if (!exists($opts{matrix})) {
3710 unless (exists($opts{preset})) {
3711 $self->{ERRSTR} = "convert() needs a matrix or preset";
3715 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3716 # convert to greyscale, keeping the alpha channel if any
3717 if ($self->getchannels == 3) {
3718 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3720 elsif ($self->getchannels == 4) {
3721 # preserve the alpha channel
3722 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3727 $matrix = _identity($self->getchannels);
3730 elsif ($opts{preset} eq 'noalpha') {
3731 # strip the alpha channel
3732 if ($self->getchannels == 2 or $self->getchannels == 4) {
3733 $matrix = _identity($self->getchannels);
3734 pop(@$matrix); # lose the alpha entry
3737 $matrix = _identity($self->getchannels);
3740 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3742 $matrix = [ [ 1 ] ];
3744 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3745 $matrix = [ [ 0, 1 ] ];
3747 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3748 $matrix = [ [ 0, 0, 1 ] ];
3750 elsif ($opts{preset} eq 'alpha') {
3751 if ($self->getchannels == 2 or $self->getchannels == 4) {
3752 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3755 # the alpha is just 1 <shrug>
3756 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3759 elsif ($opts{preset} eq 'rgb') {
3760 if ($self->getchannels == 1) {
3761 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3763 elsif ($self->getchannels == 2) {
3764 # preserve the alpha channel
3765 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3768 $matrix = _identity($self->getchannels);
3771 elsif ($opts{preset} eq 'addalpha') {
3772 if ($self->getchannels == 1) {
3773 $matrix = _identity(2);
3775 elsif ($self->getchannels == 3) {
3776 $matrix = _identity(4);
3779 $matrix = _identity($self->getchannels);
3783 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3789 $matrix = $opts{matrix};
3792 my $new = Imager->new;
3793 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3794 unless ($new->{IMG}) {
3795 # most likely a bad matrix
3796 i_push_error(0, "convert");
3797 $self->{ERRSTR} = _error_as_msg();
3803 # combine channels from multiple input images, a class method
3805 my ($class, %opts) = @_;
3807 my $src = delete $opts{src};
3809 $class->_set_error("src parameter missing");
3814 for my $img (@$src) {
3815 unless (eval { $img->isa("Imager") }) {
3816 $class->_set_error("src must contain image objects");
3819 unless ($img->_valid_image("combine")) {
3820 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3823 push @imgs, $img->{IMG};
3826 if (my $channels = delete $opts{channels}) {
3827 $result = i_combine(\@imgs, $channels);
3830 $result = i_combine(\@imgs);
3833 $class->_set_error($class->_error_as_msg);
3837 my $img = $class->new;
3838 $img->{IMG} = $result;
3844 # general function to map an image through lookup tables
3847 my ($self, %opts) = @_;
3848 my @chlist = qw( red green blue alpha );
3850 $self->_valid_image("map")
3853 if (!exists($opts{'maps'})) {
3854 # make maps from channel maps
3856 for $chnum (0..$#chlist) {
3857 if (exists $opts{$chlist[$chnum]}) {
3858 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3859 } elsif (exists $opts{'all'}) {
3860 $opts{'maps'}[$chnum] = $opts{'all'};
3864 if ($opts{'maps'} and $self->{IMG}) {
3865 i_map($self->{IMG}, $opts{'maps'} );
3871 my ($self, %opts) = @_;
3873 $self->_valid_image("difference")
3876 defined $opts{mindist} or $opts{mindist} = 0;
3878 defined $opts{other}
3879 or return $self->_set_error("No 'other' parameter supplied");
3880 unless ($opts{other}->_valid_image("difference")) {
3881 $self->_set_error($opts{other}->errstr . " (other image)");
3885 my $result = Imager->new;
3886 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3888 or return $self->_set_error($self->_error_as_msg());
3893 # destructive border - image is shrunk by one pixel all around
3896 my ($self,%opts)=@_;
3897 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3898 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3902 # Get the width of an image
3907 $self->_valid_image("getwidth")
3910 return i_img_get_width($self->{IMG});
3913 # Get the height of an image
3918 $self->_valid_image("getheight")
3921 return i_img_get_height($self->{IMG});
3924 # Get number of channels in an image
3929 $self->_valid_image("getchannels")
3932 return i_img_getchannels($self->{IMG});
3935 my @model_names = qw(unknown gray graya rgb rgba);
3938 my ($self, %opts) = @_;
3940 $self->_valid_image("colormodel")
3943 my $model = i_img_color_model($self->{IMG});
3945 return $opts{numeric} ? $model : $model_names[$model];
3951 $self->_valid_image("colorchannels")
3954 return i_img_color_channels($self->{IMG});
3960 $self->_valid_image("alphachannel")
3963 return scalar(i_img_alpha_channel($self->{IMG}));
3971 $self->_valid_image("getmask")
3974 return i_img_getmask($self->{IMG});
3983 $self->_valid_image("setmask")
3986 unless (defined $opts{mask}) {
3987 $self->_set_error("mask parameter required");
3991 i_img_setmask( $self->{IMG} , $opts{mask} );
3996 # Get number of colors in an image
4000 my %opts=('maxcolors'=>2**30,@_);
4002 $self->_valid_image("getcolorcount")
4005 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
4006 return ($rc==-1? undef : $rc);
4009 # Returns a reference to a hash. The keys are colour named (packed) and the
4010 # values are the number of pixels in this colour.
4011 sub getcolorusagehash {
4014 $self->_valid_image("getcolorusagehash")
4017 my %opts = ( maxcolors => 2**30, @_ );
4018 my $max_colors = $opts{maxcolors};
4019 unless (defined $max_colors && $max_colors > 0) {
4020 $self->_set_error('maxcolors must be a positive integer');
4024 my $channels= $self->getchannels;
4025 # We don't want to look at the alpha channel, because some gifs using it
4026 # doesn't define it for every colour (but only for some)
4027 $channels -= 1 if $channels == 2 or $channels == 4;
4029 my $height = $self->getheight;
4030 for my $y (0 .. $height - 1) {
4031 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4032 while (length $colors) {
4033 $color_use{ substr($colors, 0, $channels, '') }++;
4035 keys %color_use > $max_colors
4041 # This will return a ordered array of the colour usage. Kind of the sorted
4042 # version of the values of the hash returned by getcolorusagehash.
4043 # You might want to add safety checks and change the names, etc...
4047 $self->_valid_image("getcolorusage")
4050 my %opts = ( maxcolors => 2**30, @_ );
4051 my $max_colors = $opts{maxcolors};
4052 unless (defined $max_colors && $max_colors > 0) {
4053 $self->_set_error('maxcolors must be a positive integer');
4057 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4060 # draw string to an image
4065 $self->_valid_image("string")
4068 my %input=('x'=>0, 'y'=>0, @_);
4069 defined($input{string}) or $input{string} = $input{text};
4071 unless(defined $input{string}) {
4072 $self->{ERRSTR}="missing required parameter 'string'";
4076 unless($input{font}) {
4077 $self->{ERRSTR}="missing required parameter 'font'";
4081 unless ($input{font}->draw(image=>$self, %input)) {
4093 $self->_valid_image("align_string")
4102 my %input=('x'=>0, 'y'=>0, @_);
4103 defined $input{string}
4104 or $input{string} = $input{text};
4106 unless(exists $input{string}) {
4107 $self->_set_error("missing required parameter 'string'");
4111 unless($input{font}) {
4112 $self->_set_error("missing required parameter 'font'");
4117 unless (@result = $input{font}->align(image=>$img, %input)) {
4121 return wantarray ? @result : $result[0];
4124 my @file_limit_names = qw/width height bytes/;
4126 sub set_file_limits {
4133 @values{@file_limit_names} = (0) x @file_limit_names;
4136 @values{@file_limit_names} = i_get_image_file_limits();
4139 for my $key (keys %values) {
4140 defined $opts{$key} and $values{$key} = $opts{$key};
4143 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4146 sub get_file_limits {
4147 i_get_image_file_limits();
4150 my @check_args = qw(width height channels sample_size);
4152 sub check_file_limits {
4162 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4163 $opts{sample_size} = length(pack("d", 0));
4166 for my $name (@check_args) {
4167 unless (defined $opts{$name}) {
4168 $class->_set_error("check_file_limits: $name must be defined");
4171 unless ($opts{$name} == int($opts{$name})) {
4172 $class->_set_error("check_file_limits: $name must be a positive integer");
4177 my $result = i_int_check_image_file_limits(@opts{@check_args});
4179 $class->_set_error($class->_error_as_msg());
4185 # Shortcuts that can be exported
4187 sub newcolor { Imager::Color->new(@_); }
4188 sub newfont { Imager::Font->new(@_); }
4190 require Imager::Color::Float;
4191 return Imager::Color::Float->new(@_);
4194 *NC=*newcolour=*newcolor;
4201 #### Utility routines
4204 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4208 my ($self, $msg) = @_;
4211 $self->{ERRSTR} = $msg;
4219 # Default guess for the type of an image from extension
4221 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4225 ( map { $_ => $_ } @simple_types ),
4231 pnm => "pnm", # technically wrong, but historically it works in Imager
4244 sub def_guess_type {
4247 my ($ext) = $name =~ /\.([^.]+)$/
4250 my $type = $ext_types{$ext}
4257 return @combine_types;
4260 # get the minimum of a list
4264 for(@_) { if ($_<$mx) { $mx=$_; }}
4268 # get the maximum of a list
4272 for(@_) { if ($_>$mx) { $mx=$_; }}
4276 # string stuff for iptc headers
4280 $str = substr($str,3);
4281 $str =~ s/[\n\r]//g;
4288 # A little hack to parse iptc headers.
4293 my($caption,$photogr,$headln,$credit);
4295 my $str=$self->{IPTCRAW};
4300 @ar=split(/8BIM/,$str);
4305 @sar=split(/\034\002/);
4306 foreach $item (@sar) {
4307 if ($item =~ m/^x/) {
4308 $caption = _clean($item);
4311 if ($item =~ m/^P/) {
4312 $photogr = _clean($item);
4315 if ($item =~ m/^i/) {
4316 $headln = _clean($item);
4319 if ($item =~ m/^n/) {
4320 $credit = _clean($item);
4326 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4330 # Inline added a new argument at the beginning
4334 or die "Only C language supported";
4336 require Imager::ExtUtils;
4337 return Imager::ExtUtils->inline_config;
4340 # threads shouldn't try to close raw Imager objects
4341 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4344 # this serves two purposes:
4345 # - a class method to load the file support modules included with Imager
4346 # (or were included, once the library dependent modules are split out)
4347 # - something for Module::ScanDeps to analyze
4348 # https://rt.cpan.org/Ticket/Display.html?id=6566
4351 pop @INC if $INC[-1] eq '.';
4352 eval { require Imager::File::GIF };
4353 eval { require Imager::File::JPEG };
4354 eval { require Imager::File::PNG };
4355 eval { require Imager::File::SGI };
4356 eval { require Imager::File::TIFF };
4357 eval { require Imager::File::ICO };
4358 eval { require Imager::Font::W32 };
4359 eval { require Imager::Font::FT2 };
4360 eval { require Imager::Font::T1 };
4361 eval { require Imager::Color::Table };
4370 my ($class, $fh) = @_;
4373 return $class->new_cb
4378 return print $fh $_[0];
4382 my $count = CORE::read $fh, $tmp, $_[1];
4390 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4391 unless (CORE::seek $fh, $_[0], $_[1]) {
4402 return $class->_new_perlio($fh);
4406 # backward compatibility for %formats
4407 package Imager::FORMATS;
4409 use constant IX_FORMATS => 0;
4410 use constant IX_LIST => 1;
4411 use constant IX_INDEX => 2;
4412 use constant IX_CLASSES => 3;
4415 my ($class, $formats, $classes) = @_;
4417 return bless [ $formats, [ ], 0, $classes ], $class;
4421 my ($self, $key) = @_;
4423 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4426 my $loaded = Imager::_load_file($file, \$error);
4431 if ($error =~ /^Can't locate /) {
4432 $error = "Can't locate $file";
4434 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4437 $self->[IX_FORMATS]{$key} = $value;
4443 my ($self, $key) = @_;
4445 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4447 $self->[IX_CLASSES]{$key} or return undef;
4449 return $self->_check($key);
4453 die "%Imager::formats is not user monifiable";
4457 die "%Imager::formats is not user monifiable";
4461 die "%Imager::formats is not user monifiable";
4465 my ($self, $key) = @_;
4467 if (exists $self->[IX_FORMATS]{$key}) {
4468 my $value = $self->[IX_FORMATS]{$key}
4473 $self->_check($key) or return 1==0;
4481 unless (@{$self->[IX_LIST]}) {
4483 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4484 keys %{$self->[IX_FORMATS]};
4486 for my $key (keys %{$self->[IX_CLASSES]}) {
4487 $self->[IX_FORMATS]{$key} and next;
4489 and push @{$self->[IX_LIST]}, $key;
4493 @{$self->[IX_LIST]} or return;
4494 $self->[IX_INDEX] = 1;
4495 return $self->[IX_LIST][0];
4501 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4504 return $self->[IX_LIST][$self->[IX_INDEX]++];
4510 return scalar @{$self->[IX_LIST]};
4515 # Below is the stub of documentation for your module. You better edit it!
4519 Imager - Perl extension for Generating 24 bit Images
4529 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4534 # see Imager::Files for information on the read() method
4535 my $img = Imager->new(file=>$file)
4536 or die Imager->errstr();
4538 $file =~ s/\.[^.]*$//;
4540 # Create smaller version
4541 # documented in Imager::Transformations
4542 my $thumb = $img->scale(scalefactor=>.3);
4544 # Autostretch individual channels
4545 $thumb->filter(type=>'autolevels');
4547 # try to save in one of these formats
4550 for $format ( qw( png gif jpeg tiff ppm ) ) {
4551 # Check if given format is supported
4552 if ($Imager::formats{$format}) {
4553 $file.="_low.$format";
4554 print "Storing image as: $file\n";
4555 # documented in Imager::Files
4556 $thumb->write(file=>$file) or
4564 Imager is a module for creating and altering images. It can read and
4565 write various image formats, draw primitive shapes like lines,and
4566 polygons, blend multiple images together in various ways, scale, crop,
4567 render text and more.
4569 =head2 Overview of documentation
4575 Imager - This document - Synopsis, Example, Table of Contents and
4580 L<Imager::Install> - installation notes for Imager.
4584 L<Imager::Tutorial> - a brief introduction to Imager.
4588 L<Imager::Cookbook> - how to do various things with Imager.
4592 L<Imager::ImageTypes> - Basics of constructing image objects with
4593 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4594 8/16/double bits/channel, color maps, channel masks, image tags, color
4595 quantization. Also discusses basic image information methods.
4599 L<Imager::Files> - IO interaction, reading/writing images, format
4604 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4609 L<Imager::Color> - Color specification.
4613 L<Imager::Fill> - Fill pattern specification.
4617 L<Imager::Font> - General font rendering, bounding boxes and font
4622 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4623 blending, pasting, convert and map.
4627 L<Imager::Engines> - Programmable transformations through
4628 C<transform()>, C<transform2()> and C<matrix_transform()>.
4632 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4637 L<Imager::Expr> - Expressions for evaluation engine used by
4642 L<Imager::Matrix2d> - Helper class for affine transformations.
4646 L<Imager::Fountain> - Helper for making gradient profiles.
4650 L<Imager::IO> - Imager I/O abstraction.
4654 L<Imager::API> - using Imager's C API
4658 L<Imager::APIRef> - API function reference
4662 L<Imager::Inline> - using Imager's C API from Inline::C
4666 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4670 L<Imager::Security> - brief security notes.
4674 L<Imager::Threads> - brief information on working with threads.
4678 =head2 Basic Overview
4680 An Image object is created with C<$img = Imager-E<gt>new()>.
4683 $img=Imager->new(); # create empty image
4684 $img->read(file=>'lena.png',type=>'png') or # read image from file
4685 die $img->errstr(); # give an explanation
4686 # if something failed
4688 or if you want to create an empty image:
4690 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4692 This example creates a completely black image of width 400 and height
4695 =head1 ERROR HANDLING
4697 In general a method will return false when it fails, if it does use
4698 the C<errstr()> method to find out why:
4704 Returns the last error message in that context.
4706 If the last error you received was from calling an object method, such
4707 as read, call errstr() as an object method to find out why:
4709 my $image = Imager->new;
4710 $image->read(file => 'somefile.gif')
4711 or die $image->errstr;
4713 If it was a class method then call errstr() as a class method:
4715 my @imgs = Imager->read_multi(file => 'somefile.gif')
4716 or die Imager->errstr;
4718 Note that in some cases object methods are implemented in terms of
4719 class methods so a failing object method may set both.
4723 The C<Imager-E<gt>new> method is described in detail in
4724 L<Imager::ImageTypes>.
4728 Where to find information on methods for Imager class objects.
4730 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4733 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4735 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4738 alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
4739 channel index of the alpha channel (if any).
4741 arc() - L<Imager::Draw/arc()> - draw a filled arc
4743 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4746 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4748 check_file_limits() - L<Imager::Files/check_file_limits()>
4750 circle() - L<Imager::Draw/circle()> - draw a filled circle
4752 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4755 colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
4756 of channels used for color.
4758 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4759 colors in an image's palette (paletted images only)
4761 colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
4764 combine() - L<Imager::Transformations/combine()> - combine channels
4765 from one or more images.
4767 combines() - L<Imager::Draw/combines()> - return a list of the
4768 different combine type keywords
4770 compose() - L<Imager::Transformations/compose()> - compose one image
4773 convert() - L<Imager::Transformations/convert()> - transform the color
4776 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4779 crop() - L<Imager::Transformations/crop()> - extract part of an image
4781 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4782 used to guess the output file format based on the output file name
4784 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4786 difference() - L<Imager::Filters/difference()> - produce a difference
4787 images from two input images.
4789 errstr() - L</errstr()> - the error from the last failed operation.
4791 filter() - L<Imager::Filters/filter()> - image filtering
4793 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4794 palette, if it has one
4796 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4799 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4802 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4803 samples per pixel for an image
4805 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4806 different colors used by an image (works for direct color images)
4808 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4809 palette, if it has one
4811 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4813 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4815 get_file_limits() - L<Imager::Files/get_file_limits()>
4817 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4820 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4822 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4825 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4826 row or partial row of pixels.
4828 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4829 row or partial row of pixels.
4831 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4834 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4837 init() - L<Imager::ImageTypes/init()>
4839 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4840 image write functions should write the image in their bilevel (blank
4841 and white, no gray levels) format
4843 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4846 line() - L<Imager::Draw/line()> - draw an interval
4848 load_plugin() - L<Imager::Filters/load_plugin()>
4850 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4853 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4854 color palette from one or more input images.
4856 map() - L<Imager::Transformations/map()> - remap color
4859 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4861 matrix_transform() - L<Imager::Engines/matrix_transform()>
4863 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4865 NC() - L<Imager::Handy/NC()>
4867 NCF() - L<Imager::Handy/NCF()>
4869 new() - L<Imager::ImageTypes/new()>
4871 newcolor() - L<Imager::Handy/newcolor()>
4873 newcolour() - L<Imager::Handy/newcolour()>
4875 newfont() - L<Imager::Handy/newfont()>
4877 NF() - L<Imager::Handy/NF()>
4879 open() - L<Imager::Files/read()> - an alias for read()
4881 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4885 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4888 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4891 polygon() - L<Imager::Draw/polygon()>
4893 polyline() - L<Imager::Draw/polyline()>
4895 polypolygon() - L<Imager::Draw/polypolygon()>
4897 preload() - L<Imager::Files/preload()>
4899 read() - L<Imager::Files/read()> - read a single image from an image file
4901 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4904 read_types() - L<Imager::Files/read_types()> - list image types Imager
4907 register_filter() - L<Imager::Filters/register_filter()>
4909 register_reader() - L<Imager::Files/register_reader()>
4911 register_writer() - L<Imager::Files/register_writer()>
4913 rotate() - L<Imager::Transformations/rotate()>
4915 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4916 onto an image and use the alpha channel
4918 scale() - L<Imager::Transformations/scale()>
4920 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4922 scaleX() - L<Imager::Transformations/scaleX()>
4924 scaleY() - L<Imager::Transformations/scaleY()>
4926 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4929 set_file_limits() - L<Imager::Files/set_file_limits()>
4931 setmask() - L<Imager::ImageTypes/setmask()>
4933 setpixel() - L<Imager::Draw/setpixel()>
4935 setsamples() - L<Imager::Draw/setsamples()>
4937 setscanline() - L<Imager::Draw/setscanline()>
4939 settag() - L<Imager::ImageTypes/settag()>
4941 string() - L<Imager::Draw/string()> - draw text on an image
4943 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4945 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4947 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4949 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4951 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4952 double per sample image.
4954 transform() - L<Imager::Engines/"transform()">
4956 transform2() - L<Imager::Engines/"transform2()">
4958 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4960 unload_plugin() - L<Imager::Filters/unload_plugin()>
4962 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4965 write() - L<Imager::Files/write()> - write an image to a file
4967 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4970 write_types() - L<Imager::Files/read_types()> - list image types Imager
4973 =head1 CONCEPT INDEX
4975 animated GIF - L<Imager::Files/"Writing an animated GIF">
4977 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4978 L<Imager::ImageTypes/"Common Tags">.
4980 blend - alpha blending one image onto another
4981 L<Imager::Transformations/rubthrough()>
4983 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4985 boxes, drawing - L<Imager::Draw/box()>
4987 changes between image - L<Imager::Filters/"Image Difference">
4989 channels, combine into one image - L<Imager::Transformations/combine()>
4991 color - L<Imager::Color>
4993 color names - L<Imager::Color>, L<Imager::Color::Table>
4995 combine modes - L<Imager::Draw/"Combine Types">
4997 compare images - L<Imager::Filters/"Image Difference">
4999 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
5001 convolution - L<Imager::Filters/conv>
5003 cropping - L<Imager::Transformations/crop()>
5005 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5007 C<diff> images - L<Imager::Filters/"Image Difference">
5009 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
5010 L<Imager::Cookbook/"Image spatial resolution">
5012 drawing boxes - L<Imager::Draw/box()>
5014 drawing lines - L<Imager::Draw/line()>
5016 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
5018 error message - L</"ERROR HANDLING">
5020 files, font - L<Imager::Font>
5022 files, image - L<Imager::Files>
5024 filling, types of fill - L<Imager::Fill>
5026 filling, boxes - L<Imager::Draw/box()>
5028 filling, flood fill - L<Imager::Draw/flood_fill()>
5030 flood fill - L<Imager::Draw/flood_fill()>
5032 fonts - L<Imager::Font>
5034 fonts, drawing with - L<Imager::Draw/string()>,
5035 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
5037 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5039 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
5041 fountain fill - L<Imager::Fill/"Fountain fills">,
5042 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5043 L<Imager::Filters/gradgen>
5045 GIF files - L<Imager::Files/"GIF">
5047 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
5049 gradient fill - L<Imager::Fill/"Fountain fills">,
5050 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5051 L<Imager::Filters/gradgen>
5053 gray scale, convert image to - L<Imager::Transformations/convert()>
5055 gaussian blur - L<Imager::Filters/gaussian>
5057 hatch fills - L<Imager::Fill/"Hatched fills">
5059 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5061 invert image - L<Imager::Filters/hardinvert>,
5062 L<Imager::Filters/hardinvertall>
5064 JPEG - L<Imager::Files/"JPEG">
5066 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
5068 lines, drawing - L<Imager::Draw/line()>
5070 matrix - L<Imager::Matrix2d>,
5071 L<Imager::Engines/"Matrix Transformations">,
5072 L<Imager::Font/transform()>
5074 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5076 mosaic - L<Imager::Filters/mosaic>
5078 noise, filter - L<Imager::Filters/noise>
5080 noise, rendered - L<Imager::Filters/turbnoise>,
5081 L<Imager::Filters/radnoise>
5083 paste - L<Imager::Transformations/paste()>,
5084 L<Imager::Transformations/rubthrough()>
5086 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5087 L<Imager::ImageTypes/new()>
5089 =for stopwords posterize
5091 posterize - L<Imager::Filters/postlevels>
5093 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5095 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5097 rectangles, drawing - L<Imager::Draw/box()>
5099 resizing an image - L<Imager::Transformations/scale()>,
5100 L<Imager::Transformations/crop()>
5102 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5104 saving an image - L<Imager::Files>
5106 scaling - L<Imager::Transformations/scale()>
5108 security - L<Imager::Security>
5110 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5112 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
5114 size, image - L<Imager::ImageTypes/getwidth()>,
5115 L<Imager::ImageTypes/getheight()>
5117 size, text - L<Imager::Font/bounding_box()>
5119 tags, image metadata - L<Imager::ImageTypes/"Tags">
5121 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5122 L<Imager::Font::Wrap>
5124 text, wrapping text in an area - L<Imager::Font::Wrap>
5126 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5128 threads - L<Imager::Threads>
5130 tiles, color - L<Imager::Filters/mosaic>
5132 transparent images - L<Imager::ImageTypes>,
5133 L<Imager::Cookbook/"Transparent PNG">
5135 =for stopwords unsharp
5137 unsharp mask - L<Imager::Filters/unsharpmask>
5139 watermark - L<Imager::Filters/watermark>
5141 writing an image to a file - L<Imager::Files>
5145 The best place to get help with Imager is the mailing list.
5147 To subscribe send a message with C<subscribe> in the body to:
5149 imager-devel+request@molar.is
5155 L<http://www.molar.is/en/lists/imager-devel/>
5159 where you can also find the mailing list archive.
5161 You can report bugs by pointing your browser at:
5165 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5169 or by sending an email to:
5173 bug-Imager@rt.cpan.org
5177 Please remember to include the versions of Imager, perl, supporting
5178 libraries, and any relevant code. If you have specific images that
5179 cause the problems, please include those too.
5181 If you don't want to publish your email address on a mailing list you
5182 can use CPAN::Forum:
5184 http://www.cpanforum.com/dist/Imager
5186 You will need to register to post.
5188 =head1 CONTRIBUTING TO IMAGER
5194 If you like or dislike Imager, you can add a public review of Imager
5197 http://cpanratings.perl.org/dist/Imager
5199 =for stopwords Bitcard
5201 This requires a Bitcard account (http://www.bitcard.org).
5203 You can also send email to the maintainer below.
5205 If you send me a bug report via email, it will be copied to Request
5210 I accept patches, preferably against the master branch in git. Please
5211 include an explanation of the reason for why the patch is needed or
5214 Your patch should include regression tests where possible, otherwise
5215 it will be delayed until I get a chance to write them.
5217 To browse Imager's git repository:
5219 http://git.imager.perl.org/imager.git
5223 git clone git://git.imager.perl.org/imager.git
5225 My preference is that patches are provided in the format produced by
5226 C<git format-patch>, for example, if you made your changes in a branch
5227 from master you might do:
5229 git format-patch -k --stdout master >my-patch.txt
5231 and then attach that to your bug report, either by adding it as an
5232 attachment in your email client, or by using the Request Tracker
5233 attachment mechanism.
5237 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5239 Arnar M. Hrafnkelsson is the original author of Imager.
5241 Many others have contributed to Imager, please see the C<README> for a
5246 Imager is licensed under the same terms as perl itself.
5249 makeblendedfont Fontforge
5251 A test font, generated by the Debian packaged Fontforge,
5252 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5253 copyrighted by Adobe. See F<adobe.txt> in the source for license
5258 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5259 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5260 L<Imager::Font>(3), L<Imager::Transformations>(3),
5261 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5262 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5264 L<http://imager.perl.org/>
5266 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5268 Other perl imaging modules include:
5270 L<GD>(3), L<Image::Magick>(3),
5271 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5272 L<Prima::Image>, L<IPA>.
5274 For manipulating image metadata see L<Image::ExifTool>.
5276 If you're trying to use Imager for array processing, you should
5277 probably using L<PDL>.