4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
109 # registered file readers
112 # registered file writers
115 # modules we attempted to autoload
116 my %attempted_to_load;
118 # errors from loading files
119 my %file_load_errors;
121 # what happened when we tried to load
122 my %reader_load_errors;
123 my %writer_load_errors;
125 # library keys that are image file formats
126 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
128 # image pixel combine types
130 qw/none normal multiply dissolve add subtract diff lighten darken
131 hue saturation value color/;
133 @combine_types{@combine_types} = 0 .. $#combine_types;
134 $combine_types{mult} = $combine_types{multiply};
135 $combine_types{'sub'} = $combine_types{subtract};
136 $combine_types{sat} = $combine_types{saturation};
138 # this will be used to store global defaults at some point
143 my $ex_version = eval $Exporter::VERSION;
144 if ($ex_version < 5.57) {
149 XSLoader::load(Imager => $VERSION);
155 png => "Imager::File::PNG",
156 gif => "Imager::File::GIF",
157 tiff => "Imager::File::TIFF",
158 jpeg => "Imager::File::JPEG",
159 w32 => "Imager::Font::W32",
160 ft2 => "Imager::Font::FT2",
161 t1 => "Imager::Font::T1",
164 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
167 for(i_list_formats()) { $formats_low{$_}++; }
169 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
173 # the members of the subhashes under %filters are:
174 # callseq - a list of the parameters to the underlying filter in the
175 # order they are passed
176 # callsub - a code ref that takes a named parameter list and calls the
178 # defaults - a hash of default values
179 # names - defines names for value of given parameters so if the names
180 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
181 # foo parameter, the filter will receive 1 for the foo
184 callseq => ['image','intensity'],
185 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
189 callseq => ['image', 'amount', 'subtype'],
190 defaults => { amount=>3,subtype=>0 },
191 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
194 $filters{hardinvert} ={
195 callseq => ['image'],
197 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
200 $filters{hardinvertall} =
202 callseq => ['image'],
204 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
207 $filters{autolevels_skew} ={
208 callseq => ['image','lsat','usat','skew'],
209 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
210 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
213 $filters{autolevels} ={
214 callseq => ['image','lsat','usat'],
215 defaults => { lsat=>0.1,usat=>0.1 },
216 callsub => sub { my %hsh=@_; i_autolevels_mono($hsh{image},$hsh{lsat},$hsh{usat}); }
219 $filters{turbnoise} ={
220 callseq => ['image'],
221 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
222 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
225 $filters{radnoise} ={
226 callseq => ['image'],
227 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
228 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
233 callseq => ['image', 'coef'],
238 i_conv($hsh{image},$hsh{coef})
239 or die Imager->_error_as_msg() . "\n";
245 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
246 defaults => { dist => 0 },
250 my @colors = @{$hsh{colors}};
253 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
257 $filters{nearest_color} =
259 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
264 # make sure the segments are specified with colors
266 for my $color (@{$hsh{colors}}) {
267 my $new_color = _color($color)
268 or die $Imager::ERRSTR."\n";
269 push @colors, $new_color;
272 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
274 or die Imager->_error_as_msg() . "\n";
277 $filters{gaussian} = {
278 callseq => [ 'image', 'stddev' ],
280 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
284 callseq => [ qw(image size) ],
285 defaults => { size => 20 },
286 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
290 callseq => [ qw(image bump elevation lightx lighty st) ],
291 defaults => { elevation=>0, st=> 2 },
294 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
295 $hsh{lightx}, $hsh{lighty}, $hsh{st});
298 $filters{bumpmap_complex} =
300 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
317 for my $cname (qw/Ia Il Is/) {
318 my $old = $hsh{$cname};
319 my $new_color = _color($old)
320 or die $Imager::ERRSTR, "\n";
321 $hsh{$cname} = $new_color;
323 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
324 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
325 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
329 $filters{postlevels} =
331 callseq => [ qw(image levels) ],
332 defaults => { levels => 10 },
333 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
335 $filters{watermark} =
337 callseq => [ qw(image wmark tx ty pixdiff) ],
338 defaults => { pixdiff=>10, tx=>0, ty=>0 },
342 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
348 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
350 ftype => { linear => 0,
356 repeat => { none => 0,
371 multiply => 2, mult => 2,
374 subtract => 5, 'sub' => 5,
384 defaults => { ftype => 0, repeat => 0, combine => 0,
385 super_sample => 0, ssample_param => 4,
398 # make sure the segments are specified with colors
400 for my $segment (@{$hsh{segments}}) {
401 my @new_segment = @$segment;
403 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
404 push @segments, \@new_segment;
407 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
408 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
409 $hsh{ssample_param}, \@segments)
410 or die Imager->_error_as_msg() . "\n";
413 $filters{unsharpmask} =
415 callseq => [ qw(image stddev scale) ],
416 defaults => { stddev=>2.0, scale=>1.0 },
420 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
424 $FORMATGUESS=\&def_guess_type;
434 # NOTE: this might be moved to an import override later on
439 if ($_[$i] eq '-log-stderr') {
447 goto &Exporter::import;
451 Imager->open_log(log => $_[0], level => $_[1]);
456 my %parms=(loglevel=>1,@_);
458 if (exists $parms{'warn_obsolete'}) {
459 $warn_obsolete = $parms{'warn_obsolete'};
463 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
467 if (exists $parms{'t1log'}) {
469 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
470 Imager->_set_error(Imager->_error_as_msg);
484 my (%opts) = ( loglevel => 1, @_ );
486 $is_logging = i_init_log($opts{log}, $opts{loglevel});
487 unless ($is_logging) {
488 Imager->_set_error(Imager->_error_as_msg());
492 Imager->log("Imager $VERSION starting\n", 1);
498 i_init_log(undef, -1);
503 my ($class, $message, $level) = @_;
505 defined $level or $level = 1;
507 i_log_entry($message, $level);
517 print "shutdown code\n";
518 # for(keys %instances) { $instances{$_}->DESTROY(); }
519 malloc_state(); # how do decide if this should be used? -- store something from the import
520 print "Imager exiting\n";
524 # Load a filter plugin
530 if ($^O eq 'android') {
532 $filename = File::Spec->rel2abs($filename);
535 my ($DSO_handle,$str)=DSO_open($filename);
536 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
537 my %funcs=DSO_funclist($DSO_handle);
538 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
540 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
542 $DSOs{$filename}=[$DSO_handle,\%funcs];
545 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
546 $DEBUG && print "eval string:\n",$evstr,"\n";
558 if ($^O eq 'android') {
560 $filename = File::Spec->rel2abs($filename);
563 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
564 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
565 for(keys %{$funcref}) {
567 $DEBUG && print "unloading: $_\n";
569 my $rc=DSO_close($DSO_handle);
570 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
574 # take the results of i_error() and make a message out of it
576 return join(": ", map $_->[0], i_errors());
579 # this function tries to DWIM for color parameters
580 # color objects are used as is
581 # simple scalars are simply treated as single parameters to Imager::Color->new
582 # hashrefs are treated as named argument lists to Imager::Color->new
583 # arrayrefs are treated as list arguments to Imager::Color->new iff any
585 # other arrayrefs are treated as list arguments to Imager::Color::Float
589 # perl 5.6.0 seems to do weird things to $arg if we don't make an
590 # explicitly stringified copy
591 # I vaguely remember a bug on this on p5p, but couldn't find it
592 # through bugs.perl.org (I had trouble getting it to find any bugs)
593 my $copy = $arg . "";
597 if (UNIVERSAL::isa($arg, "Imager::Color")
598 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
602 if ($copy =~ /^HASH\(/) {
603 $result = Imager::Color->new(%$arg);
605 elsif ($copy =~ /^ARRAY\(/) {
606 $result = Imager::Color->new(@$arg);
609 $Imager::ERRSTR = "Not a color";
614 # assume Imager::Color::new knows how to handle it
615 $result = Imager::Color->new($arg);
622 my ($self, $combine, $default) = @_;
624 if (!defined $combine && ref $self) {
625 $combine = $self->{combine};
627 defined $combine or $combine = $defaults{combine};
628 defined $combine or $combine = $default;
630 if (exists $combine_types{$combine}) {
631 $combine = $combine_types{$combine};
638 my ($self, $method) = @_;
641 or return Imager->_set_error("$method needs an image object");
643 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
645 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
646 $msg = "$method: $msg" if $method;
647 $self->_set_error($msg);
652 # returns first defined parameter
655 return $_ if defined $_;
661 # Methods to be called on objects.
664 # Create a new Imager object takes very few parameters.
665 # usually you call this method and then call open from
666 # the resulting object
673 $self->{IMG}=undef; # Just to indicate what exists
674 $self->{ERRSTR}=undef; #
675 $self->{DEBUG}=$DEBUG;
676 $self->{DEBUG} and print "Initialized Imager\n";
677 if (defined $hsh{file} ||
680 defined $hsh{callback} ||
681 defined $hsh{readcb} ||
682 defined $hsh{data} ||
684 # allow $img = Imager->new(file => $filename)
687 # type is already used as a parameter to new(), rename it for the
689 if ($hsh{filetype}) {
690 $extras{type} = $hsh{filetype};
692 unless ($self->read(%hsh, %extras)) {
693 $Imager::ERRSTR = $self->{ERRSTR};
697 elsif (defined $hsh{xsize} || defined $hsh{ysize}) {
698 unless ($self->img_set(%hsh)) {
699 $Imager::ERRSTR = $self->{ERRSTR};
704 Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
711 # Copy an entire image with no changes
712 # - if an image has magic the copy of it will not be magical
717 $self->_valid_image("copy")
720 unless (defined wantarray) {
722 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
726 my $newcopy=Imager->new();
727 $newcopy->{IMG} = i_copy($self->{IMG});
736 $self->_valid_image("paste")
739 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
740 my $src = $input{img} || $input{src};
742 $self->_set_error("no source image");
745 unless ($src->_valid_image("paste")) {
746 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
749 $input{left}=0 if $input{left} <= 0;
750 $input{top}=0 if $input{top} <= 0;
752 my($r,$b)=i_img_info($src->{IMG});
753 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
754 my ($src_right, $src_bottom);
755 if ($input{src_coords}) {
756 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
759 if (defined $input{src_maxx}) {
760 $src_right = $input{src_maxx};
762 elsif (defined $input{width}) {
763 if ($input{width} <= 0) {
764 $self->_set_error("paste: width must me positive");
767 $src_right = $src_left + $input{width};
772 if (defined $input{src_maxy}) {
773 $src_bottom = $input{src_maxy};
775 elsif (defined $input{height}) {
776 if ($input{height} < 0) {
777 $self->_set_error("paste: height must be positive");
780 $src_bottom = $src_top + $input{height};
787 $src_right > $r and $src_right = $r;
788 $src_bottom > $b and $src_bottom = $b;
790 if ($src_right <= $src_left
791 || $src_bottom < $src_top) {
792 $self->_set_error("nothing to paste");
796 i_copyto($self->{IMG}, $src->{IMG},
797 $src_left, $src_top, $src_right, $src_bottom,
798 $input{left}, $input{top});
800 return $self; # What should go here??
803 # Crop an image - i.e. return a new image that is smaller
808 $self->_valid_image("crop")
811 unless (defined wantarray) {
813 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
819 my ($w, $h, $l, $r, $b, $t) =
820 @hsh{qw(width height left right bottom top)};
822 # work through the various possibilities
827 elsif (!defined $r) {
828 $r = $self->getwidth;
840 $l = int(0.5+($self->getwidth()-$w)/2);
845 $r = $self->getwidth;
851 elsif (!defined $b) {
852 $b = $self->getheight;
864 $t=int(0.5+($self->getheight()-$h)/2);
869 $b = $self->getheight;
872 ($l,$r)=($r,$l) if $l>$r;
873 ($t,$b)=($b,$t) if $t>$b;
876 $r > $self->getwidth and $r = $self->getwidth;
878 $b > $self->getheight and $b = $self->getheight;
880 if ($l == $r || $t == $b) {
881 $self->_set_error("resulting image would have no content");
884 if( $r < $l or $b < $t ) {
885 $self->_set_error("attempting to crop outside of the image");
888 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
890 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
895 my ($self, %opts) = @_;
900 my $x = $opts{xsize} || $self->getwidth;
901 my $y = $opts{ysize} || $self->getheight;
902 my $channels = $opts{channels} || $self->getchannels;
904 my $out = Imager->new;
905 if ($channels == $self->getchannels) {
906 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
909 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
911 unless ($out->{IMG}) {
912 $self->{ERRSTR} = $self->_error_as_msg;
919 # Sets an image to a certain size and channel number
920 # if there was previously data in the image it is discarded
933 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
938 if (my $channels = $model_channels{$hsh{model}}) {
939 $hsh{channels} = $channels;
942 $self->_set_error("new: unknown value for model '$hsh{model}'");
947 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
948 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
949 $hsh{maxcolors} || 256);
951 elsif ($hsh{bits} eq 'double') {
952 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
954 elsif ($hsh{bits} == 16) {
955 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
958 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
962 unless ($self->{IMG}) {
963 $self->_set_error(Imager->_error_as_msg());
970 # created a masked version of the current image
974 $self->_valid_image("masked")
977 my %opts = (left => 0,
979 right => $self->getwidth,
980 bottom => $self->getheight,
982 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
984 my $result = Imager->new;
985 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
986 $opts{top}, $opts{right} - $opts{left},
987 $opts{bottom} - $opts{top});
988 unless ($result->{IMG}) {
989 $self->_set_error(Imager->_error_as_msg);
993 # keep references to the mask and base images so they don't
995 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
1000 # convert an RGB image into a paletted image
1004 if (@_ != 1 && !ref $_[0]) {
1011 unless (defined wantarray) {
1012 my @caller = caller;
1013 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
1017 $self->_valid_image("to_paletted")
1020 my $result = Imager->new;
1021 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1022 $self->_set_error(Imager->_error_as_msg);
1030 my ($class, $quant, @images) = @_;
1033 Imager->_set_error("make_palette: supply at least one image");
1037 for my $img (@images) {
1038 unless ($img->{IMG}) {
1039 Imager->_set_error("make_palette: image $index is empty");
1045 return i_img_make_palette($quant, map $_->{IMG}, @images);
1048 # convert a paletted (or any image) to an 8-bit/channel RGB image
1052 unless (defined wantarray) {
1053 my @caller = caller;
1054 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1058 $self->_valid_image("to_rgb8")
1061 my $result = Imager->new;
1062 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1063 $self->_set_error(Imager->_error_as_msg());
1070 # convert a paletted (or any image) to a 16-bit/channel RGB image
1074 unless (defined wantarray) {
1075 my @caller = caller;
1076 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1080 $self->_valid_image("to_rgb16")
1083 my $result = Imager->new;
1084 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1085 $self->_set_error(Imager->_error_as_msg());
1092 # convert a paletted (or any image) to an double/channel RGB image
1096 unless (defined wantarray) {
1097 my @caller = caller;
1098 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1102 $self->_valid_image("to_rgb_double")
1105 my $result = Imager->new;
1106 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1107 $self->_set_error(Imager->_error_as_msg());
1116 my %opts = (colors=>[], @_);
1118 $self->_valid_image("addcolors")
1121 my @colors = @{$opts{colors}}
1124 for my $color (@colors) {
1125 $color = _color($color);
1127 $self->_set_error($Imager::ERRSTR);
1132 return i_addcolors($self->{IMG}, @colors);
1137 my %opts = (start=>0, colors=>[], @_);
1139 $self->_valid_image("setcolors")
1142 my @colors = @{$opts{colors}}
1145 for my $color (@colors) {
1146 $color = _color($color);
1148 $self->_set_error($Imager::ERRSTR);
1153 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1160 $self->_valid_image("getcolors")
1163 if (!exists $opts{start} && !exists $opts{count}) {
1166 $opts{count} = $self->colorcount;
1168 elsif (!exists $opts{count}) {
1171 elsif (!exists $opts{start}) {
1175 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1181 $self->_valid_image("colorcount")
1184 return i_colorcount($self->{IMG});
1190 $self->_valid_image("maxcolors")
1193 i_maxcolors($self->{IMG});
1200 $self->_valid_image("findcolor")
1203 unless ($opts{color}) {
1204 $self->_set_error("findcolor: no color parameter");
1208 my $color = _color($opts{color})
1211 return i_findcolor($self->{IMG}, $color);
1217 $self->_valid_image("bits")
1220 my $bits = i_img_bits($self->{IMG});
1221 if ($bits && $bits == length(pack("d", 1)) * 8) {
1230 $self->_valid_image("type")
1233 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1239 $self->_valid_image("virtual")
1242 return i_img_virtual($self->{IMG});
1248 $self->_valid_image("is_bilevel")
1251 return i_img_is_monochrome($self->{IMG});
1255 my ($self, %opts) = @_;
1257 $self->_valid_image("tags")
1260 if (defined $opts{name}) {
1264 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1265 push @result, (i_tags_get($self->{IMG}, $found))[1];
1268 return wantarray ? @result : $result[0];
1270 elsif (defined $opts{code}) {
1274 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1275 push @result, (i_tags_get($self->{IMG}, $found))[1];
1282 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1285 return i_tags_count($self->{IMG});
1294 $self->_valid_image("addtag")
1298 if (defined $opts{value}) {
1299 if ($opts{value} =~ /^\d+$/) {
1301 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1304 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1307 elsif (defined $opts{data}) {
1308 # force addition as a string
1309 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1312 $self->{ERRSTR} = "No value supplied";
1316 elsif ($opts{code}) {
1317 if (defined $opts{value}) {
1318 if ($opts{value} =~ /^\d+$/) {
1320 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1323 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1326 elsif (defined $opts{data}) {
1327 # force addition as a string
1328 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1331 $self->{ERRSTR} = "No value supplied";
1344 $self->_valid_image("deltag")
1347 if (defined $opts{'index'}) {
1348 return i_tags_delete($self->{IMG}, $opts{'index'});
1350 elsif (defined $opts{name}) {
1351 return i_tags_delbyname($self->{IMG}, $opts{name});
1353 elsif (defined $opts{code}) {
1354 return i_tags_delbycode($self->{IMG}, $opts{code});
1357 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1363 my ($self, %opts) = @_;
1365 $self->_valid_image("settag")
1369 $self->deltag(name=>$opts{name});
1370 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1372 elsif (defined $opts{code}) {
1373 $self->deltag(code=>$opts{code});
1374 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1382 sub _get_reader_io {
1383 my ($self, $input) = @_;
1386 return $input->{io}, undef;
1388 elsif ($input->{fd}) {
1389 return io_new_fd($input->{fd});
1391 elsif ($input->{fh}) {
1392 unless (Scalar::Util::openhandle($input->{fh})) {
1393 $self->_set_error("Handle in fh option not opened");
1396 return Imager::IO->new_fh($input->{fh});
1398 elsif ($input->{file}) {
1399 my $file = IO::File->new($input->{file}, "r");
1401 $self->_set_error("Could not open $input->{file}: $!");
1405 return (io_new_fd(fileno($file)), $file);
1407 elsif ($input->{data}) {
1408 return io_new_buffer($input->{data});
1410 elsif ($input->{callback} || $input->{readcb}) {
1411 if (!$input->{seekcb}) {
1412 $self->_set_error("Need a seekcb parameter");
1414 if ($input->{maxbuffer}) {
1415 return io_new_cb($input->{writecb},
1416 $input->{callback} || $input->{readcb},
1417 $input->{seekcb}, $input->{closecb},
1418 $input->{maxbuffer});
1421 return io_new_cb($input->{writecb},
1422 $input->{callback} || $input->{readcb},
1423 $input->{seekcb}, $input->{closecb});
1427 $self->_set_error("file/fd/fh/data/callback parameter missing");
1432 sub _get_writer_io {
1433 my ($self, $input) = @_;
1435 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1442 elsif ($input->{fd}) {
1443 $io = io_new_fd($input->{fd});
1445 elsif ($input->{fh}) {
1446 unless (Scalar::Util::openhandle($input->{fh})) {
1447 $self->_set_error("Handle in fh option not opened");
1450 $io = Imager::IO->new_fh($input->{fh});
1452 elsif ($input->{file}) {
1453 my $fh = new IO::File($input->{file},"w+");
1455 $self->_set_error("Could not open file $input->{file}: $!");
1458 binmode($fh) or die;
1459 $io = io_new_fd(fileno($fh));
1462 elsif ($input->{data}) {
1463 $io = io_new_bufchain();
1465 elsif ($input->{callback} || $input->{writecb}) {
1466 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1469 $io = io_new_cb($input->{callback} || $input->{writecb},
1471 $input->{seekcb}, $input->{closecb});
1474 $self->_set_error("file/fd/fh/data/callback parameter missing");
1478 unless ($buffered) {
1479 $io->set_buffered(0);
1482 return ($io, @extras);
1485 # Read an image from file
1491 if (defined($self->{IMG})) {
1492 # let IIM_DESTROY do the destruction, since the image may be
1493 # referenced from elsewhere
1494 #i_img_destroy($self->{IMG});
1495 undef($self->{IMG});
1498 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1500 my $type = $input{'type'};
1502 $type = i_test_format_probe($IO, -1);
1505 if ($input{file} && !$type) {
1507 $type = $FORMATGUESS->($input{file});
1511 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1512 $input{file} and $msg .= " or file name";
1513 $self->_set_error($msg);
1517 _reader_autoload($type);
1519 if ($readers{$type} && $readers{$type}{single}) {
1520 return $readers{$type}{single}->($self, $IO, %input);
1523 unless ($formats_low{$type}) {
1524 my $read_types = join ', ', sort Imager->read_types();
1525 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1529 my $allow_incomplete = $input{allow_incomplete};
1530 defined $allow_incomplete or $allow_incomplete = 0;
1532 if ( $type eq 'pnm' ) {
1533 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1534 if ( !defined($self->{IMG}) ) {
1535 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1538 $self->{DEBUG} && print "loading a pnm file\n";
1542 if ( $type eq 'bmp' ) {
1543 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1544 if ( !defined($self->{IMG}) ) {
1545 $self->{ERRSTR}=$self->_error_as_msg();
1548 $self->{DEBUG} && print "loading a bmp file\n";
1551 if ( $type eq 'tga' ) {
1552 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1553 if ( !defined($self->{IMG}) ) {
1554 $self->{ERRSTR}=$self->_error_as_msg();
1557 $self->{DEBUG} && print "loading a tga file\n";
1560 if ( $type eq 'raw' ) {
1561 unless ( $input{xsize} && $input{ysize} ) {
1562 $self->_set_error('missing xsize or ysize parameter for raw');
1566 my $interleave = _first($input{raw_interleave}, $input{interleave});
1567 unless (defined $interleave) {
1568 my @caller = caller;
1569 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1572 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1573 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1575 $self->{IMG} = i_readraw_wiol( $IO,
1581 if ( !defined($self->{IMG}) ) {
1582 $self->{ERRSTR}=$self->_error_as_msg();
1585 $self->{DEBUG} && print "loading a raw file\n";
1591 sub register_reader {
1592 my ($class, %opts) = @_;
1595 or die "register_reader called with no type parameter\n";
1597 my $type = $opts{type};
1599 defined $opts{single} || defined $opts{multiple}
1600 or die "register_reader called with no single or multiple parameter\n";
1602 $readers{$type} = { };
1603 if ($opts{single}) {
1604 $readers{$type}{single} = $opts{single};
1606 if ($opts{multiple}) {
1607 $readers{$type}{multiple} = $opts{multiple};
1613 sub register_writer {
1614 my ($class, %opts) = @_;
1617 or die "register_writer called with no type parameter\n";
1619 my $type = $opts{type};
1621 defined $opts{single} || defined $opts{multiple}
1622 or die "register_writer called with no single or multiple parameter\n";
1624 $writers{$type} = { };
1625 if ($opts{single}) {
1626 $writers{$type}{single} = $opts{single};
1628 if ($opts{multiple}) {
1629 $writers{$type}{multiple} = $opts{multiple};
1640 grep($file_formats{$_}, keys %formats),
1641 qw(ico sgi), # formats not handled directly, but supplied with Imager
1652 grep($file_formats{$_}, keys %formats),
1653 qw(ico sgi), # formats not handled directly, but supplied with Imager
1660 my ($file, $error) = @_;
1662 if ($attempted_to_load{$file}) {
1663 if ($file_load_errors{$file}) {
1664 $$error = $file_load_errors{$file};
1672 local $SIG{__DIE__};
1675 pop @INC if $INC[-1] eq '.';
1676 ++$attempted_to_load{$file};
1684 my $work = $@ || "Unknown error";
1686 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1687 $work =~ s/\n/\\n/g;
1688 $work =~ s/\s*\.?\z/ loading $file/;
1689 $file_load_errors{$file} = $work;
1696 # probes for an Imager::File::whatever module
1697 sub _reader_autoload {
1700 return if $formats_low{$type} || $readers{$type};
1702 return unless $type =~ /^\w+$/;
1704 my $file = "Imager/File/\U$type\E.pm";
1707 my $loaded = _load_file($file, \$error);
1708 if (!$loaded && $error =~ /^Can't locate /) {
1709 my $filer = "Imager/File/\U$type\EReader.pm";
1710 $loaded = _load_file($filer, \$error);
1711 if ($error =~ /^Can't locate /) {
1712 $error = "Can't locate $file or $filer";
1716 $reader_load_errors{$type} = $error;
1720 # probes for an Imager::File::whatever module
1721 sub _writer_autoload {
1724 return if $formats_low{$type} || $writers{$type};
1726 return unless $type =~ /^\w+$/;
1728 my $file = "Imager/File/\U$type\E.pm";
1731 my $loaded = _load_file($file, \$error);
1732 if (!$loaded && $error =~ /^Can't locate /) {
1733 my $filew = "Imager/File/\U$type\EWriter.pm";
1734 $loaded = _load_file($filew, \$error);
1735 if ($error =~ /^Can't locate /) {
1736 $error = "Can't locate $file or $filew";
1740 $writer_load_errors{$type} = $error;
1744 sub _fix_gif_positions {
1745 my ($opts, $opt, $msg, @imgs) = @_;
1747 my $positions = $opts->{'gif_positions'};
1749 for my $pos (@$positions) {
1750 my ($x, $y) = @$pos;
1751 my $img = $imgs[$index++];
1752 $img->settag(name=>'gif_left', value=>$x);
1753 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1755 $$msg .= "replaced with the gif_left and gif_top tags";
1760 gif_each_palette=>'gif_local_map',
1761 interlace => 'gif_interlace',
1762 gif_delays => 'gif_delay',
1763 gif_positions => \&_fix_gif_positions,
1764 gif_loop_count => 'gif_loop',
1767 # options that should be converted to colors
1768 my %color_opts = map { $_ => 1 } qw/i_background/;
1771 my ($self, $opts, $prefix, @imgs) = @_;
1773 for my $opt (keys %$opts) {
1775 if ($obsolete_opts{$opt}) {
1776 my $new = $obsolete_opts{$opt};
1777 my $msg = "Obsolete option $opt ";
1779 $new->($opts, $opt, \$msg, @imgs);
1782 $msg .= "replaced with the $new tag ";
1785 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1786 warn $msg if $warn_obsolete && $^W;
1788 next unless $tagname =~ /^\Q$prefix/;
1789 my $value = $opts->{$opt};
1790 if ($color_opts{$opt}) {
1791 $value = _color($value);
1793 $self->_set_error($Imager::ERRSTR);
1798 if (UNIVERSAL::isa($value, "Imager::Color")) {
1799 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1800 for my $img (@imgs) {
1801 $img->settag(name=>$tagname, value=>$tag);
1804 elsif (ref($value) eq 'ARRAY') {
1805 for my $i (0..$#$value) {
1806 my $val = $value->[$i];
1808 if (UNIVERSAL::isa($val, "Imager::Color")) {
1809 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1811 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1814 $self->_set_error("Unknown reference type " . ref($value) .
1815 " supplied in array for $opt");
1821 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1826 $self->_set_error("Unknown reference type " . ref($value) .
1827 " supplied for $opt");
1832 # set it as a tag for every image
1833 for my $img (@imgs) {
1834 $img->settag(name=>$tagname, value=>$value);
1842 # Write an image to file
1845 my %input=(jpegquality=>75,
1855 $self->_valid_image("write")
1858 $self->_set_opts(\%input, "i_", $self)
1861 my $type = $input{'type'};
1862 if (!$type and $input{file}) {
1863 $type = $FORMATGUESS->($input{file});
1866 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1870 _writer_autoload($type);
1873 if ($writers{$type} && $writers{$type}{single}) {
1874 ($IO, $fh) = $self->_get_writer_io(\%input)
1877 $writers{$type}{single}->($self, $IO, %input, type => $type)
1881 if (!$formats_low{$type}) {
1882 my $write_types = join ', ', sort Imager->write_types();
1883 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1887 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1890 if ( $type eq 'pnm' ) {
1891 $self->_set_opts(\%input, "pnm_", $self)
1893 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1894 $self->{ERRSTR} = $self->_error_as_msg();
1897 $self->{DEBUG} && print "writing a pnm file\n";
1899 elsif ( $type eq 'raw' ) {
1900 $self->_set_opts(\%input, "raw_", $self)
1902 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1903 $self->{ERRSTR} = $self->_error_as_msg();
1906 $self->{DEBUG} && print "writing a raw file\n";
1908 elsif ( $type eq 'bmp' ) {
1909 $self->_set_opts(\%input, "bmp_", $self)
1911 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1912 $self->{ERRSTR} = $self->_error_as_msg;
1915 $self->{DEBUG} && print "writing a bmp file\n";
1917 elsif ( $type eq 'tga' ) {
1918 $self->_set_opts(\%input, "tga_", $self)
1921 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1922 $self->{ERRSTR}=$self->_error_as_msg();
1925 $self->{DEBUG} && print "writing a tga file\n";
1929 if (exists $input{'data'}) {
1930 my $data = io_slurp($IO);
1932 $self->{ERRSTR}='Could not slurp from buffer';
1935 ${$input{data}} = $data;
1941 my ($class, $opts, @images) = @_;
1943 my $type = $opts->{type};
1945 if (!$type && $opts->{'file'}) {
1946 $type = $FORMATGUESS->($opts->{'file'});
1949 $class->_set_error('type parameter missing and not possible to guess from extension');
1952 # translate to ImgRaw
1954 for my $img (@images) {
1955 unless (ref $img && Scalar::Util::blessed($img) && $img->isa("Imager")) {
1956 $class->_set_error("write_multi: image $index is not an Imager image object");
1959 unless ($img->_valid_image("write_multi")) {
1960 $class->_set_error($img->errstr . " (image $index)");
1965 $class->_set_opts($opts, "i_", @images)
1967 my @work = map $_->{IMG}, @images;
1969 _writer_autoload($type);
1972 if ($writers{$type} && $writers{$type}{multiple}) {
1973 ($IO, $file) = $class->_get_writer_io($opts, $type)
1976 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1980 if (!$formats{$type}) {
1981 my $write_types = join ', ', sort Imager->write_types();
1982 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1986 ($IO, $file) = $class->_get_writer_io($opts, $type)
1989 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1993 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1998 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
2004 if (exists $opts->{'data'}) {
2005 my $data = io_slurp($IO);
2007 Imager->_set_error('Could not slurp from buffer');
2010 ${$opts->{data}} = $data;
2015 # read multiple images from a file
2017 my ($class, %opts) = @_;
2019 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2022 my $type = $opts{'type'};
2024 $type = i_test_format_probe($IO, -1);
2027 if ($opts{file} && !$type) {
2029 $type = $FORMATGUESS->($opts{file});
2033 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2034 $opts{file} and $msg .= " or file name";
2035 Imager->_set_error($msg);
2039 _reader_autoload($type);
2041 if ($readers{$type} && $readers{$type}{multiple}) {
2042 return $readers{$type}{multiple}->($IO, %opts);
2045 unless ($formats{$type}) {
2046 my $read_types = join ', ', sort Imager->read_types();
2047 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2052 if ($type eq 'pnm') {
2053 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2056 my $img = Imager->new;
2057 if ($img->read(%opts, io => $IO, type => $type)) {
2060 Imager->_set_error($img->errstr);
2065 $ERRSTR = _error_as_msg();
2069 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2073 # Destroy an Imager object
2077 # delete $instances{$self};
2078 if (defined($self->{IMG})) {
2079 # the following is now handled by the XS DESTROY method for
2080 # Imager::ImgRaw object
2081 # Re-enabling this will break virtual images
2082 # tested for in t/t020masked.t
2083 # i_img_destroy($self->{IMG});
2084 undef($self->{IMG});
2086 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2090 # Perform an inplace filter of an image
2091 # that is the image will be overwritten with the data
2098 $self->_valid_image("filter")
2101 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2103 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2104 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2107 if ($filters{$input{'type'}}{names}) {
2108 my $names = $filters{$input{'type'}}{names};
2109 for my $name (keys %$names) {
2110 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2111 $input{$name} = $names->{$name}{$input{$name}};
2115 if (defined($filters{$input{'type'}}{defaults})) {
2116 %hsh=( image => $self->{IMG},
2118 %{$filters{$input{'type'}}{defaults}},
2121 %hsh=( image => $self->{IMG},
2126 my @cs=@{$filters{$input{'type'}}{callseq}};
2129 if (!defined($hsh{$_})) {
2130 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2135 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2136 &{$filters{$input{'type'}}{callsub}}(%hsh);
2139 chomp($self->{ERRSTR} = $@);
2145 $self->{DEBUG} && print "callseq is: @cs\n";
2146 $self->{DEBUG} && print "matching callseq is: @b\n";
2151 sub register_filter {
2153 my %hsh = ( defaults => {}, @_ );
2156 or die "register_filter() with no type\n";
2157 defined $hsh{callsub}
2158 or die "register_filter() with no callsub\n";
2159 defined $hsh{callseq}
2160 or die "register_filter() with no callseq\n";
2162 exists $filters{$hsh{type}}
2165 $filters{$hsh{type}} = \%hsh;
2170 sub scale_calculate {
2173 my %opts = ('type'=>'max', @_);
2175 # none of these should be references
2176 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2177 if (defined $opts{$name} && ref $opts{$name}) {
2178 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2183 my ($x_scale, $y_scale);
2184 my $width = $opts{width};
2185 my $height = $opts{height};
2187 defined $width or $width = $self->getwidth;
2188 defined $height or $height = $self->getheight;
2191 unless (defined $width && defined $height) {
2192 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2197 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2198 $x_scale = $opts{'xscalefactor'};
2199 $y_scale = $opts{'yscalefactor'};
2201 elsif ($opts{'xscalefactor'}) {
2202 $x_scale = $opts{'xscalefactor'};
2203 $y_scale = $opts{'scalefactor'} || $x_scale;
2205 elsif ($opts{'yscalefactor'}) {
2206 $y_scale = $opts{'yscalefactor'};
2207 $x_scale = $opts{'scalefactor'} || $y_scale;
2210 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2213 # work out the scaling
2214 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2215 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2216 $opts{ypixels} / $height );
2217 if ($opts{'type'} eq 'min') {
2218 $x_scale = $y_scale = _min($xpix,$ypix);
2220 elsif ($opts{'type'} eq 'max') {
2221 $x_scale = $y_scale = _max($xpix,$ypix);
2223 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2228 $self->_set_error('invalid value for type parameter');
2231 } elsif ($opts{xpixels}) {
2232 $x_scale = $y_scale = $opts{xpixels} / $width;
2234 elsif ($opts{ypixels}) {
2235 $x_scale = $y_scale = $opts{ypixels}/$height;
2237 elsif ($opts{constrain} && ref $opts{constrain}
2238 && $opts{constrain}->can('constrain')) {
2239 # we've been passed an Image::Math::Constrain object or something
2240 # that looks like one
2242 (undef, undef, $scalefactor)
2243 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2244 unless ($scalefactor) {
2245 $self->_set_error('constrain method failed on constrain parameter');
2248 $x_scale = $y_scale = $scalefactor;
2251 my $new_width = int($x_scale * $width + 0.5);
2252 $new_width > 0 or $new_width = 1;
2253 my $new_height = int($y_scale * $height + 0.5);
2254 $new_height > 0 or $new_height = 1;
2256 return ($x_scale, $y_scale, $new_width, $new_height);
2260 # Scale an image to requested size and return the scaled version
2264 my %opts = (qtype=>'normal' ,@_);
2265 my $img = Imager->new();
2266 my $tmp = Imager->new();
2268 unless (defined wantarray) {
2269 my @caller = caller;
2270 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2274 $self->_valid_image("scale")
2277 my ($x_scale, $y_scale, $new_width, $new_height) =
2278 $self->scale_calculate(%opts)
2281 if ($opts{qtype} eq 'normal') {
2282 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2283 if ( !defined($tmp->{IMG}) ) {
2284 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2287 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2288 if ( !defined($img->{IMG}) ) {
2289 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2295 elsif ($opts{'qtype'} eq 'preview') {
2296 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2297 if ( !defined($img->{IMG}) ) {
2298 $self->{ERRSTR}='unable to scale image';
2303 elsif ($opts{'qtype'} eq 'mixing') {
2304 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2305 unless ($img->{IMG}) {
2306 $self->_set_error(Imager->_error_as_msg);
2312 $self->_set_error('invalid value for qtype parameter');
2317 # Scales only along the X axis
2321 my %opts = ( scalefactor=>0.5, @_ );
2323 unless (defined wantarray) {
2324 my @caller = caller;
2325 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2329 $self->_valid_image("scaleX")
2332 my $img = Imager->new();
2334 my $scalefactor = $opts{scalefactor};
2336 if ($opts{pixels}) {
2337 $scalefactor = $opts{pixels} / $self->getwidth();
2340 unless ($self->{IMG}) {
2341 $self->{ERRSTR}='empty input image';
2345 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2347 if ( !defined($img->{IMG}) ) {
2348 $self->{ERRSTR} = 'unable to scale image';
2355 # Scales only along the Y axis
2359 my %opts = ( scalefactor => 0.5, @_ );
2361 unless (defined wantarray) {
2362 my @caller = caller;
2363 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2367 $self->_valid_image("scaleY")
2370 my $img = Imager->new();
2372 my $scalefactor = $opts{scalefactor};
2374 if ($opts{pixels}) {
2375 $scalefactor = $opts{pixels} / $self->getheight();
2378 unless ($self->{IMG}) {
2379 $self->{ERRSTR} = 'empty input image';
2382 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2384 if ( !defined($img->{IMG}) ) {
2385 $self->{ERRSTR} = 'unable to scale image';
2392 # Transform returns a spatial transformation of the input image
2393 # this moves pixels to a new location in the returned image.
2394 # NOTE - should make a utility function to check transforms for
2400 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2402 # print Dumper(\%opts);
2405 $self->_valid_image("transform")
2408 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2412 pop @INC if $INC[-1] eq '.';
2413 eval ("use Affix::Infix2Postfix;");
2417 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2420 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2421 {op=>'-',trans=>'Sub'},
2422 {op=>'*',trans=>'Mult'},
2423 {op=>'/',trans=>'Div'},
2424 {op=>'-','type'=>'unary',trans=>'u-'},
2426 {op=>'func','type'=>'unary'}],
2427 'grouping'=>[qw( \( \) )],
2428 'func'=>[qw( sin cos )],
2433 @xt=$I2P->translate($opts{'xexpr'});
2434 @yt=$I2P->translate($opts{'yexpr'});
2436 $numre=$I2P->{'numre'};
2439 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2440 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2441 @{$opts{'parm'}}=@pt;
2444 # print Dumper(\%opts);
2446 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2447 $self->{ERRSTR}='transform: no xopcodes given.';
2451 @op=@{$opts{'xopcodes'}};
2453 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2454 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2457 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2463 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2464 $self->{ERRSTR}='transform: no yopcodes given.';
2468 @op=@{$opts{'yopcodes'}};
2470 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2471 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2474 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2479 if ( !exists $opts{'parm'}) {
2480 $self->{ERRSTR}='transform: no parameter arg given.';
2484 # print Dumper(\@ropx);
2485 # print Dumper(\@ropy);
2486 # print Dumper(\@ropy);
2488 my $img = Imager->new();
2489 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2490 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2496 my ($opts, @imgs) = @_;
2498 require "Imager/Expr.pm";
2500 $opts->{variables} = [ qw(x y) ];
2501 my ($width, $height) = @{$opts}{qw(width height)};
2504 for my $img (@imgs) {
2505 unless ($img->_valid_image("transform2")) {
2506 Imager->_set_error($img->errstr . " (input image $index)");
2512 $width ||= $imgs[0]->getwidth();
2513 $height ||= $imgs[0]->getheight();
2515 for my $img (@imgs) {
2516 $opts->{constants}{"w$img_num"} = $img->getwidth();
2517 $opts->{constants}{"h$img_num"} = $img->getheight();
2518 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2519 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2524 $opts->{constants}{w} = $width;
2525 $opts->{constants}{cx} = $width/2;
2528 $Imager::ERRSTR = "No width supplied";
2532 $opts->{constants}{h} = $height;
2533 $opts->{constants}{cy} = $height/2;
2536 $Imager::ERRSTR = "No height supplied";
2539 my $code = Imager::Expr->new($opts);
2541 $Imager::ERRSTR = Imager::Expr::error();
2544 my $channels = $opts->{channels} || 3;
2545 unless ($channels >= 1 && $channels <= 4) {
2546 return Imager->_set_error("channels must be an integer between 1 and 4");
2549 my $img = Imager->new();
2550 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2551 $channels, $code->code(),
2552 $code->nregs(), $code->cregs(),
2553 [ map { $_->{IMG} } @imgs ]);
2554 if (!defined $img->{IMG}) {
2555 $Imager::ERRSTR = Imager->_error_as_msg();
2566 $self->_valid_image("rubthrough")
2569 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2570 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2574 %opts = (src_minx => 0,
2576 src_maxx => $opts{src}->getwidth(),
2577 src_maxy => $opts{src}->getheight(),
2581 defined $tx or $tx = $opts{left};
2582 defined $tx or $tx = 0;
2585 defined $ty or $ty = $opts{top};
2586 defined $ty or $ty = 0;
2588 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2589 $opts{src_minx}, $opts{src_miny},
2590 $opts{src_maxx}, $opts{src_maxy})) {
2591 $self->_set_error($self->_error_as_msg());
2608 $self->_valid_image("compose")
2611 unless ($opts{src}) {
2612 $self->_set_error("compose: src parameter missing");
2616 unless ($opts{src}->_valid_image("compose")) {
2617 $self->_set_error($opts{src}->errstr . " (for src)");
2620 my $src = $opts{src};
2622 my $left = $opts{left};
2623 defined $left or $left = $opts{tx};
2624 defined $left or $left = 0;
2626 my $top = $opts{top};
2627 defined $top or $top = $opts{ty};
2628 defined $top or $top = 0;
2630 my $src_left = $opts{src_left};
2631 defined $src_left or $src_left = $opts{src_minx};
2632 defined $src_left or $src_left = 0;
2634 my $src_top = $opts{src_top};
2635 defined $src_top or $src_top = $opts{src_miny};
2636 defined $src_top or $src_top = 0;
2638 my $width = $opts{width};
2639 if (!defined $width && defined $opts{src_maxx}) {
2640 $width = $opts{src_maxx} - $src_left;
2642 defined $width or $width = $src->getwidth() - $src_left;
2644 my $height = $opts{height};
2645 if (!defined $height && defined $opts{src_maxy}) {
2646 $height = $opts{src_maxy} - $src_top;
2648 defined $height or $height = $src->getheight() - $src_top;
2650 my $combine = $self->_combine($opts{combine}, 'normal');
2653 unless ($opts{mask}->_valid_image("compose")) {
2654 $self->_set_error($opts{mask}->errstr . " (for mask)");
2658 my $mask_left = $opts{mask_left};
2659 defined $mask_left or $mask_left = $opts{mask_minx};
2660 defined $mask_left or $mask_left = 0;
2662 my $mask_top = $opts{mask_top};
2663 defined $mask_top or $mask_top = $opts{mask_miny};
2664 defined $mask_top or $mask_top = 0;
2666 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2667 $left, $top, $src_left, $src_top,
2668 $mask_left, $mask_top, $width, $height,
2669 $combine, $opts{opacity})) {
2670 $self->_set_error(Imager->_error_as_msg);
2675 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2676 $width, $height, $combine, $opts{opacity})) {
2677 $self->_set_error(Imager->_error_as_msg);
2689 $self->_valid_image("flip")
2692 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2694 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2695 $dir = $xlate{$opts{'dir'}};
2696 return $self if i_flipxy($self->{IMG}, $dir);
2704 unless (defined wantarray) {
2705 my @caller = caller;
2706 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2710 $self->_valid_image("rotate")
2713 if (defined $opts{right}) {
2714 my $degrees = $opts{right};
2716 $degrees += 360 * int(((-$degrees)+360)/360);
2718 $degrees = $degrees % 360;
2719 if ($degrees == 0) {
2720 return $self->copy();
2722 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2723 my $result = Imager->new();
2724 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2728 $self->{ERRSTR} = $self->_error_as_msg();
2733 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2737 elsif (defined $opts{radians} || defined $opts{degrees}) {
2738 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2740 my $back = $opts{back};
2741 my $result = Imager->new;
2743 $back = _color($back);
2745 $self->_set_error(Imager->errstr);
2749 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2752 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2754 if ($result->{IMG}) {
2758 $self->{ERRSTR} = $self->_error_as_msg();
2763 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2768 sub matrix_transform {
2772 $self->_valid_image("matrix_transform")
2775 unless (defined wantarray) {
2776 my @caller = caller;
2777 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2781 if ($opts{matrix}) {
2782 my $xsize = $opts{xsize} || $self->getwidth;
2783 my $ysize = $opts{ysize} || $self->getheight;
2785 my $result = Imager->new;
2787 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2788 $opts{matrix}, $opts{back})
2792 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2800 $self->{ERRSTR} = "matrix parameter required";
2806 *yatf = \&matrix_transform;
2808 # These two are supported for legacy code only
2811 return Imager::Color->new(@_);
2815 return Imager::Color::set(@_);
2818 # Draws a box between the specified corner points.
2821 my $raw = $self->{IMG};
2823 $self->_valid_image("box")
2828 my ($xmin, $ymin, $xmax, $ymax);
2829 if (exists $opts{'box'}) {
2830 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2831 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2832 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2833 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2836 defined($xmin = $opts{xmin}) or $xmin = 0;
2837 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2838 defined($ymin = $opts{ymin}) or $ymin = 0;
2839 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2842 if ($opts{filled}) {
2843 my $color = $opts{'color'};
2845 if (defined $color) {
2846 unless (_is_color_object($color)) {
2847 $color = _color($color);
2849 $self->{ERRSTR} = $Imager::ERRSTR;
2855 $color = i_color_new(255,255,255,255);
2858 if ($color->isa("Imager::Color")) {
2859 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2862 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2865 elsif ($opts{fill}) {
2866 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2867 # assume it's a hash ref
2868 require 'Imager/Fill.pm';
2869 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2870 $self->{ERRSTR} = $Imager::ERRSTR;
2874 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2877 my $color = $opts{'color'};
2878 if (defined $color) {
2879 unless (_is_color_object($color)) {
2880 $color = _color($color);
2882 $self->{ERRSTR} = $Imager::ERRSTR;
2888 $color = i_color_new(255, 255, 255, 255);
2891 $self->{ERRSTR} = $Imager::ERRSTR;
2894 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2903 $self->_valid_image("arc")
2906 my $dflcl= [ 255, 255, 255, 255];
2911 'r'=>_min($self->getwidth(),$self->getheight())/3,
2912 'x'=>$self->getwidth()/2,
2913 'y'=>$self->getheight()/2,
2920 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2921 # assume it's a hash ref
2922 require 'Imager/Fill.pm';
2923 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2924 $self->{ERRSTR} = $Imager::ERRSTR;
2928 if ($opts{d1} == 0 && $opts{d2} == 361) {
2929 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2933 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2934 $opts{'d2'}, $opts{fill}{fill});
2937 elsif ($opts{filled}) {
2938 my $color = _color($opts{'color'});
2940 $self->{ERRSTR} = $Imager::ERRSTR;
2943 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2944 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2948 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2949 $opts{'d1'}, $opts{'d2'}, $color);
2953 my $color = _color($opts{'color'});
2954 if ($opts{d2} - $opts{d1} >= 360) {
2955 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2958 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2964 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2965 # assume it's a hash ref
2966 require 'Imager/Fill.pm';
2967 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2968 $self->{ERRSTR} = $Imager::ERRSTR;
2972 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2973 $opts{'d2'}, $opts{fill}{fill});
2976 my $color = _color($opts{'color'});
2978 $self->{ERRSTR} = $Imager::ERRSTR;
2981 if ($opts{filled}) {
2982 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2983 $opts{'d1'}, $opts{'d2'}, $color);
2986 if ($opts{d1} == 0 && $opts{d2} == 361) {
2987 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2990 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2996 $self->_set_error($self->_error_as_msg);
3003 # Draws a line from one point to the other
3004 # the endpoint is set if the endp parameter is set which it is by default.
3005 # to turn of the endpoint being set use endp=>0 when calling line.
3009 my $dflcl=i_color_new(0,0,0,0);
3010 my %opts=(color=>$dflcl,
3014 $self->_valid_image("line")
3017 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
3018 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
3020 my $color = _color($opts{'color'});
3022 $self->{ERRSTR} = $Imager::ERRSTR;
3026 $opts{antialias} = $opts{aa} if defined $opts{aa};
3027 if ($opts{antialias}) {
3028 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3029 $color, $opts{endp});
3031 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3032 $color, $opts{endp});
3037 # Draws a line between an ordered set of points - It more or less just transforms this
3038 # into a list of lines.
3042 my ($pt,$ls,@points);
3043 my $dflcl=i_color_new(0,0,0,0);
3044 my %opts=(color=>$dflcl,@_);
3046 $self->_valid_image("polyline")
3049 if (exists($opts{points})) { @points=@{$opts{points}}; }
3050 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3051 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3054 # print Dumper(\@points);
3056 my $color = _color($opts{'color'});
3058 $self->{ERRSTR} = $Imager::ERRSTR;
3061 $opts{antialias} = $opts{aa} if defined $opts{aa};
3062 if ($opts{antialias}) {
3065 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3072 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3082 my ($pt,$ls,@points);
3083 my $dflcl = i_color_new(0,0,0,0);
3084 my %opts = (color=>$dflcl, @_);
3086 $self->_valid_image("polygon")
3089 if (exists($opts{points})) {
3090 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3091 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3094 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3095 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3098 my $mode = _first($opts{mode}, 0);
3100 if ($opts{'fill'}) {
3101 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3102 # assume it's a hash ref
3103 require 'Imager/Fill.pm';
3104 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3105 $self->{ERRSTR} = $Imager::ERRSTR;
3109 unless (i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3110 $mode, $opts{'fill'}{'fill'})) {
3111 return $self->_set_error($self->_error_as_msg);
3115 my $color = _color($opts{'color'});
3117 $self->{ERRSTR} = $Imager::ERRSTR;
3120 unless (i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color)) {
3121 return $self->_set_error($self->_error_as_msg);
3129 my ($self, %opts) = @_;
3131 $self->_valid_image("polypolygon")
3134 my $points = $opts{points};
3136 or return $self->_set_error("polypolygon: missing required points");
3138 my $mode = _first($opts{mode}, "evenodd");
3140 if ($opts{filled}) {
3141 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3142 or return $self->_set_error($Imager::ERRSTR);
3144 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3145 or return $self->_set_error($self->_error_as_msg);
3147 elsif ($opts{fill}) {
3148 my $fill = $opts{fill};
3149 $self->_valid_fill($fill, "polypolygon")
3152 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3153 or return $self->_set_error($self->_error_as_msg);
3156 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3157 or return $self->_set_error($Imager::ERRSTR);
3159 my $rimg = $self->{IMG};
3161 if (_first($opts{aa}, 1)) {
3162 for my $poly (@$points) {
3163 my $xp = $poly->[0];
3164 my $yp = $poly->[1];
3165 for my $i (0 .. $#$xp - 1) {
3166 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3169 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3174 for my $poly (@$points) {
3175 my $xp = $poly->[0];
3176 my $yp = $poly->[1];
3177 for my $i (0 .. $#$xp - 1) {
3178 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3181 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3190 # this the multipoint bezier curve
3191 # this is here more for testing that actual usage since
3192 # this is not a good algorithm. Usually the curve would be
3193 # broken into smaller segments and each done individually.
3197 my ($pt,$ls,@points);
3198 my $dflcl=i_color_new(0,0,0,0);
3199 my %opts=(color=>$dflcl,@_);
3201 $self->_valid_image("polybezier")
3204 if (exists $opts{points}) {
3205 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3206 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3209 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3210 $self->{ERRSTR}='Missing or invalid points.';
3214 my $color = _color($opts{'color'});
3216 $self->{ERRSTR} = $Imager::ERRSTR;
3219 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3225 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3228 $self->_valid_image("flood_fill")
3231 unless (exists $opts{'x'} && exists $opts{'y'}) {
3232 $self->{ERRSTR} = "missing seed x and y parameters";
3236 if ($opts{border}) {
3237 my $border = _color($opts{border});
3239 $self->_set_error($Imager::ERRSTR);
3243 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3244 # assume it's a hash ref
3245 require Imager::Fill;
3246 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3247 $self->{ERRSTR} = $Imager::ERRSTR;
3251 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3252 $opts{fill}{fill}, $border);
3255 my $color = _color($opts{'color'});
3257 $self->{ERRSTR} = $Imager::ERRSTR;
3260 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3267 $self->{ERRSTR} = $self->_error_as_msg();
3273 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3274 # assume it's a hash ref
3275 require 'Imager/Fill.pm';
3276 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3277 $self->{ERRSTR} = $Imager::ERRSTR;
3281 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3284 my $color = _color($opts{'color'});
3286 $self->{ERRSTR} = $Imager::ERRSTR;
3289 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3295 $self->{ERRSTR} = $self->_error_as_msg();
3302 my ($self, %opts) = @_;
3304 $self->_valid_image("setpixel")
3307 my $color = $opts{color};
3308 unless (defined $color) {
3309 $color = $self->{fg};
3310 defined $color or $color = NC(255, 255, 255);
3313 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3314 unless ($color = _color($color, 'setpixel')) {
3315 $self->_set_error("setpixel: " . Imager->errstr);
3320 unless (exists $opts{'x'} && exists $opts{'y'}) {
3321 $self->_set_error('setpixel: missing x or y parameter');
3327 if (ref $x || ref $y) {
3328 $x = ref $x ? $x : [ $x ];
3329 $y = ref $y ? $y : [ $y ];
3331 $self->_set_error("setpixel: x is a reference to an empty array");
3335 $self->_set_error("setpixel: y is a reference to an empty array");
3339 # make both the same length, replicating the last element
3341 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3344 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3348 if ($color->isa('Imager::Color')) {
3349 for my $i (0..$#$x) {
3350 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3355 for my $i (0..$#$x) {
3356 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3364 if ($color->isa('Imager::Color')) {
3365 i_ppix($self->{IMG}, $x, $y, $color)
3366 and return "0 but true";
3369 i_ppixf($self->{IMG}, $x, $y, $color)
3370 and return "0 but true";
3380 my %opts = ( "type"=>'8bit', @_);
3382 $self->_valid_image("getpixel")
3385 unless (exists $opts{'x'} && exists $opts{'y'}) {
3386 $self->_set_error('getpixel: missing x or y parameter');
3392 my $type = $opts{'type'};
3393 if (ref $x || ref $y) {
3394 $x = ref $x ? $x : [ $x ];
3395 $y = ref $y ? $y : [ $y ];
3397 $self->_set_error("getpixel: x is a reference to an empty array");
3401 $self->_set_error("getpixel: y is a reference to an empty array");
3405 # make both the same length, replicating the last element
3407 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3410 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3414 if ($type eq '8bit') {
3415 for my $i (0..$#$x) {
3416 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3419 elsif ($type eq 'float' || $type eq 'double') {
3420 for my $i (0..$#$x) {
3421 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3425 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3428 return wantarray ? @result : \@result;
3431 if ($type eq '8bit') {
3432 return i_get_pixel($self->{IMG}, $x, $y);
3434 elsif ($type eq 'float' || $type eq 'double') {
3435 return i_gpixf($self->{IMG}, $x, $y);
3438 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3446 my %opts = ( type => '8bit', x=>0, @_);
3448 $self->_valid_image("getscanline")
3451 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3453 unless (defined $opts{'y'}) {
3454 $self->_set_error("missing y parameter");
3458 if ($opts{type} eq '8bit') {
3459 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3462 elsif ($opts{type} eq 'float') {
3463 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3466 elsif ($opts{type} eq 'index') {
3467 unless (i_img_type($self->{IMG})) {
3468 $self->_set_error("type => index only valid on paletted images");
3471 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3475 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3482 my %opts = ( x=>0, @_);
3484 $self->_valid_image("setscanline")
3487 unless (defined $opts{'y'}) {
3488 $self->_set_error("missing y parameter");
3493 if (ref $opts{pixels} && @{$opts{pixels}}) {
3494 # try to guess the type
3495 if ($opts{pixels}[0]->isa('Imager::Color')) {
3496 $opts{type} = '8bit';
3498 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3499 $opts{type} = 'float';
3502 $self->_set_error("missing type parameter and could not guess from pixels");
3508 $opts{type} = '8bit';
3512 if ($opts{type} eq '8bit') {
3513 if (ref $opts{pixels}) {
3514 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3517 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3520 elsif ($opts{type} eq 'float') {
3521 if (ref $opts{pixels}) {
3522 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3525 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3528 elsif ($opts{type} eq 'index') {
3529 if (ref $opts{pixels}) {
3530 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3533 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3537 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3544 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3546 $self->_valid_image("getsamples")
3549 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3551 unless (defined $opts{'y'}) {
3552 $self->_set_error("missing y parameter");
3556 if ($opts{target}) {
3557 my $target = $opts{target};
3558 my $offset = $opts{offset};
3559 if ($opts{type} eq '8bit') {
3560 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3561 $opts{y}, $opts{channels})
3563 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3564 return scalar(@samples);
3566 elsif ($opts{type} eq 'float') {
3567 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3568 $opts{y}, $opts{channels});
3569 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3570 return scalar(@samples);
3572 elsif ($opts{type} =~ /^(\d+)bit$/) {
3576 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3577 $opts{y}, $bits, $target,
3578 $offset, $opts{channels});
3579 unless (defined $count) {
3580 $self->_set_error(Imager->_error_as_msg);
3587 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3592 if ($opts{type} eq '8bit') {
3593 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3594 $opts{y}, $opts{channels});
3596 elsif ($opts{type} eq 'float') {
3597 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3598 $opts{y}, $opts{channels});
3600 elsif ($opts{type} =~ /^(\d+)bit$/) {
3604 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3605 $opts{y}, $bits, \@data, 0, $opts{channels})
3610 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3619 $self->_valid_image("setsamples")
3622 my %opts = ( x => 0, offset => 0 );
3624 # avoid duplicating the data parameter, it may be a large scalar
3626 while ($i < @_ -1) {
3627 if ($_[$i] eq 'data') {
3631 $opts{$_[$i]} = $_[$i+1];
3637 unless(defined $data_index) {
3638 $self->_set_error('setsamples: data parameter missing');
3641 unless (defined $_[$data_index]) {
3642 $self->_set_error('setsamples: data parameter not defined');
3646 my $type = $opts{type};
3647 defined $type or $type = '8bit';
3649 my $width = defined $opts{width} ? $opts{width}
3650 : $self->getwidth() - $opts{x};
3653 if ($type eq '8bit') {
3654 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3655 $_[$data_index], $opts{offset}, $width);
3657 elsif ($type eq 'float') {
3658 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3659 $_[$data_index], $opts{offset}, $width);
3661 elsif ($type =~ /^([0-9]+)bit$/) {
3664 unless (ref $_[$data_index]) {
3665 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3669 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3670 $opts{channels}, $_[$data_index], $opts{offset},
3674 $self->_set_error('setsamples: type parameter invalid');
3678 unless (defined $count) {
3679 $self->_set_error(Imager->_error_as_msg);
3686 # make an identity matrix of the given size
3690 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3691 for my $c (0 .. ($size-1)) {
3692 $matrix->[$c][$c] = 1;
3697 # general function to convert an image
3699 my ($self, %opts) = @_;
3702 $self->_valid_image("convert")
3705 unless (defined wantarray) {
3706 my @caller = caller;
3707 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3711 # the user can either specify a matrix or preset
3712 # the matrix overrides the preset
3713 if (!exists($opts{matrix})) {
3714 unless (exists($opts{preset})) {
3715 $self->{ERRSTR} = "convert() needs a matrix or preset";
3719 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3720 # convert to greyscale, keeping the alpha channel if any
3721 if ($self->getchannels == 3) {
3722 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3724 elsif ($self->getchannels == 4) {
3725 # preserve the alpha channel
3726 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3731 $matrix = _identity($self->getchannels);
3734 elsif ($opts{preset} eq 'noalpha') {
3735 # strip the alpha channel
3736 if ($self->getchannels == 2 or $self->getchannels == 4) {
3737 $matrix = _identity($self->getchannels);
3738 pop(@$matrix); # lose the alpha entry
3741 $matrix = _identity($self->getchannels);
3744 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3746 $matrix = [ [ 1 ] ];
3748 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3749 $matrix = [ [ 0, 1 ] ];
3751 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3752 $matrix = [ [ 0, 0, 1 ] ];
3754 elsif ($opts{preset} eq 'alpha') {
3755 if ($self->getchannels == 2 or $self->getchannels == 4) {
3756 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3759 # the alpha is just 1 <shrug>
3760 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3763 elsif ($opts{preset} eq 'rgb') {
3764 if ($self->getchannels == 1) {
3765 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3767 elsif ($self->getchannels == 2) {
3768 # preserve the alpha channel
3769 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3772 $matrix = _identity($self->getchannels);
3775 elsif ($opts{preset} eq 'addalpha') {
3776 if ($self->getchannels == 1) {
3777 $matrix = _identity(2);
3779 elsif ($self->getchannels == 3) {
3780 $matrix = _identity(4);
3783 $matrix = _identity($self->getchannels);
3787 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3793 $matrix = $opts{matrix};
3796 my $new = Imager->new;
3797 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3798 unless ($new->{IMG}) {
3799 # most likely a bad matrix
3800 i_push_error(0, "convert");
3801 $self->{ERRSTR} = _error_as_msg();
3807 # combine channels from multiple input images, a class method
3809 my ($class, %opts) = @_;
3811 my $src = delete $opts{src};
3813 $class->_set_error("src parameter missing");
3818 for my $img (@$src) {
3819 unless (eval { $img->isa("Imager") }) {
3820 $class->_set_error("src must contain image objects");
3823 unless ($img->_valid_image("combine")) {
3824 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3827 push @imgs, $img->{IMG};
3830 if (my $channels = delete $opts{channels}) {
3831 $result = i_combine(\@imgs, $channels);
3834 $result = i_combine(\@imgs);
3837 $class->_set_error($class->_error_as_msg);
3841 my $img = $class->new;
3842 $img->{IMG} = $result;
3848 # general function to map an image through lookup tables
3851 my ($self, %opts) = @_;
3852 my @chlist = qw( red green blue alpha );
3854 $self->_valid_image("map")
3857 if (!exists($opts{'maps'})) {
3858 # make maps from channel maps
3860 for $chnum (0..$#chlist) {
3861 if (exists $opts{$chlist[$chnum]}) {
3862 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3863 } elsif (exists $opts{'all'}) {
3864 $opts{'maps'}[$chnum] = $opts{'all'};
3868 if ($opts{'maps'} and $self->{IMG}) {
3869 i_map($self->{IMG}, $opts{'maps'} );
3875 my ($self, %opts) = @_;
3877 $self->_valid_image("difference")
3880 defined $opts{mindist} or $opts{mindist} = 0;
3882 defined $opts{other}
3883 or return $self->_set_error("No 'other' parameter supplied");
3884 unless ($opts{other}->_valid_image("difference")) {
3885 $self->_set_error($opts{other}->errstr . " (other image)");
3889 my $result = Imager->new;
3890 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3892 or return $self->_set_error($self->_error_as_msg());
3897 # destructive border - image is shrunk by one pixel all around
3900 my ($self,%opts)=@_;
3901 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3902 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3906 # Get the width of an image
3911 $self->_valid_image("getwidth")
3914 return i_img_get_width($self->{IMG});
3917 # Get the height of an image
3922 $self->_valid_image("getheight")
3925 return i_img_get_height($self->{IMG});
3928 # Get number of channels in an image
3933 $self->_valid_image("getchannels")
3936 return i_img_getchannels($self->{IMG});
3939 my @model_names = qw(unknown gray graya rgb rgba);
3942 my ($self, %opts) = @_;
3944 $self->_valid_image("colormodel")
3947 my $model = i_img_color_model($self->{IMG});
3949 return $opts{numeric} ? $model : $model_names[$model];
3955 $self->_valid_image("colorchannels")
3958 return i_img_color_channels($self->{IMG});
3964 $self->_valid_image("alphachannel")
3967 return scalar(i_img_alpha_channel($self->{IMG}));
3975 $self->_valid_image("getmask")
3978 return i_img_getmask($self->{IMG});
3987 $self->_valid_image("setmask")
3990 unless (defined $opts{mask}) {
3991 $self->_set_error("mask parameter required");
3995 i_img_setmask( $self->{IMG} , $opts{mask} );
4000 # Get number of colors in an image
4004 my %opts=('maxcolors'=>2**30,@_);
4006 $self->_valid_image("getcolorcount")
4009 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
4010 return ($rc==-1? undef : $rc);
4013 # Returns a reference to a hash. The keys are colour named (packed) and the
4014 # values are the number of pixels in this colour.
4015 sub getcolorusagehash {
4018 $self->_valid_image("getcolorusagehash")
4021 my %opts = ( maxcolors => 2**30, @_ );
4022 my $max_colors = $opts{maxcolors};
4023 unless (defined $max_colors && $max_colors > 0) {
4024 $self->_set_error('maxcolors must be a positive integer');
4028 my $channels= $self->getchannels;
4029 # We don't want to look at the alpha channel, because some gifs using it
4030 # doesn't define it for every colour (but only for some)
4031 $channels -= 1 if $channels == 2 or $channels == 4;
4033 my $height = $self->getheight;
4034 for my $y (0 .. $height - 1) {
4035 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4036 while (length $colors) {
4037 $color_use{ substr($colors, 0, $channels, '') }++;
4039 keys %color_use > $max_colors
4045 # This will return a ordered array of the colour usage. Kind of the sorted
4046 # version of the values of the hash returned by getcolorusagehash.
4047 # You might want to add safety checks and change the names, etc...
4051 $self->_valid_image("getcolorusage")
4054 my %opts = ( maxcolors => 2**30, @_ );
4055 my $max_colors = $opts{maxcolors};
4056 unless (defined $max_colors && $max_colors > 0) {
4057 $self->_set_error('maxcolors must be a positive integer');
4061 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4064 # draw string to an image
4069 $self->_valid_image("string")
4072 my %input=('x'=>0, 'y'=>0, @_);
4073 defined($input{string}) or $input{string} = $input{text};
4075 unless(defined $input{string}) {
4076 $self->{ERRSTR}="missing required parameter 'string'";
4080 unless($input{font}) {
4081 $self->{ERRSTR}="missing required parameter 'font'";
4085 unless ($input{font}->draw(image=>$self, %input)) {
4097 $self->_valid_image("align_string")
4106 my %input=('x'=>0, 'y'=>0, @_);
4107 defined $input{string}
4108 or $input{string} = $input{text};
4110 unless(exists $input{string}) {
4111 $self->_set_error("missing required parameter 'string'");
4115 unless($input{font}) {
4116 $self->_set_error("missing required parameter 'font'");
4121 unless (@result = $input{font}->align(image=>$img, %input)) {
4125 return wantarray ? @result : $result[0];
4128 my @file_limit_names = qw/width height bytes/;
4130 sub set_file_limits {
4137 @values{@file_limit_names} = (0) x @file_limit_names;
4140 @values{@file_limit_names} = i_get_image_file_limits();
4143 for my $key (keys %values) {
4144 defined $opts{$key} and $values{$key} = $opts{$key};
4147 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4150 sub get_file_limits {
4151 i_get_image_file_limits();
4154 my @check_args = qw(width height channels sample_size);
4156 sub check_file_limits {
4166 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4167 $opts{sample_size} = length(pack("d", 0));
4170 for my $name (@check_args) {
4171 unless (defined $opts{$name}) {
4172 $class->_set_error("check_file_limits: $name must be defined");
4175 unless ($opts{$name} == int($opts{$name})) {
4176 $class->_set_error("check_file_limits: $name must be a positive integer");
4181 my $result = i_int_check_image_file_limits(@opts{@check_args});
4183 $class->_set_error($class->_error_as_msg());
4189 # Shortcuts that can be exported
4191 sub newcolor { Imager::Color->new(@_); }
4192 sub newfont { Imager::Font->new(@_); }
4194 require Imager::Color::Float;
4195 return Imager::Color::Float->new(@_);
4198 *NC=*newcolour=*newcolor;
4205 #### Utility routines
4208 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4212 my ($self, $msg) = @_;
4215 $self->{ERRSTR} = $msg;
4223 # Default guess for the type of an image from extension
4225 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps webp xwd xpm dng ras);
4229 ( map { $_ => $_ } @simple_types ),
4235 pnm => "pnm", # technically wrong, but historically it works in Imager
4248 sub def_guess_type {
4251 my ($ext) = $name =~ /\.([^.]+)$/
4254 my $type = $ext_types{$ext}
4260 sub add_type_extensions {
4261 my ($class, $type, @exts) = @_;
4263 for my $ext (@exts) {
4264 exists $ext_types{lc $ext} or $ext_types{lc $ext} = lc $type;
4270 return @combine_types;
4273 # get the minimum of a list
4277 for(@_) { if ($_<$mx) { $mx=$_; }}
4281 # get the maximum of a list
4285 for(@_) { if ($_>$mx) { $mx=$_; }}
4289 # string stuff for iptc headers
4293 $str = substr($str,3);
4294 $str =~ s/[\n\r]//g;
4301 # A little hack to parse iptc headers.
4306 my($caption,$photogr,$headln,$credit);
4308 my $str=$self->{IPTCRAW};
4313 @ar=split(/8BIM/,$str);
4318 @sar=split(/\034\002/);
4319 foreach $item (@sar) {
4320 if ($item =~ m/^x/) {
4321 $caption = _clean($item);
4324 if ($item =~ m/^P/) {
4325 $photogr = _clean($item);
4328 if ($item =~ m/^i/) {
4329 $headln = _clean($item);
4332 if ($item =~ m/^n/) {
4333 $credit = _clean($item);
4339 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4343 # Inline added a new argument at the beginning
4347 or die "Only C language supported";
4349 require Imager::ExtUtils;
4350 return Imager::ExtUtils->inline_config;
4353 # threads shouldn't try to close raw Imager objects
4354 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4357 # this serves two purposes:
4358 # - a class method to load the file support modules included with Imager
4359 # (or were included, once the library dependent modules are split out)
4360 # - something for Module::ScanDeps to analyze
4361 # https://rt.cpan.org/Ticket/Display.html?id=6566
4364 pop @INC if $INC[-1] eq '.';
4365 eval { require Imager::File::GIF };
4366 eval { require Imager::File::JPEG };
4367 eval { require Imager::File::PNG };
4368 eval { require Imager::File::SGI };
4369 eval { require Imager::File::TIFF };
4370 eval { require Imager::File::ICO };
4371 eval { require Imager::Font::W32 };
4372 eval { require Imager::Font::FT2 };
4373 eval { require Imager::Font::T1 };
4374 eval { require Imager::Color::Table };
4383 my ($class, $fh) = @_;
4386 return $class->new_cb
4391 return print $fh $_[0];
4395 my $count = CORE::read $fh, $tmp, $_[1];
4403 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4404 unless (CORE::seek $fh, $_[0], $_[1]) {
4415 return $class->_new_perlio($fh);
4419 # backward compatibility for %formats
4420 package Imager::FORMATS;
4422 use constant IX_FORMATS => 0;
4423 use constant IX_LIST => 1;
4424 use constant IX_INDEX => 2;
4425 use constant IX_CLASSES => 3;
4428 my ($class, $formats, $classes) = @_;
4430 return bless [ $formats, [ ], 0, $classes ], $class;
4434 my ($self, $key) = @_;
4436 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4439 my $loaded = Imager::_load_file($file, \$error);
4444 if ($error =~ /^Can't locate /) {
4445 $error = "Can't locate $file";
4447 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4450 $self->[IX_FORMATS]{$key} = $value;
4456 my ($self, $key) = @_;
4458 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4460 $self->[IX_CLASSES]{$key} or return undef;
4462 return $self->_check($key);
4466 die "%Imager::formats is not user monifiable";
4470 die "%Imager::formats is not user monifiable";
4474 die "%Imager::formats is not user monifiable";
4478 my ($self, $key) = @_;
4480 if (exists $self->[IX_FORMATS]{$key}) {
4481 my $value = $self->[IX_FORMATS]{$key}
4486 $self->_check($key) or return 1==0;
4494 unless (@{$self->[IX_LIST]}) {
4496 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4497 keys %{$self->[IX_FORMATS]};
4499 for my $key (keys %{$self->[IX_CLASSES]}) {
4500 $self->[IX_FORMATS]{$key} and next;
4502 and push @{$self->[IX_LIST]}, $key;
4506 @{$self->[IX_LIST]} or return;
4507 $self->[IX_INDEX] = 1;
4508 return $self->[IX_LIST][0];
4514 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4517 return $self->[IX_LIST][$self->[IX_INDEX]++];
4523 return scalar @{$self->[IX_LIST]};
4528 # Below is the stub of documentation for your module. You better edit it!
4532 Imager - Perl extension for Generating 24 bit Images
4542 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4547 # see Imager::Files for information on the read() method
4548 my $img = Imager->new(file=>$file)
4549 or die Imager->errstr();
4551 $file =~ s/\.[^.]*$//;
4553 # Create smaller version
4554 # documented in Imager::Transformations
4555 my $thumb = $img->scale(scalefactor=>.3);
4557 # Autostretch individual channels
4558 $thumb->filter(type=>'autolevels');
4560 # try to save in one of these formats
4563 for $format ( qw( png gif jpeg tiff ppm ) ) {
4564 # Check if given format is supported
4565 if ($Imager::formats{$format}) {
4566 $file.="_low.$format";
4567 print "Storing image as: $file\n";
4568 # documented in Imager::Files
4569 $thumb->write(file=>$file) or
4577 Imager is a module for creating and altering images. It can read and
4578 write various image formats, draw primitive shapes like lines,and
4579 polygons, blend multiple images together in various ways, scale, crop,
4580 render text and more.
4582 =head2 Overview of documentation
4588 Imager - This document - Synopsis, Example, Table of Contents and
4593 L<Imager::Install> - installation notes for Imager.
4597 L<Imager::Tutorial> - a brief introduction to Imager.
4601 L<Imager::Cookbook> - how to do various things with Imager.
4605 L<Imager::ImageTypes> - Basics of constructing image objects with
4606 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4607 8/16/double bits/channel, color maps, channel masks, image tags, color
4608 quantization. Also discusses basic image information methods.
4612 L<Imager::Files> - IO interaction, reading/writing images, format
4617 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4622 L<Imager::Color> - Color specification.
4626 L<Imager::Fill> - Fill pattern specification.
4630 L<Imager::Font> - General font rendering, bounding boxes and font
4635 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4636 blending, pasting, convert and map.
4640 L<Imager::Engines> - Programmable transformations through
4641 C<transform()>, C<transform2()> and C<matrix_transform()>.
4645 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4650 L<Imager::Expr> - Expressions for evaluation engine used by
4655 L<Imager::Matrix2d> - Helper class for affine transformations.
4659 L<Imager::Fountain> - Helper for making gradient profiles.
4663 L<Imager::IO> - Imager I/O abstraction.
4667 L<Imager::API> - using Imager's C API
4671 L<Imager::APIRef> - API function reference
4675 L<Imager::Inline> - using Imager's C API from Inline::C
4679 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4683 L<Imager::Security> - brief security notes.
4687 L<Imager::Threads> - brief information on working with threads.
4691 =head2 Basic Overview
4693 An Image object is created with C<$img = Imager-E<gt>new()>.
4696 $img=Imager->new(); # create empty image
4697 $img->read(file=>'lena.png',type=>'png') or # read image from file
4698 die $img->errstr(); # give an explanation
4699 # if something failed
4701 or if you want to create an empty image:
4703 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4705 This example creates a completely black image of width 400 and height
4708 =head1 ERROR HANDLING
4710 In general a method will return false when it fails, if it does use
4711 the C<errstr()> method to find out why:
4717 Returns the last error message in that context.
4719 If the last error you received was from calling an object method, such
4720 as read, call errstr() as an object method to find out why:
4722 my $image = Imager->new;
4723 $image->read(file => 'somefile.gif')
4724 or die $image->errstr;
4726 If it was a class method then call errstr() as a class method:
4728 my @imgs = Imager->read_multi(file => 'somefile.gif')
4729 or die Imager->errstr;
4731 Note that in some cases object methods are implemented in terms of
4732 class methods so a failing object method may set both.
4736 The C<Imager-E<gt>new> method is described in detail in
4737 L<Imager::ImageTypes>.
4741 Where to find information on methods for Imager class objects.
4743 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4746 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4748 add_type_extensions() -
4749 L<Imager::Files/add_type_extensions($type, $ext, ...)> - add extensions for
4750 new image file types.
4752 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4755 alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
4756 channel index of the alpha channel (if any).
4758 arc() - L<Imager::Draw/arc()> - draw a filled arc
4760 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4763 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4765 check_file_limits() - L<Imager::Files/check_file_limits()>
4767 circle() - L<Imager::Draw/circle()> - draw a filled circle
4769 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4772 colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
4773 of channels used for color.
4775 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4776 colors in an image's palette (paletted images only)
4778 colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
4781 combine() - L<Imager::Transformations/combine()> - combine channels
4782 from one or more images.
4784 combines() - L<Imager::Draw/combines()> - return a list of the
4785 different combine type keywords
4787 compose() - L<Imager::Transformations/compose()> - compose one image
4790 convert() - L<Imager::Transformations/convert()> - transform the color
4793 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4796 crop() - L<Imager::Transformations/crop()> - extract part of an image
4798 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4799 used to guess the output file format based on the output file name
4801 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4803 difference() - L<Imager::Filters/difference()> - produce a difference
4804 images from two input images.
4806 errstr() - L</errstr()> - the error from the last failed operation.
4808 filter() - L<Imager::Filters/filter()> - image filtering
4810 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4811 palette, if it has one
4813 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4816 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4819 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4820 samples per pixel for an image
4822 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4823 different colors used by an image (works for direct color images)
4825 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4826 palette, if it has one
4828 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4830 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4832 get_file_limits() - L<Imager::Files/get_file_limits()>
4834 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4837 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4839 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4842 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4843 row or partial row of pixels.
4845 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4846 row or partial row of pixels.
4848 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4851 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4854 init() - L<Imager::ImageTypes/init()>
4856 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4857 image write functions should write the image in their bilevel (blank
4858 and white, no gray levels) format
4860 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4863 line() - L<Imager::Draw/line()> - draw an interval
4865 load_plugin() - L<Imager::Filters/load_plugin()>
4867 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4870 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4871 color palette from one or more input images.
4873 map() - L<Imager::Transformations/map()> - remap color
4876 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4878 matrix_transform() - L<Imager::Engines/matrix_transform()>
4880 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4882 NC() - L<Imager::Handy/NC()>
4884 NCF() - L<Imager::Handy/NCF()>
4886 new() - L<Imager::ImageTypes/new()>
4888 newcolor() - L<Imager::Handy/newcolor()>
4890 newcolour() - L<Imager::Handy/newcolour()>
4892 newfont() - L<Imager::Handy/newfont()>
4894 NF() - L<Imager::Handy/NF()>
4896 open() - L<Imager::Files/read()> - an alias for read()
4898 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4902 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4905 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4908 polygon() - L<Imager::Draw/polygon()>
4910 polyline() - L<Imager::Draw/polyline()>
4912 polypolygon() - L<Imager::Draw/polypolygon()>
4914 preload() - L<Imager::Files/preload()>
4916 read() - L<Imager::Files/read()> - read a single image from an image file
4918 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4921 read_types() - L<Imager::Files/read_types()> - list image types Imager
4924 register_filter() - L<Imager::Filters/register_filter()>
4926 register_reader() - L<Imager::Files/register_reader()>
4928 register_writer() - L<Imager::Files/register_writer()>
4930 rotate() - L<Imager::Transformations/rotate()>
4932 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4933 onto an image and use the alpha channel
4935 scale() - L<Imager::Transformations/scale()>
4937 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4939 scaleX() - L<Imager::Transformations/scaleX()>
4941 scaleY() - L<Imager::Transformations/scaleY()>
4943 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4946 set_file_limits() - L<Imager::Files/set_file_limits()>
4948 setmask() - L<Imager::ImageTypes/setmask()>
4950 setpixel() - L<Imager::Draw/setpixel()>
4952 setsamples() - L<Imager::Draw/setsamples()>
4954 setscanline() - L<Imager::Draw/setscanline()>
4956 settag() - L<Imager::ImageTypes/settag()>
4958 string() - L<Imager::Draw/string()> - draw text on an image
4960 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4962 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4964 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4966 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4968 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4969 double per sample image.
4971 transform() - L<Imager::Engines/"transform()">
4973 transform2() - L<Imager::Engines/"transform2()">
4975 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4977 unload_plugin() - L<Imager::Filters/unload_plugin()>
4979 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4982 write() - L<Imager::Files/write()> - write an image to a file
4984 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4987 write_types() - L<Imager::Files/read_types()> - list image types Imager
4990 =head1 CONCEPT INDEX
4992 animated GIF - L<Imager::Files/"Writing an animated GIF">
4994 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4995 L<Imager::ImageTypes/"Common Tags">.
4997 blend - alpha blending one image onto another
4998 L<Imager::Transformations/rubthrough()>
5000 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
5002 boxes, drawing - L<Imager::Draw/box()>
5004 changes between image - L<Imager::Filters/"Image Difference">
5006 channels, combine into one image - L<Imager::Transformations/combine()>
5008 color - L<Imager::Color>
5010 color names - L<Imager::Color>, L<Imager::Color::Table>
5012 combine modes - L<Imager::Draw/"Combine Types">
5014 compare images - L<Imager::Filters/"Image Difference">
5016 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
5018 convolution - L<Imager::Filters/conv>
5020 cropping - L<Imager::Transformations/crop()>
5022 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5024 C<diff> images - L<Imager::Filters/"Image Difference">
5026 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
5027 L<Imager::Cookbook/"Image spatial resolution">
5029 drawing boxes - L<Imager::Draw/box()>
5031 drawing lines - L<Imager::Draw/line()>
5033 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
5035 error message - L</"ERROR HANDLING">
5037 files, font - L<Imager::Font>
5039 files, image - L<Imager::Files>
5041 filling, types of fill - L<Imager::Fill>
5043 filling, boxes - L<Imager::Draw/box()>
5045 filling, flood fill - L<Imager::Draw/flood_fill()>
5047 flood fill - L<Imager::Draw/flood_fill()>
5049 fonts - L<Imager::Font>
5051 fonts, drawing with - L<Imager::Draw/string()>,
5052 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
5054 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5056 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
5058 fountain fill - L<Imager::Fill/"Fountain fills">,
5059 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5060 L<Imager::Filters/gradgen>
5062 GIF files - L<Imager::Files/"GIF">
5064 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
5066 gradient fill - L<Imager::Fill/"Fountain fills">,
5067 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5068 L<Imager::Filters/gradgen>
5070 gray scale, convert image to - L<Imager::Transformations/convert()>
5072 gaussian blur - L<Imager::Filters/gaussian>
5074 hatch fills - L<Imager::Fill/"Hatched fills">
5076 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5078 invert image - L<Imager::Filters/hardinvert>,
5079 L<Imager::Filters/hardinvertall>
5081 JPEG - L<Imager::Files/"JPEG">
5083 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
5085 lines, drawing - L<Imager::Draw/line()>
5087 matrix - L<Imager::Matrix2d>,
5088 L<Imager::Engines/"Matrix Transformations">,
5089 L<Imager::Font/transform()>
5091 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5093 mosaic - L<Imager::Filters/mosaic>
5095 noise, filter - L<Imager::Filters/noise>
5097 noise, rendered - L<Imager::Filters/turbnoise>,
5098 L<Imager::Filters/radnoise>
5100 paste - L<Imager::Transformations/paste()>,
5101 L<Imager::Transformations/rubthrough()>
5103 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5104 L<Imager::ImageTypes/new()>
5106 =for stopwords posterize
5108 posterize - L<Imager::Filters/postlevels>
5110 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5112 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5114 rectangles, drawing - L<Imager::Draw/box()>
5116 resizing an image - L<Imager::Transformations/scale()>,
5117 L<Imager::Transformations/crop()>
5119 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5121 saving an image - L<Imager::Files>
5123 scaling - L<Imager::Transformations/scale()>
5125 security - L<Imager::Security>
5127 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5129 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
5131 size, image - L<Imager::ImageTypes/getwidth()>,
5132 L<Imager::ImageTypes/getheight()>
5134 size, text - L<Imager::Font/bounding_box()>
5136 tags, image metadata - L<Imager::ImageTypes/"Tags">
5138 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5139 L<Imager::Font::Wrap>
5141 text, wrapping text in an area - L<Imager::Font::Wrap>
5143 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5145 threads - L<Imager::Threads>
5147 tiles, color - L<Imager::Filters/mosaic>
5149 transparent images - L<Imager::ImageTypes>,
5150 L<Imager::Cookbook/"Transparent PNG">
5152 =for stopwords unsharp
5154 unsharp mask - L<Imager::Filters/unsharpmask>
5156 watermark - L<Imager::Filters/watermark>
5158 writing an image to a file - L<Imager::Files>
5162 The best place to get help with Imager is the mailing list.
5164 To subscribe send a message with C<subscribe> in the body to:
5166 imager-devel+request@molar.is
5172 L<http://www.molar.is/en/lists/imager-devel/>
5176 where you can also find the mailing list archive.
5178 You can report bugs by pointing your browser at:
5182 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5186 or by sending an email to:
5190 bug-Imager@rt.cpan.org
5194 Please remember to include the versions of Imager, perl, supporting
5195 libraries, and any relevant code. If you have specific images that
5196 cause the problems, please include those too.
5198 If you don't want to publish your email address on a mailing list you
5199 can use CPAN::Forum:
5201 http://www.cpanforum.com/dist/Imager
5203 You will need to register to post.
5205 =head1 CONTRIBUTING TO IMAGER
5211 If you like or dislike Imager, you can add a public review of Imager
5214 http://cpanratings.perl.org/dist/Imager
5216 =for stopwords Bitcard
5218 This requires a Bitcard account (http://www.bitcard.org).
5220 You can also send email to the maintainer below.
5222 If you send me a bug report via email, it will be copied to Request
5227 I accept patches, preferably against the master branch in git. Please
5228 include an explanation of the reason for why the patch is needed or
5231 Your patch should include regression tests where possible, otherwise
5232 it will be delayed until I get a chance to write them.
5234 To browse Imager's git repository:
5236 http://git.imager.perl.org/imager.git
5240 git clone git://git.imager.perl.org/imager.git
5242 My preference is that patches are provided in the format produced by
5243 C<git format-patch>, for example, if you made your changes in a branch
5244 from master you might do:
5246 git format-patch -k --stdout master >my-patch.txt
5248 and then attach that to your bug report, either by adding it as an
5249 attachment in your email client, or by using the Request Tracker
5250 attachment mechanism.
5254 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5256 Arnar M. Hrafnkelsson is the original author of Imager.
5258 Many others have contributed to Imager, please see the C<README> for a
5263 Imager is licensed under the same terms as perl itself.
5266 makeblendedfont Fontforge
5268 A test font, generated by the Debian packaged Fontforge,
5269 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5270 copyrighted by Adobe. See F<adobe.txt> in the source for license
5275 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5276 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5277 L<Imager::Font>(3), L<Imager::Transformations>(3),
5278 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5279 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5281 L<http://imager.perl.org/>
5283 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5285 Other perl imaging modules include:
5287 L<GD>(3), L<Image::Magick>(3),
5288 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5289 L<Prima::Image>, L<IPA>.
5291 For manipulating image metadata see L<Image::ExifTool>.
5293 If you're trying to use Imager for array processing, you should
5294 probably using L<PDL>.