4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
109 # registered file readers
112 # registered file writers
115 # modules we attempted to autoload
116 my %attempted_to_load;
118 # errors from loading files
119 my %file_load_errors;
121 # what happened when we tried to load
122 my %reader_load_errors;
123 my %writer_load_errors;
125 # library keys that are image file formats
126 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
128 # image pixel combine types
130 qw/none normal multiply dissolve add subtract diff lighten darken
131 hue saturation value color/;
133 @combine_types{@combine_types} = 0 .. $#combine_types;
134 $combine_types{mult} = $combine_types{multiply};
135 $combine_types{'sub'} = $combine_types{subtract};
136 $combine_types{sat} = $combine_types{saturation};
138 # this will be used to store global defaults at some point
143 my $ex_version = eval $Exporter::VERSION;
144 if ($ex_version < 5.57) {
149 XSLoader::load(Imager => $VERSION);
155 png => "Imager::File::PNG",
156 gif => "Imager::File::GIF",
157 tiff => "Imager::File::TIFF",
158 jpeg => "Imager::File::JPEG",
159 w32 => "Imager::Font::W32",
160 ft2 => "Imager::Font::FT2",
161 t1 => "Imager::Font::T1",
164 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
167 for(i_list_formats()) { $formats_low{$_}++; }
169 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
173 # the members of the subhashes under %filters are:
174 # callseq - a list of the parameters to the underlying filter in the
175 # order they are passed
176 # callsub - a code ref that takes a named parameter list and calls the
178 # defaults - a hash of default values
179 # names - defines names for value of given parameters so if the names
180 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
181 # foo parameter, the filter will receive 1 for the foo
184 callseq => ['image','intensity'],
185 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
189 callseq => ['image', 'amount', 'subtype'],
190 defaults => { amount=>3,subtype=>0 },
191 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
194 $filters{hardinvert} ={
195 callseq => ['image'],
197 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
200 $filters{hardinvertall} =
202 callseq => ['image'],
204 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
207 $filters{autolevels_skew} ={
208 callseq => ['image','lsat','usat','skew'],
209 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
210 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
213 $filters{autolevels} ={
214 callseq => ['image','lsat','usat'],
215 defaults => { lsat=>0.1,usat=>0.1 },
216 callsub => sub { my %hsh=@_; i_autolevels_mono($hsh{image},$hsh{lsat},$hsh{usat}); }
219 $filters{turbnoise} ={
220 callseq => ['image'],
221 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
222 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
225 $filters{radnoise} ={
226 callseq => ['image'],
227 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
228 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
233 callseq => ['image', 'coef'],
238 i_conv($hsh{image},$hsh{coef})
239 or die Imager->_error_as_msg() . "\n";
245 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
246 defaults => { dist => 0 },
250 my @colors = @{$hsh{colors}};
253 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
257 $filters{nearest_color} =
259 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
264 # make sure the segments are specified with colors
266 for my $color (@{$hsh{colors}}) {
267 my $new_color = _color($color)
268 or die $Imager::ERRSTR."\n";
269 push @colors, $new_color;
272 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
274 or die Imager->_error_as_msg() . "\n";
277 $filters{gaussian} = {
278 callseq => [ 'image', 'stddev' ],
280 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
284 callseq => [ qw(image size) ],
285 defaults => { size => 20 },
286 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
290 callseq => [ qw(image bump elevation lightx lighty st) ],
291 defaults => { elevation=>0, st=> 2 },
294 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
295 $hsh{lightx}, $hsh{lighty}, $hsh{st});
298 $filters{bumpmap_complex} =
300 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
317 for my $cname (qw/Ia Il Is/) {
318 my $old = $hsh{$cname};
319 my $new_color = _color($old)
320 or die $Imager::ERRSTR, "\n";
321 $hsh{$cname} = $new_color;
323 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
324 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
325 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
329 $filters{postlevels} =
331 callseq => [ qw(image levels) ],
332 defaults => { levels => 10 },
333 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
335 $filters{watermark} =
337 callseq => [ qw(image wmark tx ty pixdiff) ],
338 defaults => { pixdiff=>10, tx=>0, ty=>0 },
342 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
348 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
350 ftype => { linear => 0,
356 repeat => { none => 0,
371 multiply => 2, mult => 2,
374 subtract => 5, 'sub' => 5,
384 defaults => { ftype => 0, repeat => 0, combine => 0,
385 super_sample => 0, ssample_param => 4,
398 # make sure the segments are specified with colors
400 for my $segment (@{$hsh{segments}}) {
401 my @new_segment = @$segment;
403 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
404 push @segments, \@new_segment;
407 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
408 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
409 $hsh{ssample_param}, \@segments)
410 or die Imager->_error_as_msg() . "\n";
413 $filters{unsharpmask} =
415 callseq => [ qw(image stddev scale) ],
416 defaults => { stddev=>2.0, scale=>1.0 },
420 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
424 $FORMATGUESS=\&def_guess_type;
434 # NOTE: this might be moved to an import override later on
439 if ($_[$i] eq '-log-stderr') {
447 goto &Exporter::import;
451 Imager->open_log(log => $_[0], level => $_[1]);
456 my %parms=(loglevel=>1,@_);
458 if (exists $parms{'warn_obsolete'}) {
459 $warn_obsolete = $parms{'warn_obsolete'};
463 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
467 if (exists $parms{'t1log'}) {
469 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
470 Imager->_set_error(Imager->_error_as_msg);
484 my (%opts) = ( loglevel => 1, @_ );
486 $is_logging = i_init_log($opts{log}, $opts{loglevel});
487 unless ($is_logging) {
488 Imager->_set_error(Imager->_error_as_msg());
492 Imager->log("Imager $VERSION starting\n", 1);
498 i_init_log(undef, -1);
503 my ($class, $message, $level) = @_;
505 defined $level or $level = 1;
507 i_log_entry($message, $level);
517 print "shutdown code\n";
518 # for(keys %instances) { $instances{$_}->DESTROY(); }
519 malloc_state(); # how do decide if this should be used? -- store something from the import
520 print "Imager exiting\n";
524 # Load a filter plugin
530 if ($^O eq 'android') {
532 $filename = File::Spec->rel2abs($filename);
535 my ($DSO_handle,$str)=DSO_open($filename);
536 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
537 my %funcs=DSO_funclist($DSO_handle);
538 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
540 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
542 $DSOs{$filename}=[$DSO_handle,\%funcs];
545 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
546 $DEBUG && print "eval string:\n",$evstr,"\n";
558 if ($^O eq 'android') {
560 $filename = File::Spec->rel2abs($filename);
563 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
564 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
565 for(keys %{$funcref}) {
567 $DEBUG && print "unloading: $_\n";
569 my $rc=DSO_close($DSO_handle);
570 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
574 # take the results of i_error() and make a message out of it
576 return join(": ", map $_->[0], i_errors());
579 # this function tries to DWIM for color parameters
580 # color objects are used as is
581 # simple scalars are simply treated as single parameters to Imager::Color->new
582 # hashrefs are treated as named argument lists to Imager::Color->new
583 # arrayrefs are treated as list arguments to Imager::Color->new iff any
585 # other arrayrefs are treated as list arguments to Imager::Color::Float
589 # perl 5.6.0 seems to do weird things to $arg if we don't make an
590 # explicitly stringified copy
591 # I vaguely remember a bug on this on p5p, but couldn't find it
592 # through bugs.perl.org (I had trouble getting it to find any bugs)
593 my $copy = $arg . "";
597 if (UNIVERSAL::isa($arg, "Imager::Color")
598 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
602 if ($copy =~ /^HASH\(/) {
603 $result = Imager::Color->new(%$arg);
605 elsif ($copy =~ /^ARRAY\(/) {
606 $result = Imager::Color->new(@$arg);
609 $Imager::ERRSTR = "Not a color";
614 # assume Imager::Color::new knows how to handle it
615 $result = Imager::Color->new($arg);
622 my ($self, $combine, $default) = @_;
624 if (!defined $combine && ref $self) {
625 $combine = $self->{combine};
627 defined $combine or $combine = $defaults{combine};
628 defined $combine or $combine = $default;
630 if (exists $combine_types{$combine}) {
631 $combine = $combine_types{$combine};
638 my ($self, $method) = @_;
640 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
642 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
643 $msg = "$method: $msg" if $method;
644 $self->_set_error($msg);
649 # returns first defined parameter
652 return $_ if defined $_;
658 # Methods to be called on objects.
661 # Create a new Imager object takes very few parameters.
662 # usually you call this method and then call open from
663 # the resulting object
670 $self->{IMG}=undef; # Just to indicate what exists
671 $self->{ERRSTR}=undef; #
672 $self->{DEBUG}=$DEBUG;
673 $self->{DEBUG} and print "Initialized Imager\n";
674 if (defined $hsh{xsize} || defined $hsh{ysize}) {
675 unless ($self->img_set(%hsh)) {
676 $Imager::ERRSTR = $self->{ERRSTR};
680 elsif (defined $hsh{file} ||
683 defined $hsh{callback} ||
684 defined $hsh{readcb} ||
685 defined $hsh{data}) {
686 # allow $img = Imager->new(file => $filename)
689 # type is already used as a parameter to new(), rename it for the
691 if ($hsh{filetype}) {
692 $extras{type} = $hsh{filetype};
694 unless ($self->read(%hsh, %extras)) {
695 $Imager::ERRSTR = $self->{ERRSTR};
700 Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
707 # Copy an entire image with no changes
708 # - if an image has magic the copy of it will not be magical
713 $self->_valid_image("copy")
716 unless (defined wantarray) {
718 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
722 my $newcopy=Imager->new();
723 $newcopy->{IMG} = i_copy($self->{IMG});
732 $self->_valid_image("paste")
735 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
736 my $src = $input{img} || $input{src};
738 $self->_set_error("no source image");
741 unless ($src->_valid_image("paste")) {
742 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
745 $input{left}=0 if $input{left} <= 0;
746 $input{top}=0 if $input{top} <= 0;
748 my($r,$b)=i_img_info($src->{IMG});
749 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
750 my ($src_right, $src_bottom);
751 if ($input{src_coords}) {
752 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
755 if (defined $input{src_maxx}) {
756 $src_right = $input{src_maxx};
758 elsif (defined $input{width}) {
759 if ($input{width} <= 0) {
760 $self->_set_error("paste: width must me positive");
763 $src_right = $src_left + $input{width};
768 if (defined $input{src_maxy}) {
769 $src_bottom = $input{src_maxy};
771 elsif (defined $input{height}) {
772 if ($input{height} < 0) {
773 $self->_set_error("paste: height must be positive");
776 $src_bottom = $src_top + $input{height};
783 $src_right > $r and $src_right = $r;
784 $src_bottom > $b and $src_bottom = $b;
786 if ($src_right <= $src_left
787 || $src_bottom < $src_top) {
788 $self->_set_error("nothing to paste");
792 i_copyto($self->{IMG}, $src->{IMG},
793 $src_left, $src_top, $src_right, $src_bottom,
794 $input{left}, $input{top});
796 return $self; # What should go here??
799 # Crop an image - i.e. return a new image that is smaller
804 $self->_valid_image("crop")
807 unless (defined wantarray) {
809 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
815 my ($w, $h, $l, $r, $b, $t) =
816 @hsh{qw(width height left right bottom top)};
818 # work through the various possibilities
823 elsif (!defined $r) {
824 $r = $self->getwidth;
836 $l = int(0.5+($self->getwidth()-$w)/2);
841 $r = $self->getwidth;
847 elsif (!defined $b) {
848 $b = $self->getheight;
860 $t=int(0.5+($self->getheight()-$h)/2);
865 $b = $self->getheight;
868 ($l,$r)=($r,$l) if $l>$r;
869 ($t,$b)=($b,$t) if $t>$b;
872 $r > $self->getwidth and $r = $self->getwidth;
874 $b > $self->getheight and $b = $self->getheight;
876 if ($l == $r || $t == $b) {
877 $self->_set_error("resulting image would have no content");
880 if( $r < $l or $b < $t ) {
881 $self->_set_error("attempting to crop outside of the image");
884 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
886 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
891 my ($self, %opts) = @_;
896 my $x = $opts{xsize} || $self->getwidth;
897 my $y = $opts{ysize} || $self->getheight;
898 my $channels = $opts{channels} || $self->getchannels;
900 my $out = Imager->new;
901 if ($channels == $self->getchannels) {
902 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
905 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
907 unless ($out->{IMG}) {
908 $self->{ERRSTR} = $self->_error_as_msg;
915 # Sets an image to a certain size and channel number
916 # if there was previously data in the image it is discarded
929 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
934 if (my $channels = $model_channels{$hsh{model}}) {
935 $hsh{channels} = $channels;
938 $self->_set_error("new: unknown value for model '$hsh{model}'");
943 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
944 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
945 $hsh{maxcolors} || 256);
947 elsif ($hsh{bits} eq 'double') {
948 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
950 elsif ($hsh{bits} == 16) {
951 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
954 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
958 unless ($self->{IMG}) {
959 $self->_set_error(Imager->_error_as_msg());
966 # created a masked version of the current image
970 $self->_valid_image("masked")
973 my %opts = (left => 0,
975 right => $self->getwidth,
976 bottom => $self->getheight,
978 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
980 my $result = Imager->new;
981 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
982 $opts{top}, $opts{right} - $opts{left},
983 $opts{bottom} - $opts{top});
984 unless ($result->{IMG}) {
985 $self->_set_error(Imager->_error_as_msg);
989 # keep references to the mask and base images so they don't
991 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
996 # convert an RGB image into a paletted image
1000 if (@_ != 1 && !ref $_[0]) {
1007 unless (defined wantarray) {
1008 my @caller = caller;
1009 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
1013 $self->_valid_image("to_paletted")
1016 my $result = Imager->new;
1017 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1018 $self->_set_error(Imager->_error_as_msg);
1026 my ($class, $quant, @images) = @_;
1029 Imager->_set_error("make_palette: supply at least one image");
1033 for my $img (@images) {
1034 unless ($img->{IMG}) {
1035 Imager->_set_error("make_palette: image $index is empty");
1041 return i_img_make_palette($quant, map $_->{IMG}, @images);
1044 # convert a paletted (or any image) to an 8-bit/channel RGB image
1048 unless (defined wantarray) {
1049 my @caller = caller;
1050 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1054 $self->_valid_image("to_rgb8")
1057 my $result = Imager->new;
1058 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1059 $self->_set_error(Imager->_error_as_msg());
1066 # convert a paletted (or any image) to a 16-bit/channel RGB image
1070 unless (defined wantarray) {
1071 my @caller = caller;
1072 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1076 $self->_valid_image("to_rgb16")
1079 my $result = Imager->new;
1080 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1081 $self->_set_error(Imager->_error_as_msg());
1088 # convert a paletted (or any image) to an double/channel RGB image
1092 unless (defined wantarray) {
1093 my @caller = caller;
1094 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1098 $self->_valid_image("to_rgb_double")
1101 my $result = Imager->new;
1102 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1103 $self->_set_error(Imager->_error_as_msg());
1112 my %opts = (colors=>[], @_);
1114 $self->_valid_image("addcolors")
1117 my @colors = @{$opts{colors}}
1120 for my $color (@colors) {
1121 $color = _color($color);
1123 $self->_set_error($Imager::ERRSTR);
1128 return i_addcolors($self->{IMG}, @colors);
1133 my %opts = (start=>0, colors=>[], @_);
1135 $self->_valid_image("setcolors")
1138 my @colors = @{$opts{colors}}
1141 for my $color (@colors) {
1142 $color = _color($color);
1144 $self->_set_error($Imager::ERRSTR);
1149 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1156 $self->_valid_image("getcolors")
1159 if (!exists $opts{start} && !exists $opts{count}) {
1162 $opts{count} = $self->colorcount;
1164 elsif (!exists $opts{count}) {
1167 elsif (!exists $opts{start}) {
1171 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1177 $self->_valid_image("colorcount")
1180 return i_colorcount($self->{IMG});
1186 $self->_valid_image("maxcolors")
1189 i_maxcolors($self->{IMG});
1196 $self->_valid_image("findcolor")
1199 unless ($opts{color}) {
1200 $self->_set_error("findcolor: no color parameter");
1204 my $color = _color($opts{color})
1207 return i_findcolor($self->{IMG}, $color);
1213 $self->_valid_image("bits")
1216 my $bits = i_img_bits($self->{IMG});
1217 if ($bits && $bits == length(pack("d", 1)) * 8) {
1226 $self->_valid_image("type")
1229 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1235 $self->_valid_image("virtual")
1238 return i_img_virtual($self->{IMG});
1244 $self->_valid_image("is_bilevel")
1247 return i_img_is_monochrome($self->{IMG});
1251 my ($self, %opts) = @_;
1253 $self->_valid_image("tags")
1256 if (defined $opts{name}) {
1260 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1261 push @result, (i_tags_get($self->{IMG}, $found))[1];
1264 return wantarray ? @result : $result[0];
1266 elsif (defined $opts{code}) {
1270 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1271 push @result, (i_tags_get($self->{IMG}, $found))[1];
1278 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1281 return i_tags_count($self->{IMG});
1290 $self->_valid_image("addtag")
1294 if (defined $opts{value}) {
1295 if ($opts{value} =~ /^\d+$/) {
1297 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1300 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1303 elsif (defined $opts{data}) {
1304 # force addition as a string
1305 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1308 $self->{ERRSTR} = "No value supplied";
1312 elsif ($opts{code}) {
1313 if (defined $opts{value}) {
1314 if ($opts{value} =~ /^\d+$/) {
1316 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1319 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1322 elsif (defined $opts{data}) {
1323 # force addition as a string
1324 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1327 $self->{ERRSTR} = "No value supplied";
1340 $self->_valid_image("deltag")
1343 if (defined $opts{'index'}) {
1344 return i_tags_delete($self->{IMG}, $opts{'index'});
1346 elsif (defined $opts{name}) {
1347 return i_tags_delbyname($self->{IMG}, $opts{name});
1349 elsif (defined $opts{code}) {
1350 return i_tags_delbycode($self->{IMG}, $opts{code});
1353 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1359 my ($self, %opts) = @_;
1361 $self->_valid_image("settag")
1365 $self->deltag(name=>$opts{name});
1366 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1368 elsif (defined $opts{code}) {
1369 $self->deltag(code=>$opts{code});
1370 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1378 sub _get_reader_io {
1379 my ($self, $input) = @_;
1382 return $input->{io}, undef;
1384 elsif ($input->{fd}) {
1385 return io_new_fd($input->{fd});
1387 elsif ($input->{fh}) {
1388 unless (Scalar::Util::openhandle($input->{fh})) {
1389 $self->_set_error("Handle in fh option not opened");
1392 return Imager::IO->new_fh($input->{fh});
1394 elsif ($input->{file}) {
1395 my $file = IO::File->new($input->{file}, "r");
1397 $self->_set_error("Could not open $input->{file}: $!");
1401 return (io_new_fd(fileno($file)), $file);
1403 elsif ($input->{data}) {
1404 return io_new_buffer($input->{data});
1406 elsif ($input->{callback} || $input->{readcb}) {
1407 if (!$input->{seekcb}) {
1408 $self->_set_error("Need a seekcb parameter");
1410 if ($input->{maxbuffer}) {
1411 return io_new_cb($input->{writecb},
1412 $input->{callback} || $input->{readcb},
1413 $input->{seekcb}, $input->{closecb},
1414 $input->{maxbuffer});
1417 return io_new_cb($input->{writecb},
1418 $input->{callback} || $input->{readcb},
1419 $input->{seekcb}, $input->{closecb});
1423 $self->_set_error("file/fd/fh/data/callback parameter missing");
1428 sub _get_writer_io {
1429 my ($self, $input) = @_;
1431 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1438 elsif ($input->{fd}) {
1439 $io = io_new_fd($input->{fd});
1441 elsif ($input->{fh}) {
1442 unless (Scalar::Util::openhandle($input->{fh})) {
1443 $self->_set_error("Handle in fh option not opened");
1446 $io = Imager::IO->new_fh($input->{fh});
1448 elsif ($input->{file}) {
1449 my $fh = new IO::File($input->{file},"w+");
1451 $self->_set_error("Could not open file $input->{file}: $!");
1454 binmode($fh) or die;
1455 $io = io_new_fd(fileno($fh));
1458 elsif ($input->{data}) {
1459 $io = io_new_bufchain();
1461 elsif ($input->{callback} || $input->{writecb}) {
1462 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1465 $io = io_new_cb($input->{callback} || $input->{writecb},
1467 $input->{seekcb}, $input->{closecb});
1470 $self->_set_error("file/fd/fh/data/callback parameter missing");
1474 unless ($buffered) {
1475 $io->set_buffered(0);
1478 return ($io, @extras);
1481 # Read an image from file
1487 if (defined($self->{IMG})) {
1488 # let IIM_DESTROY do the destruction, since the image may be
1489 # referenced from elsewhere
1490 #i_img_destroy($self->{IMG});
1491 undef($self->{IMG});
1494 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1496 my $type = $input{'type'};
1498 $type = i_test_format_probe($IO, -1);
1501 if ($input{file} && !$type) {
1503 $type = $FORMATGUESS->($input{file});
1507 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1508 $input{file} and $msg .= " or file name";
1509 $self->_set_error($msg);
1513 _reader_autoload($type);
1515 if ($readers{$type} && $readers{$type}{single}) {
1516 return $readers{$type}{single}->($self, $IO, %input);
1519 unless ($formats_low{$type}) {
1520 my $read_types = join ', ', sort Imager->read_types();
1521 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1525 my $allow_incomplete = $input{allow_incomplete};
1526 defined $allow_incomplete or $allow_incomplete = 0;
1528 if ( $type eq 'pnm' ) {
1529 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1530 if ( !defined($self->{IMG}) ) {
1531 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1534 $self->{DEBUG} && print "loading a pnm file\n";
1538 if ( $type eq 'bmp' ) {
1539 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1540 if ( !defined($self->{IMG}) ) {
1541 $self->{ERRSTR}=$self->_error_as_msg();
1544 $self->{DEBUG} && print "loading a bmp file\n";
1547 if ( $type eq 'tga' ) {
1548 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1549 if ( !defined($self->{IMG}) ) {
1550 $self->{ERRSTR}=$self->_error_as_msg();
1553 $self->{DEBUG} && print "loading a tga file\n";
1556 if ( $type eq 'raw' ) {
1557 unless ( $input{xsize} && $input{ysize} ) {
1558 $self->_set_error('missing xsize or ysize parameter for raw');
1562 my $interleave = _first($input{raw_interleave}, $input{interleave});
1563 unless (defined $interleave) {
1564 my @caller = caller;
1565 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1568 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1569 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1571 $self->{IMG} = i_readraw_wiol( $IO,
1577 if ( !defined($self->{IMG}) ) {
1578 $self->{ERRSTR}=$self->_error_as_msg();
1581 $self->{DEBUG} && print "loading a raw file\n";
1587 sub register_reader {
1588 my ($class, %opts) = @_;
1591 or die "register_reader called with no type parameter\n";
1593 my $type = $opts{type};
1595 defined $opts{single} || defined $opts{multiple}
1596 or die "register_reader called with no single or multiple parameter\n";
1598 $readers{$type} = { };
1599 if ($opts{single}) {
1600 $readers{$type}{single} = $opts{single};
1602 if ($opts{multiple}) {
1603 $readers{$type}{multiple} = $opts{multiple};
1609 sub register_writer {
1610 my ($class, %opts) = @_;
1613 or die "register_writer called with no type parameter\n";
1615 my $type = $opts{type};
1617 defined $opts{single} || defined $opts{multiple}
1618 or die "register_writer called with no single or multiple parameter\n";
1620 $writers{$type} = { };
1621 if ($opts{single}) {
1622 $writers{$type}{single} = $opts{single};
1624 if ($opts{multiple}) {
1625 $writers{$type}{multiple} = $opts{multiple};
1636 grep($file_formats{$_}, keys %formats),
1637 qw(ico sgi), # formats not handled directly, but supplied with Imager
1648 grep($file_formats{$_}, keys %formats),
1649 qw(ico sgi), # formats not handled directly, but supplied with Imager
1656 my ($file, $error) = @_;
1658 if ($attempted_to_load{$file}) {
1659 if ($file_load_errors{$file}) {
1660 $$error = $file_load_errors{$file};
1668 local $SIG{__DIE__};
1670 ++$attempted_to_load{$file};
1678 my $work = $@ || "Unknown error";
1680 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1681 $work =~ s/\n/\\n/g;
1682 $work =~ s/\s*\.?\z/ loading $file/;
1683 $file_load_errors{$file} = $work;
1690 # probes for an Imager::File::whatever module
1691 sub _reader_autoload {
1694 return if $formats_low{$type} || $readers{$type};
1696 return unless $type =~ /^\w+$/;
1698 my $file = "Imager/File/\U$type\E.pm";
1701 my $loaded = _load_file($file, \$error);
1702 if (!$loaded && $error =~ /^Can't locate /) {
1703 my $filer = "Imager/File/\U$type\EReader.pm";
1704 $loaded = _load_file($filer, \$error);
1705 if ($error =~ /^Can't locate /) {
1706 $error = "Can't locate $file or $filer";
1710 $reader_load_errors{$type} = $error;
1714 # probes for an Imager::File::whatever module
1715 sub _writer_autoload {
1718 return if $formats_low{$type} || $writers{$type};
1720 return unless $type =~ /^\w+$/;
1722 my $file = "Imager/File/\U$type\E.pm";
1725 my $loaded = _load_file($file, \$error);
1726 if (!$loaded && $error =~ /^Can't locate /) {
1727 my $filew = "Imager/File/\U$type\EWriter.pm";
1728 $loaded = _load_file($filew, \$error);
1729 if ($error =~ /^Can't locate /) {
1730 $error = "Can't locate $file or $filew";
1734 $writer_load_errors{$type} = $error;
1738 sub _fix_gif_positions {
1739 my ($opts, $opt, $msg, @imgs) = @_;
1741 my $positions = $opts->{'gif_positions'};
1743 for my $pos (@$positions) {
1744 my ($x, $y) = @$pos;
1745 my $img = $imgs[$index++];
1746 $img->settag(name=>'gif_left', value=>$x);
1747 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1749 $$msg .= "replaced with the gif_left and gif_top tags";
1754 gif_each_palette=>'gif_local_map',
1755 interlace => 'gif_interlace',
1756 gif_delays => 'gif_delay',
1757 gif_positions => \&_fix_gif_positions,
1758 gif_loop_count => 'gif_loop',
1761 # options that should be converted to colors
1762 my %color_opts = map { $_ => 1 } qw/i_background/;
1765 my ($self, $opts, $prefix, @imgs) = @_;
1767 for my $opt (keys %$opts) {
1769 if ($obsolete_opts{$opt}) {
1770 my $new = $obsolete_opts{$opt};
1771 my $msg = "Obsolete option $opt ";
1773 $new->($opts, $opt, \$msg, @imgs);
1776 $msg .= "replaced with the $new tag ";
1779 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1780 warn $msg if $warn_obsolete && $^W;
1782 next unless $tagname =~ /^\Q$prefix/;
1783 my $value = $opts->{$opt};
1784 if ($color_opts{$opt}) {
1785 $value = _color($value);
1787 $self->_set_error($Imager::ERRSTR);
1792 if (UNIVERSAL::isa($value, "Imager::Color")) {
1793 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1794 for my $img (@imgs) {
1795 $img->settag(name=>$tagname, value=>$tag);
1798 elsif (ref($value) eq 'ARRAY') {
1799 for my $i (0..$#$value) {
1800 my $val = $value->[$i];
1802 if (UNIVERSAL::isa($val, "Imager::Color")) {
1803 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1805 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1808 $self->_set_error("Unknown reference type " . ref($value) .
1809 " supplied in array for $opt");
1815 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1820 $self->_set_error("Unknown reference type " . ref($value) .
1821 " supplied for $opt");
1826 # set it as a tag for every image
1827 for my $img (@imgs) {
1828 $img->settag(name=>$tagname, value=>$value);
1836 # Write an image to file
1839 my %input=(jpegquality=>75,
1849 $self->_valid_image("write")
1852 $self->_set_opts(\%input, "i_", $self)
1855 my $type = $input{'type'};
1856 if (!$type and $input{file}) {
1857 $type = $FORMATGUESS->($input{file});
1860 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1864 _writer_autoload($type);
1867 if ($writers{$type} && $writers{$type}{single}) {
1868 ($IO, $fh) = $self->_get_writer_io(\%input)
1871 $writers{$type}{single}->($self, $IO, %input, type => $type)
1875 if (!$formats_low{$type}) {
1876 my $write_types = join ', ', sort Imager->write_types();
1877 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1881 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1884 if ( $type eq 'pnm' ) {
1885 $self->_set_opts(\%input, "pnm_", $self)
1887 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1888 $self->{ERRSTR} = $self->_error_as_msg();
1891 $self->{DEBUG} && print "writing a pnm file\n";
1893 elsif ( $type eq 'raw' ) {
1894 $self->_set_opts(\%input, "raw_", $self)
1896 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1897 $self->{ERRSTR} = $self->_error_as_msg();
1900 $self->{DEBUG} && print "writing a raw file\n";
1902 elsif ( $type eq 'bmp' ) {
1903 $self->_set_opts(\%input, "bmp_", $self)
1905 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1906 $self->{ERRSTR} = $self->_error_as_msg;
1909 $self->{DEBUG} && print "writing a bmp file\n";
1911 elsif ( $type eq 'tga' ) {
1912 $self->_set_opts(\%input, "tga_", $self)
1915 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1916 $self->{ERRSTR}=$self->_error_as_msg();
1919 $self->{DEBUG} && print "writing a tga file\n";
1923 if (exists $input{'data'}) {
1924 my $data = io_slurp($IO);
1926 $self->{ERRSTR}='Could not slurp from buffer';
1929 ${$input{data}} = $data;
1935 my ($class, $opts, @images) = @_;
1937 my $type = $opts->{type};
1939 if (!$type && $opts->{'file'}) {
1940 $type = $FORMATGUESS->($opts->{'file'});
1943 $class->_set_error('type parameter missing and not possible to guess from extension');
1946 # translate to ImgRaw
1948 for my $img (@images) {
1949 unless ($img->_valid_image("write_multi")) {
1950 $class->_set_error($img->errstr . " (image $index)");
1955 $class->_set_opts($opts, "i_", @images)
1957 my @work = map $_->{IMG}, @images;
1959 _writer_autoload($type);
1962 if ($writers{$type} && $writers{$type}{multiple}) {
1963 ($IO, $file) = $class->_get_writer_io($opts, $type)
1966 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1970 if (!$formats{$type}) {
1971 my $write_types = join ', ', sort Imager->write_types();
1972 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1976 ($IO, $file) = $class->_get_writer_io($opts, $type)
1979 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1983 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1988 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1994 if (exists $opts->{'data'}) {
1995 my $data = io_slurp($IO);
1997 Imager->_set_error('Could not slurp from buffer');
2000 ${$opts->{data}} = $data;
2005 # read multiple images from a file
2007 my ($class, %opts) = @_;
2009 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2012 my $type = $opts{'type'};
2014 $type = i_test_format_probe($IO, -1);
2017 if ($opts{file} && !$type) {
2019 $type = $FORMATGUESS->($opts{file});
2023 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2024 $opts{file} and $msg .= " or file name";
2025 Imager->_set_error($msg);
2029 _reader_autoload($type);
2031 if ($readers{$type} && $readers{$type}{multiple}) {
2032 return $readers{$type}{multiple}->($IO, %opts);
2035 unless ($formats{$type}) {
2036 my $read_types = join ', ', sort Imager->read_types();
2037 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2042 if ($type eq 'pnm') {
2043 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2046 my $img = Imager->new;
2047 if ($img->read(%opts, io => $IO, type => $type)) {
2050 Imager->_set_error($img->errstr);
2055 $ERRSTR = _error_as_msg();
2059 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2063 # Destroy an Imager object
2067 # delete $instances{$self};
2068 if (defined($self->{IMG})) {
2069 # the following is now handled by the XS DESTROY method for
2070 # Imager::ImgRaw object
2071 # Re-enabling this will break virtual images
2072 # tested for in t/t020masked.t
2073 # i_img_destroy($self->{IMG});
2074 undef($self->{IMG});
2076 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2080 # Perform an inplace filter of an image
2081 # that is the image will be overwritten with the data
2088 $self->_valid_image("filter")
2091 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2093 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2094 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2097 if ($filters{$input{'type'}}{names}) {
2098 my $names = $filters{$input{'type'}}{names};
2099 for my $name (keys %$names) {
2100 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2101 $input{$name} = $names->{$name}{$input{$name}};
2105 if (defined($filters{$input{'type'}}{defaults})) {
2106 %hsh=( image => $self->{IMG},
2108 %{$filters{$input{'type'}}{defaults}},
2111 %hsh=( image => $self->{IMG},
2116 my @cs=@{$filters{$input{'type'}}{callseq}};
2119 if (!defined($hsh{$_})) {
2120 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2125 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2126 &{$filters{$input{'type'}}{callsub}}(%hsh);
2129 chomp($self->{ERRSTR} = $@);
2135 $self->{DEBUG} && print "callseq is: @cs\n";
2136 $self->{DEBUG} && print "matching callseq is: @b\n";
2141 sub register_filter {
2143 my %hsh = ( defaults => {}, @_ );
2146 or die "register_filter() with no type\n";
2147 defined $hsh{callsub}
2148 or die "register_filter() with no callsub\n";
2149 defined $hsh{callseq}
2150 or die "register_filter() with no callseq\n";
2152 exists $filters{$hsh{type}}
2155 $filters{$hsh{type}} = \%hsh;
2160 sub scale_calculate {
2163 my %opts = ('type'=>'max', @_);
2165 # none of these should be references
2166 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2167 if (defined $opts{$name} && ref $opts{$name}) {
2168 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2173 my ($x_scale, $y_scale);
2174 my $width = $opts{width};
2175 my $height = $opts{height};
2177 defined $width or $width = $self->getwidth;
2178 defined $height or $height = $self->getheight;
2181 unless (defined $width && defined $height) {
2182 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2187 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2188 $x_scale = $opts{'xscalefactor'};
2189 $y_scale = $opts{'yscalefactor'};
2191 elsif ($opts{'xscalefactor'}) {
2192 $x_scale = $opts{'xscalefactor'};
2193 $y_scale = $opts{'scalefactor'} || $x_scale;
2195 elsif ($opts{'yscalefactor'}) {
2196 $y_scale = $opts{'yscalefactor'};
2197 $x_scale = $opts{'scalefactor'} || $y_scale;
2200 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2203 # work out the scaling
2204 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2205 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2206 $opts{ypixels} / $height );
2207 if ($opts{'type'} eq 'min') {
2208 $x_scale = $y_scale = _min($xpix,$ypix);
2210 elsif ($opts{'type'} eq 'max') {
2211 $x_scale = $y_scale = _max($xpix,$ypix);
2213 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2218 $self->_set_error('invalid value for type parameter');
2221 } elsif ($opts{xpixels}) {
2222 $x_scale = $y_scale = $opts{xpixels} / $width;
2224 elsif ($opts{ypixels}) {
2225 $x_scale = $y_scale = $opts{ypixels}/$height;
2227 elsif ($opts{constrain} && ref $opts{constrain}
2228 && $opts{constrain}->can('constrain')) {
2229 # we've been passed an Image::Math::Constrain object or something
2230 # that looks like one
2232 (undef, undef, $scalefactor)
2233 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2234 unless ($scalefactor) {
2235 $self->_set_error('constrain method failed on constrain parameter');
2238 $x_scale = $y_scale = $scalefactor;
2241 my $new_width = int($x_scale * $width + 0.5);
2242 $new_width > 0 or $new_width = 1;
2243 my $new_height = int($y_scale * $height + 0.5);
2244 $new_height > 0 or $new_height = 1;
2246 return ($x_scale, $y_scale, $new_width, $new_height);
2250 # Scale an image to requested size and return the scaled version
2254 my %opts = (qtype=>'normal' ,@_);
2255 my $img = Imager->new();
2256 my $tmp = Imager->new();
2258 unless (defined wantarray) {
2259 my @caller = caller;
2260 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2264 $self->_valid_image("scale")
2267 my ($x_scale, $y_scale, $new_width, $new_height) =
2268 $self->scale_calculate(%opts)
2271 if ($opts{qtype} eq 'normal') {
2272 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2273 if ( !defined($tmp->{IMG}) ) {
2274 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2277 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2278 if ( !defined($img->{IMG}) ) {
2279 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2285 elsif ($opts{'qtype'} eq 'preview') {
2286 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2287 if ( !defined($img->{IMG}) ) {
2288 $self->{ERRSTR}='unable to scale image';
2293 elsif ($opts{'qtype'} eq 'mixing') {
2294 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2295 unless ($img->{IMG}) {
2296 $self->_set_error(Imager->_error_as_msg);
2302 $self->_set_error('invalid value for qtype parameter');
2307 # Scales only along the X axis
2311 my %opts = ( scalefactor=>0.5, @_ );
2313 unless (defined wantarray) {
2314 my @caller = caller;
2315 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2319 $self->_valid_image("scaleX")
2322 my $img = Imager->new();
2324 my $scalefactor = $opts{scalefactor};
2326 if ($opts{pixels}) {
2327 $scalefactor = $opts{pixels} / $self->getwidth();
2330 unless ($self->{IMG}) {
2331 $self->{ERRSTR}='empty input image';
2335 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2337 if ( !defined($img->{IMG}) ) {
2338 $self->{ERRSTR} = 'unable to scale image';
2345 # Scales only along the Y axis
2349 my %opts = ( scalefactor => 0.5, @_ );
2351 unless (defined wantarray) {
2352 my @caller = caller;
2353 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2357 $self->_valid_image("scaleY")
2360 my $img = Imager->new();
2362 my $scalefactor = $opts{scalefactor};
2364 if ($opts{pixels}) {
2365 $scalefactor = $opts{pixels} / $self->getheight();
2368 unless ($self->{IMG}) {
2369 $self->{ERRSTR} = 'empty input image';
2372 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2374 if ( !defined($img->{IMG}) ) {
2375 $self->{ERRSTR} = 'unable to scale image';
2382 # Transform returns a spatial transformation of the input image
2383 # this moves pixels to a new location in the returned image.
2384 # NOTE - should make a utility function to check transforms for
2390 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2392 # print Dumper(\%opts);
2395 $self->_valid_image("transform")
2398 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2400 eval ("use Affix::Infix2Postfix;");
2403 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2406 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2407 {op=>'-',trans=>'Sub'},
2408 {op=>'*',trans=>'Mult'},
2409 {op=>'/',trans=>'Div'},
2410 {op=>'-','type'=>'unary',trans=>'u-'},
2412 {op=>'func','type'=>'unary'}],
2413 'grouping'=>[qw( \( \) )],
2414 'func'=>[qw( sin cos )],
2419 @xt=$I2P->translate($opts{'xexpr'});
2420 @yt=$I2P->translate($opts{'yexpr'});
2422 $numre=$I2P->{'numre'};
2425 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2426 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2427 @{$opts{'parm'}}=@pt;
2430 # print Dumper(\%opts);
2432 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2433 $self->{ERRSTR}='transform: no xopcodes given.';
2437 @op=@{$opts{'xopcodes'}};
2439 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2440 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2443 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2449 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2450 $self->{ERRSTR}='transform: no yopcodes given.';
2454 @op=@{$opts{'yopcodes'}};
2456 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2457 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2460 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2465 if ( !exists $opts{'parm'}) {
2466 $self->{ERRSTR}='transform: no parameter arg given.';
2470 # print Dumper(\@ropx);
2471 # print Dumper(\@ropy);
2472 # print Dumper(\@ropy);
2474 my $img = Imager->new();
2475 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2476 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2482 my ($opts, @imgs) = @_;
2484 require "Imager/Expr.pm";
2486 $opts->{variables} = [ qw(x y) ];
2487 my ($width, $height) = @{$opts}{qw(width height)};
2490 for my $img (@imgs) {
2491 unless ($img->_valid_image("transform2")) {
2492 Imager->_set_error($img->errstr . " (input image $index)");
2498 $width ||= $imgs[0]->getwidth();
2499 $height ||= $imgs[0]->getheight();
2501 for my $img (@imgs) {
2502 $opts->{constants}{"w$img_num"} = $img->getwidth();
2503 $opts->{constants}{"h$img_num"} = $img->getheight();
2504 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2505 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2510 $opts->{constants}{w} = $width;
2511 $opts->{constants}{cx} = $width/2;
2514 $Imager::ERRSTR = "No width supplied";
2518 $opts->{constants}{h} = $height;
2519 $opts->{constants}{cy} = $height/2;
2522 $Imager::ERRSTR = "No height supplied";
2525 my $code = Imager::Expr->new($opts);
2527 $Imager::ERRSTR = Imager::Expr::error();
2530 my $channels = $opts->{channels} || 3;
2531 unless ($channels >= 1 && $channels <= 4) {
2532 return Imager->_set_error("channels must be an integer between 1 and 4");
2535 my $img = Imager->new();
2536 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2537 $channels, $code->code(),
2538 $code->nregs(), $code->cregs(),
2539 [ map { $_->{IMG} } @imgs ]);
2540 if (!defined $img->{IMG}) {
2541 $Imager::ERRSTR = Imager->_error_as_msg();
2552 $self->_valid_image("rubthrough")
2555 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2556 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2560 %opts = (src_minx => 0,
2562 src_maxx => $opts{src}->getwidth(),
2563 src_maxy => $opts{src}->getheight(),
2567 defined $tx or $tx = $opts{left};
2568 defined $tx or $tx = 0;
2571 defined $ty or $ty = $opts{top};
2572 defined $ty or $ty = 0;
2574 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2575 $opts{src_minx}, $opts{src_miny},
2576 $opts{src_maxx}, $opts{src_maxy})) {
2577 $self->_set_error($self->_error_as_msg());
2594 $self->_valid_image("compose")
2597 unless ($opts{src}) {
2598 $self->_set_error("compose: src parameter missing");
2602 unless ($opts{src}->_valid_image("compose")) {
2603 $self->_set_error($opts{src}->errstr . " (for src)");
2606 my $src = $opts{src};
2608 my $left = $opts{left};
2609 defined $left or $left = $opts{tx};
2610 defined $left or $left = 0;
2612 my $top = $opts{top};
2613 defined $top or $top = $opts{ty};
2614 defined $top or $top = 0;
2616 my $src_left = $opts{src_left};
2617 defined $src_left or $src_left = $opts{src_minx};
2618 defined $src_left or $src_left = 0;
2620 my $src_top = $opts{src_top};
2621 defined $src_top or $src_top = $opts{src_miny};
2622 defined $src_top or $src_top = 0;
2624 my $width = $opts{width};
2625 if (!defined $width && defined $opts{src_maxx}) {
2626 $width = $opts{src_maxx} - $src_left;
2628 defined $width or $width = $src->getwidth() - $src_left;
2630 my $height = $opts{height};
2631 if (!defined $height && defined $opts{src_maxy}) {
2632 $height = $opts{src_maxy} - $src_top;
2634 defined $height or $height = $src->getheight() - $src_top;
2636 my $combine = $self->_combine($opts{combine}, 'normal');
2639 unless ($opts{mask}->_valid_image("compose")) {
2640 $self->_set_error($opts{mask}->errstr . " (for mask)");
2644 my $mask_left = $opts{mask_left};
2645 defined $mask_left or $mask_left = $opts{mask_minx};
2646 defined $mask_left or $mask_left = 0;
2648 my $mask_top = $opts{mask_top};
2649 defined $mask_top or $mask_top = $opts{mask_miny};
2650 defined $mask_top or $mask_top = 0;
2652 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2653 $left, $top, $src_left, $src_top,
2654 $mask_left, $mask_top, $width, $height,
2655 $combine, $opts{opacity})) {
2656 $self->_set_error(Imager->_error_as_msg);
2661 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2662 $width, $height, $combine, $opts{opacity})) {
2663 $self->_set_error(Imager->_error_as_msg);
2675 $self->_valid_image("flip")
2678 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2680 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2681 $dir = $xlate{$opts{'dir'}};
2682 return $self if i_flipxy($self->{IMG}, $dir);
2690 unless (defined wantarray) {
2691 my @caller = caller;
2692 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2696 $self->_valid_image("rotate")
2699 if (defined $opts{right}) {
2700 my $degrees = $opts{right};
2702 $degrees += 360 * int(((-$degrees)+360)/360);
2704 $degrees = $degrees % 360;
2705 if ($degrees == 0) {
2706 return $self->copy();
2708 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2709 my $result = Imager->new();
2710 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2714 $self->{ERRSTR} = $self->_error_as_msg();
2719 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2723 elsif (defined $opts{radians} || defined $opts{degrees}) {
2724 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2726 my $back = $opts{back};
2727 my $result = Imager->new;
2729 $back = _color($back);
2731 $self->_set_error(Imager->errstr);
2735 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2738 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2740 if ($result->{IMG}) {
2744 $self->{ERRSTR} = $self->_error_as_msg();
2749 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2754 sub matrix_transform {
2758 $self->_valid_image("matrix_transform")
2761 unless (defined wantarray) {
2762 my @caller = caller;
2763 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2767 if ($opts{matrix}) {
2768 my $xsize = $opts{xsize} || $self->getwidth;
2769 my $ysize = $opts{ysize} || $self->getheight;
2771 my $result = Imager->new;
2773 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2774 $opts{matrix}, $opts{back})
2778 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2786 $self->{ERRSTR} = "matrix parameter required";
2792 *yatf = \&matrix_transform;
2794 # These two are supported for legacy code only
2797 return Imager::Color->new(@_);
2801 return Imager::Color::set(@_);
2804 # Draws a box between the specified corner points.
2807 my $raw = $self->{IMG};
2809 $self->_valid_image("box")
2814 my ($xmin, $ymin, $xmax, $ymax);
2815 if (exists $opts{'box'}) {
2816 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2817 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2818 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2819 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2822 defined($xmin = $opts{xmin}) or $xmin = 0;
2823 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2824 defined($ymin = $opts{ymin}) or $ymin = 0;
2825 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2828 if ($opts{filled}) {
2829 my $color = $opts{'color'};
2831 if (defined $color) {
2832 unless (_is_color_object($color)) {
2833 $color = _color($color);
2835 $self->{ERRSTR} = $Imager::ERRSTR;
2841 $color = i_color_new(255,255,255,255);
2844 if ($color->isa("Imager::Color")) {
2845 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2848 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2851 elsif ($opts{fill}) {
2852 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2853 # assume it's a hash ref
2854 require 'Imager/Fill.pm';
2855 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2856 $self->{ERRSTR} = $Imager::ERRSTR;
2860 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2863 my $color = $opts{'color'};
2864 if (defined $color) {
2865 unless (_is_color_object($color)) {
2866 $color = _color($color);
2868 $self->{ERRSTR} = $Imager::ERRSTR;
2874 $color = i_color_new(255, 255, 255, 255);
2877 $self->{ERRSTR} = $Imager::ERRSTR;
2880 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2889 $self->_valid_image("arc")
2892 my $dflcl= [ 255, 255, 255, 255];
2897 'r'=>_min($self->getwidth(),$self->getheight())/3,
2898 'x'=>$self->getwidth()/2,
2899 'y'=>$self->getheight()/2,
2906 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2907 # assume it's a hash ref
2908 require 'Imager/Fill.pm';
2909 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2910 $self->{ERRSTR} = $Imager::ERRSTR;
2914 if ($opts{d1} == 0 && $opts{d2} == 361) {
2915 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2919 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2920 $opts{'d2'}, $opts{fill}{fill});
2923 elsif ($opts{filled}) {
2924 my $color = _color($opts{'color'});
2926 $self->{ERRSTR} = $Imager::ERRSTR;
2929 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2930 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2934 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2935 $opts{'d1'}, $opts{'d2'}, $color);
2939 my $color = _color($opts{'color'});
2940 if ($opts{d2} - $opts{d1} >= 360) {
2941 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2944 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2950 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2951 # assume it's a hash ref
2952 require 'Imager/Fill.pm';
2953 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2954 $self->{ERRSTR} = $Imager::ERRSTR;
2958 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2959 $opts{'d2'}, $opts{fill}{fill});
2962 my $color = _color($opts{'color'});
2964 $self->{ERRSTR} = $Imager::ERRSTR;
2967 if ($opts{filled}) {
2968 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2969 $opts{'d1'}, $opts{'d2'}, $color);
2972 if ($opts{d1} == 0 && $opts{d2} == 361) {
2973 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2976 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2982 $self->_set_error($self->_error_as_msg);
2989 # Draws a line from one point to the other
2990 # the endpoint is set if the endp parameter is set which it is by default.
2991 # to turn of the endpoint being set use endp=>0 when calling line.
2995 my $dflcl=i_color_new(0,0,0,0);
2996 my %opts=(color=>$dflcl,
3000 $self->_valid_image("line")
3003 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
3004 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
3006 my $color = _color($opts{'color'});
3008 $self->{ERRSTR} = $Imager::ERRSTR;
3012 $opts{antialias} = $opts{aa} if defined $opts{aa};
3013 if ($opts{antialias}) {
3014 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3015 $color, $opts{endp});
3017 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3018 $color, $opts{endp});
3023 # Draws a line between an ordered set of points - It more or less just transforms this
3024 # into a list of lines.
3028 my ($pt,$ls,@points);
3029 my $dflcl=i_color_new(0,0,0,0);
3030 my %opts=(color=>$dflcl,@_);
3032 $self->_valid_image("polyline")
3035 if (exists($opts{points})) { @points=@{$opts{points}}; }
3036 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3037 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3040 # print Dumper(\@points);
3042 my $color = _color($opts{'color'});
3044 $self->{ERRSTR} = $Imager::ERRSTR;
3047 $opts{antialias} = $opts{aa} if defined $opts{aa};
3048 if ($opts{antialias}) {
3051 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3058 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3068 my ($pt,$ls,@points);
3069 my $dflcl = i_color_new(0,0,0,0);
3070 my %opts = (color=>$dflcl, @_);
3072 $self->_valid_image("polygon")
3075 if (exists($opts{points})) {
3076 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3077 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3080 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3081 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3084 my $mode = _first($opts{mode}, 0);
3086 if ($opts{'fill'}) {
3087 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3088 # assume it's a hash ref
3089 require 'Imager/Fill.pm';
3090 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3091 $self->{ERRSTR} = $Imager::ERRSTR;
3095 i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3096 $mode, $opts{'fill'}{'fill'});
3099 my $color = _color($opts{'color'});
3101 $self->{ERRSTR} = $Imager::ERRSTR;
3104 i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color);
3111 my ($self, %opts) = @_;
3113 $self->_valid_image("polypolygon")
3116 my $points = $opts{points};
3118 or return $self->_set_error("polypolygon: missing required points");
3120 my $mode = _first($opts{mode}, "evenodd");
3122 if ($opts{filled}) {
3123 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3124 or return $self->_set_error($Imager::ERRSTR);
3126 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3127 or return $self->_set_error($self->_error_as_msg);
3129 elsif ($opts{fill}) {
3130 my $fill = $opts{fill};
3131 $self->_valid_fill($fill, "polypolygon")
3134 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3135 or return $self->_set_error($self->_error_as_msg);
3138 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3139 or return $self->_set_error($Imager::ERRSTR);
3141 my $rimg = $self->{IMG};
3143 if (_first($opts{aa}, 1)) {
3144 for my $poly (@$points) {
3145 my $xp = $poly->[0];
3146 my $yp = $poly->[1];
3147 for my $i (0 .. $#$xp - 1) {
3148 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3151 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3156 for my $poly (@$points) {
3157 my $xp = $poly->[0];
3158 my $yp = $poly->[1];
3159 for my $i (0 .. $#$xp - 1) {
3160 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3163 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3172 # this the multipoint bezier curve
3173 # this is here more for testing that actual usage since
3174 # this is not a good algorithm. Usually the curve would be
3175 # broken into smaller segments and each done individually.
3179 my ($pt,$ls,@points);
3180 my $dflcl=i_color_new(0,0,0,0);
3181 my %opts=(color=>$dflcl,@_);
3183 $self->_valid_image("polybezier")
3186 if (exists $opts{points}) {
3187 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3188 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3191 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3192 $self->{ERRSTR}='Missing or invalid points.';
3196 my $color = _color($opts{'color'});
3198 $self->{ERRSTR} = $Imager::ERRSTR;
3201 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3207 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3210 $self->_valid_image("flood_fill")
3213 unless (exists $opts{'x'} && exists $opts{'y'}) {
3214 $self->{ERRSTR} = "missing seed x and y parameters";
3218 if ($opts{border}) {
3219 my $border = _color($opts{border});
3221 $self->_set_error($Imager::ERRSTR);
3225 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3226 # assume it's a hash ref
3227 require Imager::Fill;
3228 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3229 $self->{ERRSTR} = $Imager::ERRSTR;
3233 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3234 $opts{fill}{fill}, $border);
3237 my $color = _color($opts{'color'});
3239 $self->{ERRSTR} = $Imager::ERRSTR;
3242 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3249 $self->{ERRSTR} = $self->_error_as_msg();
3255 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3256 # assume it's a hash ref
3257 require 'Imager/Fill.pm';
3258 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3259 $self->{ERRSTR} = $Imager::ERRSTR;
3263 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3266 my $color = _color($opts{'color'});
3268 $self->{ERRSTR} = $Imager::ERRSTR;
3271 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3277 $self->{ERRSTR} = $self->_error_as_msg();
3284 my ($self, %opts) = @_;
3286 $self->_valid_image("setpixel")
3289 my $color = $opts{color};
3290 unless (defined $color) {
3291 $color = $self->{fg};
3292 defined $color or $color = NC(255, 255, 255);
3295 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3296 unless ($color = _color($color, 'setpixel')) {
3297 $self->_set_error("setpixel: " . Imager->errstr);
3302 unless (exists $opts{'x'} && exists $opts{'y'}) {
3303 $self->_set_error('setpixel: missing x or y parameter');
3309 if (ref $x || ref $y) {
3310 $x = ref $x ? $x : [ $x ];
3311 $y = ref $y ? $y : [ $y ];
3313 $self->_set_error("setpixel: x is a reference to an empty array");
3317 $self->_set_error("setpixel: y is a reference to an empty array");
3321 # make both the same length, replicating the last element
3323 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3326 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3330 if ($color->isa('Imager::Color')) {
3331 for my $i (0..$#$x) {
3332 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3337 for my $i (0..$#$x) {
3338 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3346 if ($color->isa('Imager::Color')) {
3347 i_ppix($self->{IMG}, $x, $y, $color)
3348 and return "0 but true";
3351 i_ppixf($self->{IMG}, $x, $y, $color)
3352 and return "0 but true";
3362 my %opts = ( "type"=>'8bit', @_);
3364 $self->_valid_image("getpixel")
3367 unless (exists $opts{'x'} && exists $opts{'y'}) {
3368 $self->_set_error('getpixel: missing x or y parameter');
3374 my $type = $opts{'type'};
3375 if (ref $x || ref $y) {
3376 $x = ref $x ? $x : [ $x ];
3377 $y = ref $y ? $y : [ $y ];
3379 $self->_set_error("getpixel: x is a reference to an empty array");
3383 $self->_set_error("getpixel: y is a reference to an empty array");
3387 # make both the same length, replicating the last element
3389 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3392 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3396 if ($type eq '8bit') {
3397 for my $i (0..$#$x) {
3398 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3401 elsif ($type eq 'float' || $type eq 'double') {
3402 for my $i (0..$#$x) {
3403 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3407 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3410 return wantarray ? @result : \@result;
3413 if ($type eq '8bit') {
3414 return i_get_pixel($self->{IMG}, $x, $y);
3416 elsif ($type eq 'float' || $type eq 'double') {
3417 return i_gpixf($self->{IMG}, $x, $y);
3420 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3428 my %opts = ( type => '8bit', x=>0, @_);
3430 $self->_valid_image("getscanline")
3433 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3435 unless (defined $opts{'y'}) {
3436 $self->_set_error("missing y parameter");
3440 if ($opts{type} eq '8bit') {
3441 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3444 elsif ($opts{type} eq 'float') {
3445 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3448 elsif ($opts{type} eq 'index') {
3449 unless (i_img_type($self->{IMG})) {
3450 $self->_set_error("type => index only valid on paletted images");
3453 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3457 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3464 my %opts = ( x=>0, @_);
3466 $self->_valid_image("setscanline")
3469 unless (defined $opts{'y'}) {
3470 $self->_set_error("missing y parameter");
3475 if (ref $opts{pixels} && @{$opts{pixels}}) {
3476 # try to guess the type
3477 if ($opts{pixels}[0]->isa('Imager::Color')) {
3478 $opts{type} = '8bit';
3480 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3481 $opts{type} = 'float';
3484 $self->_set_error("missing type parameter and could not guess from pixels");
3490 $opts{type} = '8bit';
3494 if ($opts{type} eq '8bit') {
3495 if (ref $opts{pixels}) {
3496 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3499 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3502 elsif ($opts{type} eq 'float') {
3503 if (ref $opts{pixels}) {
3504 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3507 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3510 elsif ($opts{type} eq 'index') {
3511 if (ref $opts{pixels}) {
3512 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3515 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3519 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3526 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3528 $self->_valid_image("getsamples")
3531 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3533 unless (defined $opts{'y'}) {
3534 $self->_set_error("missing y parameter");
3538 if ($opts{target}) {
3539 my $target = $opts{target};
3540 my $offset = $opts{offset};
3541 if ($opts{type} eq '8bit') {
3542 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3543 $opts{y}, $opts{channels})
3545 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3546 return scalar(@samples);
3548 elsif ($opts{type} eq 'float') {
3549 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3550 $opts{y}, $opts{channels});
3551 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3552 return scalar(@samples);
3554 elsif ($opts{type} =~ /^(\d+)bit$/) {
3558 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3559 $opts{y}, $bits, $target,
3560 $offset, $opts{channels});
3561 unless (defined $count) {
3562 $self->_set_error(Imager->_error_as_msg);
3569 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3574 if ($opts{type} eq '8bit') {
3575 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3576 $opts{y}, $opts{channels});
3578 elsif ($opts{type} eq 'float') {
3579 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3580 $opts{y}, $opts{channels});
3582 elsif ($opts{type} =~ /^(\d+)bit$/) {
3586 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3587 $opts{y}, $bits, \@data, 0, $opts{channels})
3592 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3601 $self->_valid_image("setsamples")
3604 my %opts = ( x => 0, offset => 0 );
3606 # avoid duplicating the data parameter, it may be a large scalar
3608 while ($i < @_ -1) {
3609 if ($_[$i] eq 'data') {
3613 $opts{$_[$i]} = $_[$i+1];
3619 unless(defined $data_index) {
3620 $self->_set_error('setsamples: data parameter missing');
3623 unless (defined $_[$data_index]) {
3624 $self->_set_error('setsamples: data parameter not defined');
3628 my $type = $opts{type};
3629 defined $type or $type = '8bit';
3631 my $width = defined $opts{width} ? $opts{width}
3632 : $self->getwidth() - $opts{x};
3635 if ($type eq '8bit') {
3636 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3637 $_[$data_index], $opts{offset}, $width);
3639 elsif ($type eq 'float') {
3640 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3641 $_[$data_index], $opts{offset}, $width);
3643 elsif ($type =~ /^([0-9]+)bit$/) {
3646 unless (ref $_[$data_index]) {
3647 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3651 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3652 $opts{channels}, $_[$data_index], $opts{offset},
3656 $self->_set_error('setsamples: type parameter invalid');
3660 unless (defined $count) {
3661 $self->_set_error(Imager->_error_as_msg);
3668 # make an identity matrix of the given size
3672 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3673 for my $c (0 .. ($size-1)) {
3674 $matrix->[$c][$c] = 1;
3679 # general function to convert an image
3681 my ($self, %opts) = @_;
3684 $self->_valid_image("convert")
3687 unless (defined wantarray) {
3688 my @caller = caller;
3689 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3693 # the user can either specify a matrix or preset
3694 # the matrix overrides the preset
3695 if (!exists($opts{matrix})) {
3696 unless (exists($opts{preset})) {
3697 $self->{ERRSTR} = "convert() needs a matrix or preset";
3701 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3702 # convert to greyscale, keeping the alpha channel if any
3703 if ($self->getchannels == 3) {
3704 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3706 elsif ($self->getchannels == 4) {
3707 # preserve the alpha channel
3708 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3713 $matrix = _identity($self->getchannels);
3716 elsif ($opts{preset} eq 'noalpha') {
3717 # strip the alpha channel
3718 if ($self->getchannels == 2 or $self->getchannels == 4) {
3719 $matrix = _identity($self->getchannels);
3720 pop(@$matrix); # lose the alpha entry
3723 $matrix = _identity($self->getchannels);
3726 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3728 $matrix = [ [ 1 ] ];
3730 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3731 $matrix = [ [ 0, 1 ] ];
3733 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3734 $matrix = [ [ 0, 0, 1 ] ];
3736 elsif ($opts{preset} eq 'alpha') {
3737 if ($self->getchannels == 2 or $self->getchannels == 4) {
3738 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3741 # the alpha is just 1 <shrug>
3742 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3745 elsif ($opts{preset} eq 'rgb') {
3746 if ($self->getchannels == 1) {
3747 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3749 elsif ($self->getchannels == 2) {
3750 # preserve the alpha channel
3751 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3754 $matrix = _identity($self->getchannels);
3757 elsif ($opts{preset} eq 'addalpha') {
3758 if ($self->getchannels == 1) {
3759 $matrix = _identity(2);
3761 elsif ($self->getchannels == 3) {
3762 $matrix = _identity(4);
3765 $matrix = _identity($self->getchannels);
3769 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3775 $matrix = $opts{matrix};
3778 my $new = Imager->new;
3779 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3780 unless ($new->{IMG}) {
3781 # most likely a bad matrix
3782 i_push_error(0, "convert");
3783 $self->{ERRSTR} = _error_as_msg();
3789 # combine channels from multiple input images, a class method
3791 my ($class, %opts) = @_;
3793 my $src = delete $opts{src};
3795 $class->_set_error("src parameter missing");
3800 for my $img (@$src) {
3801 unless (eval { $img->isa("Imager") }) {
3802 $class->_set_error("src must contain image objects");
3805 unless ($img->_valid_image("combine")) {
3806 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3809 push @imgs, $img->{IMG};
3812 if (my $channels = delete $opts{channels}) {
3813 $result = i_combine(\@imgs, $channels);
3816 $result = i_combine(\@imgs);
3819 $class->_set_error($class->_error_as_msg);
3823 my $img = $class->new;
3824 $img->{IMG} = $result;
3830 # general function to map an image through lookup tables
3833 my ($self, %opts) = @_;
3834 my @chlist = qw( red green blue alpha );
3836 $self->_valid_image("map")
3839 if (!exists($opts{'maps'})) {
3840 # make maps from channel maps
3842 for $chnum (0..$#chlist) {
3843 if (exists $opts{$chlist[$chnum]}) {
3844 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3845 } elsif (exists $opts{'all'}) {
3846 $opts{'maps'}[$chnum] = $opts{'all'};
3850 if ($opts{'maps'} and $self->{IMG}) {
3851 i_map($self->{IMG}, $opts{'maps'} );
3857 my ($self, %opts) = @_;
3859 $self->_valid_image("difference")
3862 defined $opts{mindist} or $opts{mindist} = 0;
3864 defined $opts{other}
3865 or return $self->_set_error("No 'other' parameter supplied");
3866 unless ($opts{other}->_valid_image("difference")) {
3867 $self->_set_error($opts{other}->errstr . " (other image)");
3871 my $result = Imager->new;
3872 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3874 or return $self->_set_error($self->_error_as_msg());
3879 # destructive border - image is shrunk by one pixel all around
3882 my ($self,%opts)=@_;
3883 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3884 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3888 # Get the width of an image
3893 $self->_valid_image("getwidth")
3896 return i_img_get_width($self->{IMG});
3899 # Get the height of an image
3904 $self->_valid_image("getheight")
3907 return i_img_get_height($self->{IMG});
3910 # Get number of channels in an image
3915 $self->_valid_image("getchannels")
3918 return i_img_getchannels($self->{IMG});
3921 my @model_names = qw(unknown gray graya rgb rgba);
3924 my ($self, %opts) = @_;
3926 $self->_valid_image("colormodel")
3929 my $model = i_img_color_model($self->{IMG});
3931 return $opts{numeric} ? $model : $model_names[$model];
3937 $self->_valid_image("colorchannels")
3940 return i_img_color_channels($self->{IMG});
3946 $self->_valid_image("alphachannel")
3949 return scalar(i_img_alpha_channel($self->{IMG}));
3957 $self->_valid_image("getmask")
3960 return i_img_getmask($self->{IMG});
3969 $self->_valid_image("setmask")
3972 unless (defined $opts{mask}) {
3973 $self->_set_error("mask parameter required");
3977 i_img_setmask( $self->{IMG} , $opts{mask} );
3982 # Get number of colors in an image
3986 my %opts=('maxcolors'=>2**30,@_);
3988 $self->_valid_image("getcolorcount")
3991 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3992 return ($rc==-1? undef : $rc);
3995 # Returns a reference to a hash. The keys are colour named (packed) and the
3996 # values are the number of pixels in this colour.
3997 sub getcolorusagehash {
4000 $self->_valid_image("getcolorusagehash")
4003 my %opts = ( maxcolors => 2**30, @_ );
4004 my $max_colors = $opts{maxcolors};
4005 unless (defined $max_colors && $max_colors > 0) {
4006 $self->_set_error('maxcolors must be a positive integer');
4010 my $channels= $self->getchannels;
4011 # We don't want to look at the alpha channel, because some gifs using it
4012 # doesn't define it for every colour (but only for some)
4013 $channels -= 1 if $channels == 2 or $channels == 4;
4015 my $height = $self->getheight;
4016 for my $y (0 .. $height - 1) {
4017 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4018 while (length $colors) {
4019 $color_use{ substr($colors, 0, $channels, '') }++;
4021 keys %color_use > $max_colors
4027 # This will return a ordered array of the colour usage. Kind of the sorted
4028 # version of the values of the hash returned by getcolorusagehash.
4029 # You might want to add safety checks and change the names, etc...
4033 $self->_valid_image("getcolorusage")
4036 my %opts = ( maxcolors => 2**30, @_ );
4037 my $max_colors = $opts{maxcolors};
4038 unless (defined $max_colors && $max_colors > 0) {
4039 $self->_set_error('maxcolors must be a positive integer');
4043 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4046 # draw string to an image
4051 $self->_valid_image("string")
4054 my %input=('x'=>0, 'y'=>0, @_);
4055 defined($input{string}) or $input{string} = $input{text};
4057 unless(defined $input{string}) {
4058 $self->{ERRSTR}="missing required parameter 'string'";
4062 unless($input{font}) {
4063 $self->{ERRSTR}="missing required parameter 'font'";
4067 unless ($input{font}->draw(image=>$self, %input)) {
4079 $self->_valid_image("align_string")
4088 my %input=('x'=>0, 'y'=>0, @_);
4089 defined $input{string}
4090 or $input{string} = $input{text};
4092 unless(exists $input{string}) {
4093 $self->_set_error("missing required parameter 'string'");
4097 unless($input{font}) {
4098 $self->_set_error("missing required parameter 'font'");
4103 unless (@result = $input{font}->align(image=>$img, %input)) {
4107 return wantarray ? @result : $result[0];
4110 my @file_limit_names = qw/width height bytes/;
4112 sub set_file_limits {
4119 @values{@file_limit_names} = (0) x @file_limit_names;
4122 @values{@file_limit_names} = i_get_image_file_limits();
4125 for my $key (keys %values) {
4126 defined $opts{$key} and $values{$key} = $opts{$key};
4129 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4132 sub get_file_limits {
4133 i_get_image_file_limits();
4136 my @check_args = qw(width height channels sample_size);
4138 sub check_file_limits {
4148 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4149 $opts{sample_size} = length(pack("d", 0));
4152 for my $name (@check_args) {
4153 unless (defined $opts{$name}) {
4154 $class->_set_error("check_file_limits: $name must be defined");
4157 unless ($opts{$name} == int($opts{$name})) {
4158 $class->_set_error("check_file_limits: $name must be a positive integer");
4163 my $result = i_int_check_image_file_limits(@opts{@check_args});
4165 $class->_set_error($class->_error_as_msg());
4171 # Shortcuts that can be exported
4173 sub newcolor { Imager::Color->new(@_); }
4174 sub newfont { Imager::Font->new(@_); }
4176 require Imager::Color::Float;
4177 return Imager::Color::Float->new(@_);
4180 *NC=*newcolour=*newcolor;
4187 #### Utility routines
4190 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4194 my ($self, $msg) = @_;
4197 $self->{ERRSTR} = $msg;
4205 # Default guess for the type of an image from extension
4207 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4211 ( map { $_ => $_ } @simple_types ),
4217 pnm => "pnm", # technically wrong, but historically it works in Imager
4230 sub def_guess_type {
4233 my ($ext) = $name =~ /\.([^.]+)$/
4236 my $type = $ext_types{$ext}
4243 return @combine_types;
4246 # get the minimum of a list
4250 for(@_) { if ($_<$mx) { $mx=$_; }}
4254 # get the maximum of a list
4258 for(@_) { if ($_>$mx) { $mx=$_; }}
4262 # string stuff for iptc headers
4266 $str = substr($str,3);
4267 $str =~ s/[\n\r]//g;
4274 # A little hack to parse iptc headers.
4279 my($caption,$photogr,$headln,$credit);
4281 my $str=$self->{IPTCRAW};
4286 @ar=split(/8BIM/,$str);
4291 @sar=split(/\034\002/);
4292 foreach $item (@sar) {
4293 if ($item =~ m/^x/) {
4294 $caption = _clean($item);
4297 if ($item =~ m/^P/) {
4298 $photogr = _clean($item);
4301 if ($item =~ m/^i/) {
4302 $headln = _clean($item);
4305 if ($item =~ m/^n/) {
4306 $credit = _clean($item);
4312 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4316 # Inline added a new argument at the beginning
4320 or die "Only C language supported";
4322 require Imager::ExtUtils;
4323 return Imager::ExtUtils->inline_config;
4326 # threads shouldn't try to close raw Imager objects
4327 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4330 # this serves two purposes:
4331 # - a class method to load the file support modules included with Imager
4332 # (or were included, once the library dependent modules are split out)
4333 # - something for Module::ScanDeps to analyze
4334 # https://rt.cpan.org/Ticket/Display.html?id=6566
4336 eval { require Imager::File::GIF };
4337 eval { require Imager::File::JPEG };
4338 eval { require Imager::File::PNG };
4339 eval { require Imager::File::SGI };
4340 eval { require Imager::File::TIFF };
4341 eval { require Imager::File::ICO };
4342 eval { require Imager::Font::W32 };
4343 eval { require Imager::Font::FT2 };
4344 eval { require Imager::Font::T1 };
4351 my ($class, $fh) = @_;
4354 return $class->new_cb
4359 return print $fh $_[0];
4363 my $count = CORE::read $fh, $tmp, $_[1];
4371 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4372 unless (CORE::seek $fh, $_[0], $_[1]) {
4383 return $class->_new_perlio($fh);
4387 # backward compatibility for %formats
4388 package Imager::FORMATS;
4390 use constant IX_FORMATS => 0;
4391 use constant IX_LIST => 1;
4392 use constant IX_INDEX => 2;
4393 use constant IX_CLASSES => 3;
4396 my ($class, $formats, $classes) = @_;
4398 return bless [ $formats, [ ], 0, $classes ], $class;
4402 my ($self, $key) = @_;
4404 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4407 my $loaded = Imager::_load_file($file, \$error);
4412 if ($error =~ /^Can't locate /) {
4413 $error = "Can't locate $file";
4415 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4418 $self->[IX_FORMATS]{$key} = $value;
4424 my ($self, $key) = @_;
4426 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4428 $self->[IX_CLASSES]{$key} or return undef;
4430 return $self->_check($key);
4434 die "%Imager::formats is not user monifiable";
4438 die "%Imager::formats is not user monifiable";
4442 die "%Imager::formats is not user monifiable";
4446 my ($self, $key) = @_;
4448 if (exists $self->[IX_FORMATS]{$key}) {
4449 my $value = $self->[IX_FORMATS]{$key}
4454 $self->_check($key) or return 1==0;
4462 unless (@{$self->[IX_LIST]}) {
4464 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4465 keys %{$self->[IX_FORMATS]};
4467 for my $key (keys %{$self->[IX_CLASSES]}) {
4468 $self->[IX_FORMATS]{$key} and next;
4470 and push @{$self->[IX_LIST]}, $key;
4474 @{$self->[IX_LIST]} or return;
4475 $self->[IX_INDEX] = 1;
4476 return $self->[IX_LIST][0];
4482 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4485 return $self->[IX_LIST][$self->[IX_INDEX]++];
4491 return scalar @{$self->[IX_LIST]};
4496 # Below is the stub of documentation for your module. You better edit it!
4500 Imager - Perl extension for Generating 24 bit Images
4510 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4515 # see Imager::Files for information on the read() method
4516 my $img = Imager->new(file=>$file)
4517 or die Imager->errstr();
4519 $file =~ s/\.[^.]*$//;
4521 # Create smaller version
4522 # documented in Imager::Transformations
4523 my $thumb = $img->scale(scalefactor=>.3);
4525 # Autostretch individual channels
4526 $thumb->filter(type=>'autolevels');
4528 # try to save in one of these formats
4531 for $format ( qw( png gif jpeg tiff ppm ) ) {
4532 # Check if given format is supported
4533 if ($Imager::formats{$format}) {
4534 $file.="_low.$format";
4535 print "Storing image as: $file\n";
4536 # documented in Imager::Files
4537 $thumb->write(file=>$file) or
4545 Imager is a module for creating and altering images. It can read and
4546 write various image formats, draw primitive shapes like lines,and
4547 polygons, blend multiple images together in various ways, scale, crop,
4548 render text and more.
4550 =head2 Overview of documentation
4556 Imager - This document - Synopsis, Example, Table of Contents and
4561 L<Imager::Install> - installation notes for Imager.
4565 L<Imager::Tutorial> - a brief introduction to Imager.
4569 L<Imager::Cookbook> - how to do various things with Imager.
4573 L<Imager::ImageTypes> - Basics of constructing image objects with
4574 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4575 8/16/double bits/channel, color maps, channel masks, image tags, color
4576 quantization. Also discusses basic image information methods.
4580 L<Imager::Files> - IO interaction, reading/writing images, format
4585 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4590 L<Imager::Color> - Color specification.
4594 L<Imager::Fill> - Fill pattern specification.
4598 L<Imager::Font> - General font rendering, bounding boxes and font
4603 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4604 blending, pasting, convert and map.
4608 L<Imager::Engines> - Programmable transformations through
4609 C<transform()>, C<transform2()> and C<matrix_transform()>.
4613 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4618 L<Imager::Expr> - Expressions for evaluation engine used by
4623 L<Imager::Matrix2d> - Helper class for affine transformations.
4627 L<Imager::Fountain> - Helper for making gradient profiles.
4631 L<Imager::IO> - Imager I/O abstraction.
4635 L<Imager::API> - using Imager's C API
4639 L<Imager::APIRef> - API function reference
4643 L<Imager::Inline> - using Imager's C API from Inline::C
4647 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4651 L<Imager::Security> - brief security notes.
4655 L<Imager::Threads> - brief information on working with threads.
4659 =head2 Basic Overview
4661 An Image object is created with C<$img = Imager-E<gt>new()>.
4664 $img=Imager->new(); # create empty image
4665 $img->read(file=>'lena.png',type=>'png') or # read image from file
4666 die $img->errstr(); # give an explanation
4667 # if something failed
4669 or if you want to create an empty image:
4671 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4673 This example creates a completely black image of width 400 and height
4676 =head1 ERROR HANDLING
4678 In general a method will return false when it fails, if it does use
4679 the C<errstr()> method to find out why:
4685 Returns the last error message in that context.
4687 If the last error you received was from calling an object method, such
4688 as read, call errstr() as an object method to find out why:
4690 my $image = Imager->new;
4691 $image->read(file => 'somefile.gif')
4692 or die $image->errstr;
4694 If it was a class method then call errstr() as a class method:
4696 my @imgs = Imager->read_multi(file => 'somefile.gif')
4697 or die Imager->errstr;
4699 Note that in some cases object methods are implemented in terms of
4700 class methods so a failing object method may set both.
4704 The C<Imager-E<gt>new> method is described in detail in
4705 L<Imager::ImageTypes>.
4709 Where to find information on methods for Imager class objects.
4711 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4714 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4716 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4719 alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
4720 channel index of the alpha channel (if any).
4722 arc() - L<Imager::Draw/arc()> - draw a filled arc
4724 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4727 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4729 check_file_limits() - L<Imager::Files/check_file_limits()>
4731 circle() - L<Imager::Draw/circle()> - draw a filled circle
4733 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4736 colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
4737 of channels used for color.
4739 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4740 colors in an image's palette (paletted images only)
4742 colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
4745 combine() - L<Imager::Transformations/combine()> - combine channels
4746 from one or more images.
4748 combines() - L<Imager::Draw/combines()> - return a list of the
4749 different combine type keywords
4751 compose() - L<Imager::Transformations/compose()> - compose one image
4754 convert() - L<Imager::Transformations/convert()> - transform the color
4757 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4760 crop() - L<Imager::Transformations/crop()> - extract part of an image
4762 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4763 used to guess the output file format based on the output file name
4765 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4767 difference() - L<Imager::Filters/difference()> - produce a difference
4768 images from two input images.
4770 errstr() - L</errstr()> - the error from the last failed operation.
4772 filter() - L<Imager::Filters/filter()> - image filtering
4774 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4775 palette, if it has one
4777 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4780 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4783 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4784 samples per pixel for an image
4786 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4787 different colors used by an image (works for direct color images)
4789 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4790 palette, if it has one
4792 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4794 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4796 get_file_limits() - L<Imager::Files/get_file_limits()>
4798 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4801 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4803 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4806 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4807 row or partial row of pixels.
4809 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4810 row or partial row of pixels.
4812 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4815 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4818 init() - L<Imager::ImageTypes/init()>
4820 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4821 image write functions should write the image in their bilevel (blank
4822 and white, no gray levels) format
4824 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4827 line() - L<Imager::Draw/line()> - draw an interval
4829 load_plugin() - L<Imager::Filters/load_plugin()>
4831 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4834 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4835 color palette from one or more input images.
4837 map() - L<Imager::Transformations/map()> - remap color
4840 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4842 matrix_transform() - L<Imager::Engines/matrix_transform()>
4844 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4846 NC() - L<Imager::Handy/NC()>
4848 NCF() - L<Imager::Handy/NCF()>
4850 new() - L<Imager::ImageTypes/new()>
4852 newcolor() - L<Imager::Handy/newcolor()>
4854 newcolour() - L<Imager::Handy/newcolour()>
4856 newfont() - L<Imager::Handy/newfont()>
4858 NF() - L<Imager::Handy/NF()>
4860 open() - L<Imager::Files/read()> - an alias for read()
4862 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4866 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4869 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4872 polygon() - L<Imager::Draw/polygon()>
4874 polyline() - L<Imager::Draw/polyline()>
4876 polypolygon() - L<Imager::Draw/polypolygon()>
4878 preload() - L<Imager::Files/preload()>
4880 read() - L<Imager::Files/read()> - read a single image from an image file
4882 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4885 read_types() - L<Imager::Files/read_types()> - list image types Imager
4888 register_filter() - L<Imager::Filters/register_filter()>
4890 register_reader() - L<Imager::Files/register_reader()>
4892 register_writer() - L<Imager::Files/register_writer()>
4894 rotate() - L<Imager::Transformations/rotate()>
4896 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4897 onto an image and use the alpha channel
4899 scale() - L<Imager::Transformations/scale()>
4901 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4903 scaleX() - L<Imager::Transformations/scaleX()>
4905 scaleY() - L<Imager::Transformations/scaleY()>
4907 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4910 set_file_limits() - L<Imager::Files/set_file_limits()>
4912 setmask() - L<Imager::ImageTypes/setmask()>
4914 setpixel() - L<Imager::Draw/setpixel()>
4916 setsamples() - L<Imager::Draw/setsamples()>
4918 setscanline() - L<Imager::Draw/setscanline()>
4920 settag() - L<Imager::ImageTypes/settag()>
4922 string() - L<Imager::Draw/string()> - draw text on an image
4924 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4926 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4928 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4930 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4932 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4933 double per sample image.
4935 transform() - L<Imager::Engines/"transform()">
4937 transform2() - L<Imager::Engines/"transform2()">
4939 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4941 unload_plugin() - L<Imager::Filters/unload_plugin()>
4943 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4946 write() - L<Imager::Files/write()> - write an image to a file
4948 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4951 write_types() - L<Imager::Files/read_types()> - list image types Imager
4954 =head1 CONCEPT INDEX
4956 animated GIF - L<Imager::Files/"Writing an animated GIF">
4958 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4959 L<Imager::ImageTypes/"Common Tags">.
4961 blend - alpha blending one image onto another
4962 L<Imager::Transformations/rubthrough()>
4964 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4966 boxes, drawing - L<Imager::Draw/box()>
4968 changes between image - L<Imager::Filters/"Image Difference">
4970 channels, combine into one image - L<Imager::Transformations/combine()>
4972 color - L<Imager::Color>
4974 color names - L<Imager::Color>, L<Imager::Color::Table>
4976 combine modes - L<Imager::Draw/"Combine Types">
4978 compare images - L<Imager::Filters/"Image Difference">
4980 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4982 convolution - L<Imager::Filters/conv>
4984 cropping - L<Imager::Transformations/crop()>
4986 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4988 C<diff> images - L<Imager::Filters/"Image Difference">
4990 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4991 L<Imager::Cookbook/"Image spatial resolution">
4993 drawing boxes - L<Imager::Draw/box()>
4995 drawing lines - L<Imager::Draw/line()>
4997 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4999 error message - L</"ERROR HANDLING">
5001 files, font - L<Imager::Font>
5003 files, image - L<Imager::Files>
5005 filling, types of fill - L<Imager::Fill>
5007 filling, boxes - L<Imager::Draw/box()>
5009 filling, flood fill - L<Imager::Draw/flood_fill()>
5011 flood fill - L<Imager::Draw/flood_fill()>
5013 fonts - L<Imager::Font>
5015 fonts, drawing with - L<Imager::Draw/string()>,
5016 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
5018 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5020 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
5022 fountain fill - L<Imager::Fill/"Fountain fills">,
5023 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5024 L<Imager::Filters/gradgen>
5026 GIF files - L<Imager::Files/"GIF">
5028 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
5030 gradient fill - L<Imager::Fill/"Fountain fills">,
5031 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5032 L<Imager::Filters/gradgen>
5034 gray scale, convert image to - L<Imager::Transformations/convert()>
5036 gaussian blur - L<Imager::Filters/gaussian>
5038 hatch fills - L<Imager::Fill/"Hatched fills">
5040 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5042 invert image - L<Imager::Filters/hardinvert>,
5043 L<Imager::Filters/hardinvertall>
5045 JPEG - L<Imager::Files/"JPEG">
5047 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
5049 lines, drawing - L<Imager::Draw/line()>
5051 matrix - L<Imager::Matrix2d>,
5052 L<Imager::Engines/"Matrix Transformations">,
5053 L<Imager::Font/transform()>
5055 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5057 mosaic - L<Imager::Filters/mosaic>
5059 noise, filter - L<Imager::Filters/noise>
5061 noise, rendered - L<Imager::Filters/turbnoise>,
5062 L<Imager::Filters/radnoise>
5064 paste - L<Imager::Transformations/paste()>,
5065 L<Imager::Transformations/rubthrough()>
5067 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5068 L<Imager::ImageTypes/new()>
5070 =for stopwords posterize
5072 posterize - L<Imager::Filters/postlevels>
5074 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5076 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5078 rectangles, drawing - L<Imager::Draw/box()>
5080 resizing an image - L<Imager::Transformations/scale()>,
5081 L<Imager::Transformations/crop()>
5083 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5085 saving an image - L<Imager::Files>
5087 scaling - L<Imager::Transformations/scale()>
5089 security - L<Imager::Security>
5091 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5093 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
5095 size, image - L<Imager::ImageTypes/getwidth()>,
5096 L<Imager::ImageTypes/getheight()>
5098 size, text - L<Imager::Font/bounding_box()>
5100 tags, image metadata - L<Imager::ImageTypes/"Tags">
5102 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5103 L<Imager::Font::Wrap>
5105 text, wrapping text in an area - L<Imager::Font::Wrap>
5107 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5109 threads - L<Imager::Threads>
5111 tiles, color - L<Imager::Filters/mosaic>
5113 transparent images - L<Imager::ImageTypes>,
5114 L<Imager::Cookbook/"Transparent PNG">
5116 =for stopwords unsharp
5118 unsharp mask - L<Imager::Filters/unsharpmask>
5120 watermark - L<Imager::Filters/watermark>
5122 writing an image to a file - L<Imager::Files>
5126 The best place to get help with Imager is the mailing list.
5128 To subscribe send a message with C<subscribe> in the body to:
5130 imager-devel+request@molar.is
5136 L<http://www.molar.is/en/lists/imager-devel/>
5140 where you can also find the mailing list archive.
5142 You can report bugs by pointing your browser at:
5146 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5150 or by sending an email to:
5154 bug-Imager@rt.cpan.org
5158 Please remember to include the versions of Imager, perl, supporting
5159 libraries, and any relevant code. If you have specific images that
5160 cause the problems, please include those too.
5162 If you don't want to publish your email address on a mailing list you
5163 can use CPAN::Forum:
5165 http://www.cpanforum.com/dist/Imager
5167 You will need to register to post.
5169 =head1 CONTRIBUTING TO IMAGER
5175 If you like or dislike Imager, you can add a public review of Imager
5178 http://cpanratings.perl.org/dist/Imager
5180 =for stopwords Bitcard
5182 This requires a Bitcard account (http://www.bitcard.org).
5184 You can also send email to the maintainer below.
5186 If you send me a bug report via email, it will be copied to Request
5191 I accept patches, preferably against the master branch in git. Please
5192 include an explanation of the reason for why the patch is needed or
5195 Your patch should include regression tests where possible, otherwise
5196 it will be delayed until I get a chance to write them.
5198 To browse Imager's git repository:
5200 http://git.imager.perl.org/imager.git
5204 git clone git://git.imager.perl.org/imager.git
5206 My preference is that patches are provided in the format produced by
5207 C<git format-patch>, for example, if you made your changes in a branch
5208 from master you might do:
5210 git format-patch -k --stdout master >my-patch.txt
5212 and then attach that to your bug report, either by adding it as an
5213 attachment in your email client, or by using the Request Tracker
5214 attachment mechanism.
5218 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5220 Arnar M. Hrafnkelsson is the original author of Imager.
5222 Many others have contributed to Imager, please see the C<README> for a
5227 Imager is licensed under the same terms as perl itself.
5230 makeblendedfont Fontforge
5232 A test font, generated by the Debian packaged Fontforge,
5233 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5234 copyrighted by Adobe. See F<adobe.txt> in the source for license
5239 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5240 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5241 L<Imager::Font>(3), L<Imager::Transformations>(3),
5242 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5243 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5245 L<http://imager.perl.org/>
5247 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5249 Other perl imaging modules include:
5251 L<GD>(3), L<Image::Magick>(3),
5252 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5253 L<Prima::Image>, L<IPA>.
5255 For manipulating image metadata see L<Image::ExifTool>.
5257 If you're trying to use Imager for array processing, you should
5258 probably using L<PDL>.