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}); },
282 $filters{gaussian2} = {
283 callseq => [ 'image', 'stddevX', 'stddevY' ],
285 callsub => sub { my %hsh = @_; i_gaussian2($hsh{image}, $hsh{stddevX}, $hsh{stddevY}); },
289 callseq => [ qw(image size) ],
290 defaults => { size => 20 },
291 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
295 callseq => [ qw(image bump elevation lightx lighty st) ],
296 defaults => { elevation=>0, st=> 2 },
299 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
300 $hsh{lightx}, $hsh{lighty}, $hsh{st});
303 $filters{bumpmap_complex} =
305 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
322 for my $cname (qw/Ia Il Is/) {
323 my $old = $hsh{$cname};
324 my $new_color = _color($old)
325 or die $Imager::ERRSTR, "\n";
326 $hsh{$cname} = $new_color;
328 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
329 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
330 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
334 $filters{postlevels} =
336 callseq => [ qw(image levels) ],
337 defaults => { levels => 10 },
338 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
340 $filters{watermark} =
342 callseq => [ qw(image wmark tx ty pixdiff) ],
343 defaults => { pixdiff=>10, tx=>0, ty=>0 },
347 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
353 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
355 ftype => { linear => 0,
361 repeat => { none => 0,
376 multiply => 2, mult => 2,
379 subtract => 5, 'sub' => 5,
389 defaults => { ftype => 0, repeat => 0, combine => 0,
390 super_sample => 0, ssample_param => 4,
403 # make sure the segments are specified with colors
405 for my $segment (@{$hsh{segments}}) {
406 my @new_segment = @$segment;
408 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
409 push @segments, \@new_segment;
412 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
413 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
414 $hsh{ssample_param}, \@segments)
415 or die Imager->_error_as_msg() . "\n";
418 $filters{unsharpmask} =
420 callseq => [ qw(image stddev scale) ],
421 defaults => { stddev=>2.0, scale=>1.0 },
425 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
429 $FORMATGUESS=\&def_guess_type;
439 # NOTE: this might be moved to an import override later on
444 if ($_[$i] eq '-log-stderr') {
452 goto &Exporter::import;
456 Imager->open_log(log => $_[0], level => $_[1]);
461 my %parms=(loglevel=>1,@_);
463 if (exists $parms{'warn_obsolete'}) {
464 $warn_obsolete = $parms{'warn_obsolete'};
468 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
472 if (exists $parms{'t1log'}) {
474 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
475 Imager->_set_error(Imager->_error_as_msg);
489 my (%opts) = ( loglevel => 1, @_ );
491 $is_logging = i_init_log($opts{log}, $opts{loglevel});
492 unless ($is_logging) {
493 Imager->_set_error(Imager->_error_as_msg());
497 Imager->log("Imager $VERSION starting\n", 1);
503 i_init_log(undef, -1);
508 my ($class, $message, $level) = @_;
510 defined $level or $level = 1;
512 i_log_entry($message, $level);
522 print "shutdown code\n";
523 # for(keys %instances) { $instances{$_}->DESTROY(); }
524 malloc_state(); # how do decide if this should be used? -- store something from the import
525 print "Imager exiting\n";
529 # Load a filter plugin
535 if ($^O eq 'android') {
537 $filename = File::Spec->rel2abs($filename);
540 my ($DSO_handle,$str)=DSO_open($filename);
541 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
542 my %funcs=DSO_funclist($DSO_handle);
543 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
545 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
547 $DSOs{$filename}=[$DSO_handle,\%funcs];
550 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
551 $DEBUG && print "eval string:\n",$evstr,"\n";
563 if ($^O eq 'android') {
565 $filename = File::Spec->rel2abs($filename);
568 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
569 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
570 for(keys %{$funcref}) {
572 $DEBUG && print "unloading: $_\n";
574 my $rc=DSO_close($DSO_handle);
575 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
579 # take the results of i_error() and make a message out of it
581 return join(": ", map $_->[0], i_errors());
584 # this function tries to DWIM for color parameters
585 # color objects are used as is
586 # simple scalars are simply treated as single parameters to Imager::Color->new
587 # hashrefs are treated as named argument lists to Imager::Color->new
588 # arrayrefs are treated as list arguments to Imager::Color->new iff any
590 # other arrayrefs are treated as list arguments to Imager::Color::Float
594 # perl 5.6.0 seems to do weird things to $arg if we don't make an
595 # explicitly stringified copy
596 # I vaguely remember a bug on this on p5p, but couldn't find it
597 # through bugs.perl.org (I had trouble getting it to find any bugs)
598 my $copy = $arg . "";
602 if (UNIVERSAL::isa($arg, "Imager::Color")
603 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
607 if ($copy =~ /^HASH\(/) {
608 $result = Imager::Color->new(%$arg);
610 elsif ($copy =~ /^ARRAY\(/) {
611 $result = Imager::Color->new(@$arg);
614 $Imager::ERRSTR = "Not a color";
619 # assume Imager::Color::new knows how to handle it
620 $result = Imager::Color->new($arg);
627 my ($self, $combine, $default) = @_;
629 if (!defined $combine && ref $self) {
630 $combine = $self->{combine};
632 defined $combine or $combine = $defaults{combine};
633 defined $combine or $combine = $default;
635 if (exists $combine_types{$combine}) {
636 $combine = $combine_types{$combine};
643 my ($self, $method) = @_;
646 or return Imager->_set_error("$method needs an image object");
648 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
650 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
651 $msg = "$method: $msg" if $method;
652 $self->_set_error($msg);
657 # returns first defined parameter
660 return $_ if defined $_;
666 # Methods to be called on objects.
669 # Create a new Imager object takes very few parameters.
670 # usually you call this method and then call open from
671 # the resulting object
678 $self->{IMG}=undef; # Just to indicate what exists
679 $self->{ERRSTR}=undef; #
680 $self->{DEBUG}=$DEBUG;
681 $self->{DEBUG} and print "Initialized Imager\n";
682 if (defined $hsh{file} ||
685 defined $hsh{callback} ||
686 defined $hsh{readcb} ||
687 defined $hsh{data} ||
689 # allow $img = Imager->new(file => $filename)
692 # type is already used as a parameter to new(), rename it for the
694 if ($hsh{filetype}) {
695 $extras{type} = $hsh{filetype};
697 unless ($self->read(%hsh, %extras)) {
698 $Imager::ERRSTR = $self->{ERRSTR};
702 elsif (defined $hsh{xsize} || defined $hsh{ysize}) {
703 unless ($self->img_set(%hsh)) {
704 $Imager::ERRSTR = $self->{ERRSTR};
709 Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
716 # Copy an entire image with no changes
717 # - if an image has magic the copy of it will not be magical
722 $self->_valid_image("copy")
725 unless (defined wantarray) {
727 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
731 my $newcopy=Imager->new();
732 $newcopy->{IMG} = i_copy($self->{IMG});
741 $self->_valid_image("paste")
744 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
745 my $src = $input{img} || $input{src};
747 $self->_set_error("no source image");
750 unless ($src->_valid_image("paste")) {
751 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
754 $input{left}=0 if $input{left} <= 0;
755 $input{top}=0 if $input{top} <= 0;
757 my($r,$b)=i_img_info($src->{IMG});
758 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
759 my ($src_right, $src_bottom);
760 if ($input{src_coords}) {
761 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
764 if (defined $input{src_maxx}) {
765 $src_right = $input{src_maxx};
767 elsif (defined $input{width}) {
768 if ($input{width} <= 0) {
769 $self->_set_error("paste: width must me positive");
772 $src_right = $src_left + $input{width};
777 if (defined $input{src_maxy}) {
778 $src_bottom = $input{src_maxy};
780 elsif (defined $input{height}) {
781 if ($input{height} < 0) {
782 $self->_set_error("paste: height must be positive");
785 $src_bottom = $src_top + $input{height};
792 $src_right > $r and $src_right = $r;
793 $src_bottom > $b and $src_bottom = $b;
795 if ($src_right <= $src_left
796 || $src_bottom < $src_top) {
797 $self->_set_error("nothing to paste");
801 i_copyto($self->{IMG}, $src->{IMG},
802 $src_left, $src_top, $src_right, $src_bottom,
803 $input{left}, $input{top});
805 return $self; # What should go here??
808 # Crop an image - i.e. return a new image that is smaller
813 $self->_valid_image("crop")
816 unless (defined wantarray) {
818 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
824 my ($w, $h, $l, $r, $b, $t) =
825 @hsh{qw(width height left right bottom top)};
827 # work through the various possibilities
832 elsif (!defined $r) {
833 $r = $self->getwidth;
845 $l = int(0.5+($self->getwidth()-$w)/2);
850 $r = $self->getwidth;
856 elsif (!defined $b) {
857 $b = $self->getheight;
869 $t=int(0.5+($self->getheight()-$h)/2);
874 $b = $self->getheight;
877 ($l,$r)=($r,$l) if $l>$r;
878 ($t,$b)=($b,$t) if $t>$b;
881 $r > $self->getwidth and $r = $self->getwidth;
883 $b > $self->getheight and $b = $self->getheight;
885 if ($l == $r || $t == $b) {
886 $self->_set_error("resulting image would have no content");
889 if( $r < $l or $b < $t ) {
890 $self->_set_error("attempting to crop outside of the image");
893 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
895 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
900 my ($self, %opts) = @_;
905 my $x = $opts{xsize} || $self->getwidth;
906 my $y = $opts{ysize} || $self->getheight;
907 my $channels = $opts{channels} || $self->getchannels;
909 my $out = Imager->new;
910 if ($channels == $self->getchannels) {
911 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
914 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
916 unless ($out->{IMG}) {
917 $self->{ERRSTR} = $self->_error_as_msg;
924 # Sets an image to a certain size and channel number
925 # if there was previously data in the image it is discarded
938 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
943 if (my $channels = $model_channels{$hsh{model}}) {
944 $hsh{channels} = $channels;
947 $self->_set_error("new: unknown value for model '$hsh{model}'");
952 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
953 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
954 $hsh{maxcolors} || 256);
956 elsif ($hsh{bits} eq 'double') {
957 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
959 elsif ($hsh{bits} == 16) {
960 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
963 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
967 unless ($self->{IMG}) {
968 $self->_set_error(Imager->_error_as_msg());
975 # created a masked version of the current image
979 $self->_valid_image("masked")
982 my %opts = (left => 0,
984 right => $self->getwidth,
985 bottom => $self->getheight,
987 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
989 my $result = Imager->new;
990 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
991 $opts{top}, $opts{right} - $opts{left},
992 $opts{bottom} - $opts{top});
993 unless ($result->{IMG}) {
994 $self->_set_error(Imager->_error_as_msg);
998 # keep references to the mask and base images so they don't
1000 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
1005 # convert an RGB image into a paletted image
1009 if (@_ != 1 && !ref $_[0]) {
1016 unless (defined wantarray) {
1017 my @caller = caller;
1018 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
1022 $self->_valid_image("to_paletted")
1025 my $result = Imager->new;
1026 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1027 $self->_set_error(Imager->_error_as_msg);
1035 my ($class, $quant, @images) = @_;
1038 Imager->_set_error("make_palette: supply at least one image");
1042 for my $img (@images) {
1043 unless ($img->{IMG}) {
1044 Imager->_set_error("make_palette: image $index is empty");
1050 my @cols = i_img_make_palette($quant, map $_->{IMG}, @images);
1052 Imager->_set_error(Imager->_error_as_msg);
1058 # convert a paletted (or any image) to an 8-bit/channel RGB image
1062 unless (defined wantarray) {
1063 my @caller = caller;
1064 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1068 $self->_valid_image("to_rgb8")
1071 my $result = Imager->new;
1072 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1073 $self->_set_error(Imager->_error_as_msg());
1080 # convert a paletted (or any image) to a 16-bit/channel RGB image
1084 unless (defined wantarray) {
1085 my @caller = caller;
1086 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1090 $self->_valid_image("to_rgb16")
1093 my $result = Imager->new;
1094 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1095 $self->_set_error(Imager->_error_as_msg());
1102 # convert a paletted (or any image) to an double/channel RGB image
1106 unless (defined wantarray) {
1107 my @caller = caller;
1108 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1112 $self->_valid_image("to_rgb_double")
1115 my $result = Imager->new;
1116 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1117 $self->_set_error(Imager->_error_as_msg());
1126 my %opts = (colors=>[], @_);
1128 $self->_valid_image("addcolors")
1131 my @colors = @{$opts{colors}}
1134 for my $color (@colors) {
1135 $color = _color($color);
1137 $self->_set_error($Imager::ERRSTR);
1142 return i_addcolors($self->{IMG}, @colors);
1147 my %opts = (start=>0, colors=>[], @_);
1149 $self->_valid_image("setcolors")
1152 my @colors = @{$opts{colors}}
1155 for my $color (@colors) {
1156 $color = _color($color);
1158 $self->_set_error($Imager::ERRSTR);
1163 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1170 $self->_valid_image("getcolors")
1173 if (!exists $opts{start} && !exists $opts{count}) {
1176 $opts{count} = $self->colorcount;
1178 elsif (!exists $opts{count}) {
1181 elsif (!exists $opts{start}) {
1185 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1191 $self->_valid_image("colorcount")
1194 return i_colorcount($self->{IMG});
1200 $self->_valid_image("maxcolors")
1203 i_maxcolors($self->{IMG});
1210 $self->_valid_image("findcolor")
1213 unless ($opts{color}) {
1214 $self->_set_error("findcolor: no color parameter");
1218 my $color = _color($opts{color})
1221 return i_findcolor($self->{IMG}, $color);
1227 $self->_valid_image("bits")
1230 my $bits = i_img_bits($self->{IMG});
1231 if ($bits && $bits == length(pack("d", 1)) * 8) {
1240 $self->_valid_image("type")
1243 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1249 $self->_valid_image("virtual")
1252 return i_img_virtual($self->{IMG});
1258 $self->_valid_image("is_bilevel")
1261 return i_img_is_monochrome($self->{IMG});
1265 my ($self, %opts) = @_;
1267 $self->_valid_image("tags")
1270 if (defined $opts{name}) {
1274 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1275 push @result, (i_tags_get($self->{IMG}, $found))[1];
1278 return wantarray ? @result : $result[0];
1280 elsif (defined $opts{code}) {
1284 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1285 push @result, (i_tags_get($self->{IMG}, $found))[1];
1292 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1295 return i_tags_count($self->{IMG});
1304 $self->_valid_image("addtag")
1308 if (defined $opts{value}) {
1309 if ($opts{value} =~ /^\d+$/) {
1311 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1314 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1317 elsif (defined $opts{data}) {
1318 # force addition as a string
1319 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1322 $self->{ERRSTR} = "No value supplied";
1326 elsif ($opts{code}) {
1327 if (defined $opts{value}) {
1328 if ($opts{value} =~ /^\d+$/) {
1330 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1333 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1336 elsif (defined $opts{data}) {
1337 # force addition as a string
1338 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1341 $self->{ERRSTR} = "No value supplied";
1354 $self->_valid_image("deltag")
1357 if (defined $opts{'index'}) {
1358 return i_tags_delete($self->{IMG}, $opts{'index'});
1360 elsif (defined $opts{name}) {
1361 return i_tags_delbyname($self->{IMG}, $opts{name});
1363 elsif (defined $opts{code}) {
1364 return i_tags_delbycode($self->{IMG}, $opts{code});
1367 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1373 my ($self, %opts) = @_;
1375 $self->_valid_image("settag")
1379 $self->deltag(name=>$opts{name});
1380 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1382 elsif (defined $opts{code}) {
1383 $self->deltag(code=>$opts{code});
1384 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1392 sub _get_reader_io {
1393 my ($self, $input) = @_;
1396 return $input->{io}, undef;
1398 elsif ($input->{fd}) {
1399 return io_new_fd($input->{fd});
1401 elsif ($input->{fh}) {
1402 unless (Scalar::Util::openhandle($input->{fh})) {
1403 $self->_set_error("Handle in fh option not opened");
1406 return Imager::IO->new_fh($input->{fh});
1408 elsif ($input->{file}) {
1409 my $file = IO::File->new($input->{file}, "r");
1411 $self->_set_error("Could not open $input->{file}: $!");
1415 return (io_new_fd(fileno($file)), $file);
1417 elsif ($input->{data}) {
1418 return io_new_buffer($input->{data});
1420 elsif ($input->{callback} || $input->{readcb}) {
1421 if (!$input->{seekcb}) {
1422 $self->_set_error("Need a seekcb parameter");
1424 if ($input->{maxbuffer}) {
1425 return io_new_cb($input->{writecb},
1426 $input->{callback} || $input->{readcb},
1427 $input->{seekcb}, $input->{closecb},
1428 $input->{maxbuffer});
1431 return io_new_cb($input->{writecb},
1432 $input->{callback} || $input->{readcb},
1433 $input->{seekcb}, $input->{closecb});
1437 $self->_set_error("file/fd/fh/data/callback parameter missing");
1442 sub _get_writer_io {
1443 my ($self, $input) = @_;
1445 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1452 elsif ($input->{fd}) {
1453 $io = io_new_fd($input->{fd});
1455 elsif ($input->{fh}) {
1456 unless (Scalar::Util::openhandle($input->{fh})) {
1457 $self->_set_error("Handle in fh option not opened");
1460 $io = Imager::IO->new_fh($input->{fh});
1462 elsif ($input->{file}) {
1463 my $fh = new IO::File($input->{file},"w+");
1465 $self->_set_error("Could not open file $input->{file}: $!");
1468 binmode($fh) or die;
1469 $io = io_new_fd(fileno($fh));
1472 elsif ($input->{data}) {
1473 $io = io_new_bufchain();
1475 elsif ($input->{callback} || $input->{writecb}) {
1476 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1479 $io = io_new_cb($input->{callback} || $input->{writecb},
1481 $input->{seekcb}, $input->{closecb});
1484 $self->_set_error("file/fd/fh/data/callback parameter missing");
1488 unless ($buffered) {
1489 $io->set_buffered(0);
1492 return ($io, @extras);
1498 return i_test_format_probe($io, -1);
1501 sub add_file_magic {
1502 my ($class, %opts) = @_;
1504 my $name = delete $opts{name};
1505 my $bits = delete $opts{bits};
1506 my $mask = delete $opts{mask};
1508 unless (i_add_file_magic($name, $bits, $mask)) {
1509 Imager->_set_error(Imager->_error_as_msg);
1516 # Read an image from file
1522 if (defined($self->{IMG})) {
1523 # let IIM_DESTROY do the destruction, since the image may be
1524 # referenced from elsewhere
1525 #i_img_destroy($self->{IMG});
1526 undef($self->{IMG});
1529 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1531 my $type = $input{'type'};
1533 $type = _test_format($IO);
1536 if ($input{file} && !$type) {
1538 $type = $FORMATGUESS->($input{file});
1542 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1543 $input{file} and $msg .= " or file name";
1544 $self->_set_error($msg);
1548 _reader_autoload($type);
1550 if ($readers{$type} && $readers{$type}{single}) {
1551 return $readers{$type}{single}->($self, $IO, %input);
1554 unless ($formats_low{$type}) {
1555 my $read_types = join ', ', sort Imager->read_types();
1556 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1560 my $allow_incomplete = $input{allow_incomplete};
1561 defined $allow_incomplete or $allow_incomplete = 0;
1563 if ( $type eq 'pnm' ) {
1564 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1565 if ( !defined($self->{IMG}) ) {
1566 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1569 $self->{DEBUG} && print "loading a pnm file\n";
1573 if ( $type eq 'bmp' ) {
1574 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1575 if ( !defined($self->{IMG}) ) {
1576 $self->{ERRSTR}=$self->_error_as_msg();
1579 $self->{DEBUG} && print "loading a bmp file\n";
1582 if ( $type eq 'tga' ) {
1583 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1584 if ( !defined($self->{IMG}) ) {
1585 $self->{ERRSTR}=$self->_error_as_msg();
1588 $self->{DEBUG} && print "loading a tga file\n";
1591 if ( $type eq 'raw' ) {
1592 unless ( $input{xsize} && $input{ysize} ) {
1593 $self->_set_error('missing xsize or ysize parameter for raw');
1597 my $interleave = _first($input{raw_interleave}, $input{interleave});
1598 unless (defined $interleave) {
1599 my @caller = caller;
1600 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1603 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1604 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1606 $self->{IMG} = i_readraw_wiol( $IO,
1612 if ( !defined($self->{IMG}) ) {
1613 $self->{ERRSTR}=$self->_error_as_msg();
1616 $self->{DEBUG} && print "loading a raw file\n";
1622 sub register_reader {
1623 my ($class, %opts) = @_;
1626 or die "register_reader called with no type parameter\n";
1628 my $type = $opts{type};
1630 defined $opts{single} || defined $opts{multiple}
1631 or die "register_reader called with no single or multiple parameter\n";
1633 $readers{$type} = { };
1634 if ($opts{single}) {
1635 $readers{$type}{single} = $opts{single};
1637 if ($opts{multiple}) {
1638 $readers{$type}{multiple} = $opts{multiple};
1644 sub register_writer {
1645 my ($class, %opts) = @_;
1648 or die "register_writer called with no type parameter\n";
1650 my $type = $opts{type};
1652 defined $opts{single} || defined $opts{multiple}
1653 or die "register_writer called with no single or multiple parameter\n";
1655 $writers{$type} = { };
1656 if ($opts{single}) {
1657 $writers{$type}{single} = $opts{single};
1659 if ($opts{multiple}) {
1660 $writers{$type}{multiple} = $opts{multiple};
1671 grep($file_formats{$_}, keys %formats),
1672 qw(ico sgi), # formats not handled directly, but supplied with Imager
1683 grep($file_formats{$_}, keys %formats),
1684 qw(ico sgi), # formats not handled directly, but supplied with Imager
1691 my ($file, $error) = @_;
1693 if ($attempted_to_load{$file}) {
1694 if ($file_load_errors{$file}) {
1695 $$error = $file_load_errors{$file};
1703 local $SIG{__DIE__};
1706 pop @INC if $INC[-1] eq '.';
1707 ++$attempted_to_load{$file};
1715 my $work = $@ || "Unknown error";
1717 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1718 $work =~ s/\n/\\n/g;
1719 $work =~ s/\s*\.?\z/ loading $file/;
1720 $file_load_errors{$file} = $work;
1727 # probes for an Imager::File::whatever module
1728 sub _reader_autoload {
1731 return if $formats_low{$type} || $readers{$type};
1733 return unless $type =~ /^\w+$/;
1735 my $file = "Imager/File/\U$type\E.pm";
1738 my $loaded = _load_file($file, \$error);
1739 if (!$loaded && $error =~ /^Can't locate /) {
1740 my $filer = "Imager/File/\U$type\EReader.pm";
1741 $loaded = _load_file($filer, \$error);
1742 if ($error =~ /^Can't locate /) {
1743 $error = "Can't locate $file or $filer";
1747 $reader_load_errors{$type} = $error;
1751 # probes for an Imager::File::whatever module
1752 sub _writer_autoload {
1755 return if $formats_low{$type} || $writers{$type};
1757 return unless $type =~ /^\w+$/;
1759 my $file = "Imager/File/\U$type\E.pm";
1762 my $loaded = _load_file($file, \$error);
1763 if (!$loaded && $error =~ /^Can't locate /) {
1764 my $filew = "Imager/File/\U$type\EWriter.pm";
1765 $loaded = _load_file($filew, \$error);
1766 if ($error =~ /^Can't locate /) {
1767 $error = "Can't locate $file or $filew";
1771 $writer_load_errors{$type} = $error;
1775 sub _fix_gif_positions {
1776 my ($opts, $opt, $msg, @imgs) = @_;
1778 my $positions = $opts->{'gif_positions'};
1780 for my $pos (@$positions) {
1781 my ($x, $y) = @$pos;
1782 my $img = $imgs[$index++];
1783 $img->settag(name=>'gif_left', value=>$x);
1784 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1786 $$msg .= "replaced with the gif_left and gif_top tags";
1791 gif_each_palette=>'gif_local_map',
1792 interlace => 'gif_interlace',
1793 gif_delays => 'gif_delay',
1794 gif_positions => \&_fix_gif_positions,
1795 gif_loop_count => 'gif_loop',
1798 # options that should be converted to colors
1799 my %color_opts = map { $_ => 1 } qw/i_background/;
1802 my ($self, $opts, $prefix, @imgs) = @_;
1804 for my $opt (keys %$opts) {
1806 if ($obsolete_opts{$opt}) {
1807 my $new = $obsolete_opts{$opt};
1808 my $msg = "Obsolete option $opt ";
1810 $new->($opts, $opt, \$msg, @imgs);
1813 $msg .= "replaced with the $new tag ";
1816 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1817 warn $msg if $warn_obsolete && $^W;
1819 next unless $tagname =~ /^\Q$prefix/;
1820 my $value = $opts->{$opt};
1821 if ($color_opts{$opt}) {
1822 $value = _color($value);
1824 $self->_set_error($Imager::ERRSTR);
1829 if (UNIVERSAL::isa($value, "Imager::Color")) {
1830 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1831 for my $img (@imgs) {
1832 $img->settag(name=>$tagname, value=>$tag);
1835 elsif (ref($value) eq 'ARRAY') {
1836 for my $i (0..$#$value) {
1837 my $val = $value->[$i];
1839 if (UNIVERSAL::isa($val, "Imager::Color")) {
1840 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1842 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1845 $self->_set_error("Unknown reference type " . ref($value) .
1846 " supplied in array for $opt");
1852 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1857 $self->_set_error("Unknown reference type " . ref($value) .
1858 " supplied for $opt");
1863 # set it as a tag for every image
1864 for my $img (@imgs) {
1865 $img->settag(name=>$tagname, value=>$value);
1873 # Write an image to file
1876 my %input=(jpegquality=>75,
1886 $self->_valid_image("write")
1889 $self->_set_opts(\%input, "i_", $self)
1892 my $type = $input{'type'};
1893 if (!$type and $input{file}) {
1894 $type = $FORMATGUESS->($input{file});
1897 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1901 _writer_autoload($type);
1904 if ($writers{$type} && $writers{$type}{single}) {
1905 ($IO, $fh) = $self->_get_writer_io(\%input)
1908 $writers{$type}{single}->($self, $IO, %input, type => $type)
1912 if (!$formats_low{$type}) {
1913 my $write_types = join ', ', sort Imager->write_types();
1914 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1918 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1921 if ( $type eq 'pnm' ) {
1922 $self->_set_opts(\%input, "pnm_", $self)
1924 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1925 $self->{ERRSTR} = $self->_error_as_msg();
1928 $self->{DEBUG} && print "writing a pnm file\n";
1930 elsif ( $type eq 'raw' ) {
1931 $self->_set_opts(\%input, "raw_", $self)
1933 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1934 $self->{ERRSTR} = $self->_error_as_msg();
1937 $self->{DEBUG} && print "writing a raw file\n";
1939 elsif ( $type eq 'bmp' ) {
1940 $self->_set_opts(\%input, "bmp_", $self)
1942 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1943 $self->{ERRSTR} = $self->_error_as_msg;
1946 $self->{DEBUG} && print "writing a bmp file\n";
1948 elsif ( $type eq 'tga' ) {
1949 $self->_set_opts(\%input, "tga_", $self)
1952 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1953 $self->{ERRSTR}=$self->_error_as_msg();
1956 $self->{DEBUG} && print "writing a tga file\n";
1960 if (exists $input{'data'}) {
1961 my $data = io_slurp($IO);
1963 $self->{ERRSTR}='Could not slurp from buffer';
1966 ${$input{data}} = $data;
1972 my ($class, $opts, @images) = @_;
1974 my $type = $opts->{type};
1976 if (!$type && $opts->{'file'}) {
1977 $type = $FORMATGUESS->($opts->{'file'});
1980 $class->_set_error('type parameter missing and not possible to guess from extension');
1983 # translate to ImgRaw
1985 for my $img (@images) {
1986 unless (ref $img && Scalar::Util::blessed($img) && $img->isa("Imager")) {
1987 $class->_set_error("write_multi: image $index is not an Imager image object");
1990 unless ($img->_valid_image("write_multi")) {
1991 $class->_set_error($img->errstr . " (image $index)");
1996 $class->_set_opts($opts, "i_", @images)
1998 my @work = map $_->{IMG}, @images;
2000 _writer_autoload($type);
2003 if ($writers{$type} && $writers{$type}{multiple}) {
2004 ($IO, $file) = $class->_get_writer_io($opts, $type)
2007 $writers{$type}{multiple}->($class, $IO, $opts, @images)
2011 if (!$formats{$type}) {
2012 my $write_types = join ', ', sort Imager->write_types();
2013 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
2017 ($IO, $file) = $class->_get_writer_io($opts, $type)
2020 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
2024 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
2029 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
2035 if (exists $opts->{'data'}) {
2036 my $data = io_slurp($IO);
2038 Imager->_set_error('Could not slurp from buffer');
2041 ${$opts->{data}} = $data;
2046 # read multiple images from a file
2048 my ($class, %opts) = @_;
2050 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2053 my $type = $opts{'type'};
2055 $type = _test_format($IO);
2058 if ($opts{file} && !$type) {
2060 $type = $FORMATGUESS->($opts{file});
2064 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2065 $opts{file} and $msg .= " or file name";
2066 Imager->_set_error($msg);
2070 _reader_autoload($type);
2072 if ($readers{$type} && $readers{$type}{multiple}) {
2073 return $readers{$type}{multiple}->($IO, %opts);
2076 unless ($formats{$type}) {
2077 my $read_types = join ', ', sort Imager->read_types();
2078 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2083 if ($type eq 'pnm') {
2084 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2087 my $img = Imager->new;
2088 if ($img->read(%opts, io => $IO, type => $type)) {
2091 Imager->_set_error($img->errstr);
2096 $ERRSTR = _error_as_msg();
2100 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2104 # Destroy an Imager object
2108 # delete $instances{$self};
2109 if (defined($self->{IMG})) {
2110 # the following is now handled by the XS DESTROY method for
2111 # Imager::ImgRaw object
2112 # Re-enabling this will break virtual images
2113 # tested for in t/t020masked.t
2114 # i_img_destroy($self->{IMG});
2115 undef($self->{IMG});
2117 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2121 # Perform an inplace filter of an image
2122 # that is the image will be overwritten with the data
2129 $self->_valid_image("filter")
2132 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2134 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2135 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2138 if ($filters{$input{'type'}}{names}) {
2139 my $names = $filters{$input{'type'}}{names};
2140 for my $name (keys %$names) {
2141 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2142 $input{$name} = $names->{$name}{$input{$name}};
2146 if (defined($filters{$input{'type'}}{defaults})) {
2147 %hsh=( image => $self->{IMG},
2149 %{$filters{$input{'type'}}{defaults}},
2152 %hsh=( image => $self->{IMG},
2157 my @cs=@{$filters{$input{'type'}}{callseq}};
2160 if (!defined($hsh{$_})) {
2161 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2166 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2167 &{$filters{$input{'type'}}{callsub}}(%hsh);
2170 chomp($self->{ERRSTR} = $@);
2176 $self->{DEBUG} && print "callseq is: @cs\n";
2177 $self->{DEBUG} && print "matching callseq is: @b\n";
2182 sub register_filter {
2184 my %hsh = ( defaults => {}, @_ );
2187 or die "register_filter() with no type\n";
2188 defined $hsh{callsub}
2189 or die "register_filter() with no callsub\n";
2190 defined $hsh{callseq}
2191 or die "register_filter() with no callseq\n";
2193 exists $filters{$hsh{type}}
2196 $filters{$hsh{type}} = \%hsh;
2201 sub scale_calculate {
2204 my %opts = ('type'=>'max', @_);
2206 # none of these should be references
2207 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2208 if (defined $opts{$name} && ref $opts{$name}) {
2209 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2214 my ($x_scale, $y_scale);
2215 my $width = $opts{width};
2216 my $height = $opts{height};
2218 defined $width or $width = $self->getwidth;
2219 defined $height or $height = $self->getheight;
2222 unless (defined $width && defined $height) {
2223 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2228 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2229 $x_scale = $opts{'xscalefactor'};
2230 $y_scale = $opts{'yscalefactor'};
2232 elsif ($opts{'xscalefactor'}) {
2233 $x_scale = $opts{'xscalefactor'};
2234 $y_scale = $opts{'scalefactor'} || $x_scale;
2236 elsif ($opts{'yscalefactor'}) {
2237 $y_scale = $opts{'yscalefactor'};
2238 $x_scale = $opts{'scalefactor'} || $y_scale;
2241 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2244 # work out the scaling
2245 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2246 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2247 $opts{ypixels} / $height );
2248 if ($opts{'type'} eq 'min') {
2249 $x_scale = $y_scale = _min($xpix,$ypix);
2251 elsif ($opts{'type'} eq 'max') {
2252 $x_scale = $y_scale = _max($xpix,$ypix);
2254 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2259 $self->_set_error('invalid value for type parameter');
2262 } elsif ($opts{xpixels}) {
2263 $x_scale = $y_scale = $opts{xpixels} / $width;
2265 elsif ($opts{ypixels}) {
2266 $x_scale = $y_scale = $opts{ypixels}/$height;
2268 elsif ($opts{constrain} && ref $opts{constrain}
2269 && $opts{constrain}->can('constrain')) {
2270 # we've been passed an Image::Math::Constrain object or something
2271 # that looks like one
2273 (undef, undef, $scalefactor)
2274 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2275 unless ($scalefactor) {
2276 $self->_set_error('constrain method failed on constrain parameter');
2279 $x_scale = $y_scale = $scalefactor;
2282 my $new_width = int($x_scale * $width + 0.5);
2283 $new_width > 0 or $new_width = 1;
2284 my $new_height = int($y_scale * $height + 0.5);
2285 $new_height > 0 or $new_height = 1;
2287 return ($x_scale, $y_scale, $new_width, $new_height);
2291 # Scale an image to requested size and return the scaled version
2295 my %opts = (qtype=>'normal' ,@_);
2296 my $img = Imager->new();
2297 my $tmp = Imager->new();
2299 unless (defined wantarray) {
2300 my @caller = caller;
2301 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2305 $self->_valid_image("scale")
2308 my ($x_scale, $y_scale, $new_width, $new_height) =
2309 $self->scale_calculate(%opts)
2312 if ($opts{qtype} eq 'normal') {
2313 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2314 if ( !defined($tmp->{IMG}) ) {
2315 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2318 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2319 if ( !defined($img->{IMG}) ) {
2320 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2326 elsif ($opts{'qtype'} eq 'preview') {
2327 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2328 if ( !defined($img->{IMG}) ) {
2329 $self->{ERRSTR}='unable to scale image';
2334 elsif ($opts{'qtype'} eq 'mixing') {
2335 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2336 unless ($img->{IMG}) {
2337 $self->_set_error(Imager->_error_as_msg);
2343 $self->_set_error('invalid value for qtype parameter');
2348 # Scales only along the X axis
2352 my %opts = ( scalefactor=>0.5, @_ );
2354 unless (defined wantarray) {
2355 my @caller = caller;
2356 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2360 $self->_valid_image("scaleX")
2363 my $img = Imager->new();
2365 my $scalefactor = $opts{scalefactor};
2367 if ($opts{pixels}) {
2368 $scalefactor = $opts{pixels} / $self->getwidth();
2371 unless ($self->{IMG}) {
2372 $self->{ERRSTR}='empty input image';
2376 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2378 if ( !defined($img->{IMG}) ) {
2379 $self->{ERRSTR} = 'unable to scale image';
2386 # Scales only along the Y axis
2390 my %opts = ( scalefactor => 0.5, @_ );
2392 unless (defined wantarray) {
2393 my @caller = caller;
2394 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2398 $self->_valid_image("scaleY")
2401 my $img = Imager->new();
2403 my $scalefactor = $opts{scalefactor};
2405 if ($opts{pixels}) {
2406 $scalefactor = $opts{pixels} / $self->getheight();
2409 unless ($self->{IMG}) {
2410 $self->{ERRSTR} = 'empty input image';
2413 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2415 if ( !defined($img->{IMG}) ) {
2416 $self->{ERRSTR} = 'unable to scale image';
2423 # Transform returns a spatial transformation of the input image
2424 # this moves pixels to a new location in the returned image.
2425 # NOTE - should make a utility function to check transforms for
2431 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2433 # print Dumper(\%opts);
2436 $self->_valid_image("transform")
2439 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2443 pop @INC if $INC[-1] eq '.';
2444 eval ("use Affix::Infix2Postfix;");
2448 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2451 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2452 {op=>'-',trans=>'Sub'},
2453 {op=>'*',trans=>'Mult'},
2454 {op=>'/',trans=>'Div'},
2455 {op=>'-','type'=>'unary',trans=>'u-'},
2457 {op=>'func','type'=>'unary'}],
2458 'grouping'=>[qw( \( \) )],
2459 'func'=>[qw( sin cos )],
2464 @xt=$I2P->translate($opts{'xexpr'});
2465 @yt=$I2P->translate($opts{'yexpr'});
2467 $numre=$I2P->{'numre'};
2470 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2471 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2472 @{$opts{'parm'}}=@pt;
2475 # print Dumper(\%opts);
2477 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2478 $self->{ERRSTR}='transform: no xopcodes given.';
2482 @op=@{$opts{'xopcodes'}};
2484 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2485 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2488 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2494 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2495 $self->{ERRSTR}='transform: no yopcodes given.';
2499 @op=@{$opts{'yopcodes'}};
2501 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2502 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2505 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2510 if ( !exists $opts{'parm'}) {
2511 $self->{ERRSTR}='transform: no parameter arg given.';
2515 # print Dumper(\@ropx);
2516 # print Dumper(\@ropy);
2517 # print Dumper(\@ropy);
2519 my $img = Imager->new();
2520 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2521 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2527 my ($opts, @imgs) = @_;
2529 require "Imager/Expr.pm";
2531 $opts->{variables} = [ qw(x y) ];
2532 my ($width, $height) = @{$opts}{qw(width height)};
2535 for my $img (@imgs) {
2536 unless ($img->_valid_image("transform2")) {
2537 Imager->_set_error($img->errstr . " (input image $index)");
2543 $width ||= $imgs[0]->getwidth();
2544 $height ||= $imgs[0]->getheight();
2546 for my $img (@imgs) {
2547 $opts->{constants}{"w$img_num"} = $img->getwidth();
2548 $opts->{constants}{"h$img_num"} = $img->getheight();
2549 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2550 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2555 $opts->{constants}{w} = $width;
2556 $opts->{constants}{cx} = $width/2;
2559 $Imager::ERRSTR = "No width supplied";
2563 $opts->{constants}{h} = $height;
2564 $opts->{constants}{cy} = $height/2;
2567 $Imager::ERRSTR = "No height supplied";
2570 my $code = Imager::Expr->new($opts);
2572 $Imager::ERRSTR = Imager::Expr::error();
2575 my $channels = $opts->{channels} || 3;
2576 unless ($channels >= 1 && $channels <= 4) {
2577 return Imager->_set_error("channels must be an integer between 1 and 4");
2580 my $img = Imager->new();
2581 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2582 $channels, $code->code(),
2583 $code->nregs(), $code->cregs(),
2584 [ map { $_->{IMG} } @imgs ]);
2585 if (!defined $img->{IMG}) {
2586 $Imager::ERRSTR = Imager->_error_as_msg();
2597 $self->_valid_image("rubthrough")
2600 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2601 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2605 %opts = (src_minx => 0,
2607 src_maxx => $opts{src}->getwidth(),
2608 src_maxy => $opts{src}->getheight(),
2612 defined $tx or $tx = $opts{left};
2613 defined $tx or $tx = 0;
2616 defined $ty or $ty = $opts{top};
2617 defined $ty or $ty = 0;
2619 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2620 $opts{src_minx}, $opts{src_miny},
2621 $opts{src_maxx}, $opts{src_maxy})) {
2622 $self->_set_error($self->_error_as_msg());
2639 $self->_valid_image("compose")
2642 unless ($opts{src}) {
2643 $self->_set_error("compose: src parameter missing");
2647 unless ($opts{src}->_valid_image("compose")) {
2648 $self->_set_error($opts{src}->errstr . " (for src)");
2651 my $src = $opts{src};
2653 my $left = $opts{left};
2654 defined $left or $left = $opts{tx};
2655 defined $left or $left = 0;
2657 my $top = $opts{top};
2658 defined $top or $top = $opts{ty};
2659 defined $top or $top = 0;
2661 my $src_left = $opts{src_left};
2662 defined $src_left or $src_left = $opts{src_minx};
2663 defined $src_left or $src_left = 0;
2665 my $src_top = $opts{src_top};
2666 defined $src_top or $src_top = $opts{src_miny};
2667 defined $src_top or $src_top = 0;
2669 my $width = $opts{width};
2670 if (!defined $width && defined $opts{src_maxx}) {
2671 $width = $opts{src_maxx} - $src_left;
2673 defined $width or $width = $src->getwidth() - $src_left;
2675 my $height = $opts{height};
2676 if (!defined $height && defined $opts{src_maxy}) {
2677 $height = $opts{src_maxy} - $src_top;
2679 defined $height or $height = $src->getheight() - $src_top;
2681 my $combine = $self->_combine($opts{combine}, 'normal');
2684 unless ($opts{mask}->_valid_image("compose")) {
2685 $self->_set_error($opts{mask}->errstr . " (for mask)");
2689 my $mask_left = $opts{mask_left};
2690 defined $mask_left or $mask_left = $opts{mask_minx};
2691 defined $mask_left or $mask_left = 0;
2693 my $mask_top = $opts{mask_top};
2694 defined $mask_top or $mask_top = $opts{mask_miny};
2695 defined $mask_top or $mask_top = 0;
2697 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2698 $left, $top, $src_left, $src_top,
2699 $mask_left, $mask_top, $width, $height,
2700 $combine, $opts{opacity})) {
2701 $self->_set_error(Imager->_error_as_msg);
2706 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2707 $width, $height, $combine, $opts{opacity})) {
2708 $self->_set_error(Imager->_error_as_msg);
2720 $self->_valid_image("flip")
2723 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2725 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2726 $dir = $xlate{$opts{'dir'}};
2727 return $self if i_flipxy($self->{IMG}, $dir);
2735 unless (defined wantarray) {
2736 my @caller = caller;
2737 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2741 $self->_valid_image("rotate")
2744 if (defined $opts{right}) {
2745 my $degrees = $opts{right};
2747 $degrees += 360 * int(((-$degrees)+360)/360);
2749 $degrees = $degrees % 360;
2750 if ($degrees == 0) {
2751 return $self->copy();
2753 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2754 my $result = Imager->new();
2755 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2759 $self->{ERRSTR} = $self->_error_as_msg();
2764 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2768 elsif (defined $opts{radians} || defined $opts{degrees}) {
2769 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2771 my $back = $opts{back};
2772 my $result = Imager->new;
2774 $back = _color($back);
2776 $self->_set_error(Imager->errstr);
2780 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2783 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2785 if ($result->{IMG}) {
2789 $self->{ERRSTR} = $self->_error_as_msg();
2794 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2799 sub matrix_transform {
2803 $self->_valid_image("matrix_transform")
2806 unless (defined wantarray) {
2807 my @caller = caller;
2808 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2812 if ($opts{matrix}) {
2813 my $xsize = $opts{xsize} || $self->getwidth;
2814 my $ysize = $opts{ysize} || $self->getheight;
2816 my $result = Imager->new;
2818 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2819 $opts{matrix}, $opts{back})
2823 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2831 $self->{ERRSTR} = "matrix parameter required";
2837 *yatf = \&matrix_transform;
2839 # These two are supported for legacy code only
2842 return Imager::Color->new(@_);
2846 return Imager::Color::set(@_);
2849 # Draws a box between the specified corner points.
2852 my $raw = $self->{IMG};
2854 $self->_valid_image("box")
2859 my ($xmin, $ymin, $xmax, $ymax);
2860 if (exists $opts{'box'}) {
2861 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2862 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2863 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2864 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2867 defined($xmin = $opts{xmin}) or $xmin = 0;
2868 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2869 defined($ymin = $opts{ymin}) or $ymin = 0;
2870 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2873 if ($opts{filled}) {
2874 my $color = $opts{'color'};
2876 if (defined $color) {
2877 unless (_is_color_object($color)) {
2878 $color = _color($color);
2880 $self->{ERRSTR} = $Imager::ERRSTR;
2886 $color = i_color_new(255,255,255,255);
2889 if ($color->isa("Imager::Color")) {
2890 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2893 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2896 elsif ($opts{fill}) {
2897 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2898 # assume it's a hash ref
2899 require 'Imager/Fill.pm';
2900 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2901 $self->{ERRSTR} = $Imager::ERRSTR;
2905 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2908 my $color = $opts{'color'};
2909 if (defined $color) {
2910 unless (_is_color_object($color)) {
2911 $color = _color($color);
2913 $self->{ERRSTR} = $Imager::ERRSTR;
2919 $color = i_color_new(255, 255, 255, 255);
2922 $self->{ERRSTR} = $Imager::ERRSTR;
2925 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2934 $self->_valid_image("arc")
2937 my $dflcl= [ 255, 255, 255, 255];
2942 'r'=>_min($self->getwidth(),$self->getheight())/3,
2943 'x'=>$self->getwidth()/2,
2944 'y'=>$self->getheight()/2,
2951 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2952 # assume it's a hash ref
2953 require 'Imager/Fill.pm';
2954 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2955 $self->{ERRSTR} = $Imager::ERRSTR;
2959 if ($opts{d1} == 0 && $opts{d2} == 361) {
2960 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2964 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2965 $opts{'d2'}, $opts{fill}{fill});
2968 elsif ($opts{filled}) {
2969 my $color = _color($opts{'color'});
2971 $self->{ERRSTR} = $Imager::ERRSTR;
2974 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2975 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2979 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2980 $opts{'d1'}, $opts{'d2'}, $color);
2984 my $color = _color($opts{'color'});
2985 if ($opts{d2} - $opts{d1} >= 360) {
2986 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2989 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2995 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2996 # assume it's a hash ref
2997 require 'Imager/Fill.pm';
2998 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2999 $self->{ERRSTR} = $Imager::ERRSTR;
3003 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
3004 $opts{'d2'}, $opts{fill}{fill});
3007 my $color = _color($opts{'color'});
3009 $self->{ERRSTR} = $Imager::ERRSTR;
3012 if ($opts{filled}) {
3013 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
3014 $opts{'d1'}, $opts{'d2'}, $color);
3017 if ($opts{d1} == 0 && $opts{d2} == 361) {
3018 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
3021 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
3027 $self->_set_error($self->_error_as_msg);
3034 # Draws a line from one point to the other
3035 # the endpoint is set if the endp parameter is set which it is by default.
3036 # to turn of the endpoint being set use endp=>0 when calling line.
3040 my $dflcl=i_color_new(0,0,0,0);
3041 my %opts=(color=>$dflcl,
3045 $self->_valid_image("line")
3048 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
3049 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
3051 my $color = _color($opts{'color'});
3053 $self->{ERRSTR} = $Imager::ERRSTR;
3057 $opts{antialias} = $opts{aa} if defined $opts{aa};
3058 if ($opts{antialias}) {
3059 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3060 $color, $opts{endp});
3062 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3063 $color, $opts{endp});
3068 # Draws a line between an ordered set of points - It more or less just transforms this
3069 # into a list of lines.
3073 my ($pt,$ls,@points);
3074 my $dflcl=i_color_new(0,0,0,0);
3075 my %opts=(color=>$dflcl,@_);
3077 $self->_valid_image("polyline")
3080 if (exists($opts{points})) { @points=@{$opts{points}}; }
3081 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3082 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3085 # print Dumper(\@points);
3087 my $color = _color($opts{'color'});
3089 $self->{ERRSTR} = $Imager::ERRSTR;
3092 $opts{antialias} = $opts{aa} if defined $opts{aa};
3093 if ($opts{antialias}) {
3096 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3103 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3113 my ($pt,$ls,@points);
3114 my $dflcl = i_color_new(0,0,0,0);
3115 my %opts = (color=>$dflcl, @_);
3117 $self->_valid_image("polygon")
3120 if (exists($opts{points})) {
3121 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3122 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3125 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3126 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3129 my $mode = _first($opts{mode}, 0);
3131 if ($opts{'fill'}) {
3132 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3133 # assume it's a hash ref
3134 require 'Imager/Fill.pm';
3135 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3136 $self->{ERRSTR} = $Imager::ERRSTR;
3140 unless (i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3141 $mode, $opts{'fill'}{'fill'})) {
3142 return $self->_set_error($self->_error_as_msg);
3146 my $color = _color($opts{'color'});
3148 $self->{ERRSTR} = $Imager::ERRSTR;
3151 unless (i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color)) {
3152 return $self->_set_error($self->_error_as_msg);
3160 my ($self, %opts) = @_;
3162 $self->_valid_image("polypolygon")
3165 my $points = $opts{points};
3167 or return $self->_set_error("polypolygon: missing required points");
3169 my $mode = _first($opts{mode}, "evenodd");
3171 if ($opts{filled}) {
3172 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3173 or return $self->_set_error($Imager::ERRSTR);
3175 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3176 or return $self->_set_error($self->_error_as_msg);
3178 elsif ($opts{fill}) {
3179 my $fill = $opts{fill};
3180 $self->_valid_fill($fill, "polypolygon")
3183 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3184 or return $self->_set_error($self->_error_as_msg);
3187 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3188 or return $self->_set_error($Imager::ERRSTR);
3190 my $rimg = $self->{IMG};
3192 if (_first($opts{aa}, 1)) {
3193 for my $poly (@$points) {
3194 my $xp = $poly->[0];
3195 my $yp = $poly->[1];
3196 for my $i (0 .. $#$xp - 1) {
3197 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3200 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3205 for my $poly (@$points) {
3206 my $xp = $poly->[0];
3207 my $yp = $poly->[1];
3208 for my $i (0 .. $#$xp - 1) {
3209 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3212 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3221 # this the multipoint bezier curve
3222 # this is here more for testing that actual usage since
3223 # this is not a good algorithm. Usually the curve would be
3224 # broken into smaller segments and each done individually.
3228 my ($pt,$ls,@points);
3229 my $dflcl=i_color_new(0,0,0,0);
3230 my %opts=(color=>$dflcl,@_);
3232 $self->_valid_image("polybezier")
3235 if (exists $opts{points}) {
3236 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3237 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3240 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3241 $self->{ERRSTR}='Missing or invalid points.';
3245 my $color = _color($opts{'color'});
3247 $self->{ERRSTR} = $Imager::ERRSTR;
3250 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3256 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3259 $self->_valid_image("flood_fill")
3262 unless (exists $opts{'x'} && exists $opts{'y'}) {
3263 $self->{ERRSTR} = "missing seed x and y parameters";
3267 if ($opts{border}) {
3268 my $border = _color($opts{border});
3270 $self->_set_error($Imager::ERRSTR);
3274 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3275 # assume it's a hash ref
3276 require Imager::Fill;
3277 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3278 $self->{ERRSTR} = $Imager::ERRSTR;
3282 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3283 $opts{fill}{fill}, $border);
3286 my $color = _color($opts{'color'});
3288 $self->{ERRSTR} = $Imager::ERRSTR;
3291 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3298 $self->{ERRSTR} = $self->_error_as_msg();
3304 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3305 # assume it's a hash ref
3306 require 'Imager/Fill.pm';
3307 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3308 $self->{ERRSTR} = $Imager::ERRSTR;
3312 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3315 my $color = _color($opts{'color'});
3317 $self->{ERRSTR} = $Imager::ERRSTR;
3320 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3326 $self->{ERRSTR} = $self->_error_as_msg();
3333 my ($self, %opts) = @_;
3335 $self->_valid_image("setpixel")
3338 my $color = $opts{color};
3339 unless (defined $color) {
3340 $color = $self->{fg};
3341 defined $color or $color = NC(255, 255, 255);
3344 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3345 unless ($color = _color($color, 'setpixel')) {
3346 $self->_set_error("setpixel: " . Imager->errstr);
3351 unless (exists $opts{'x'} && exists $opts{'y'}) {
3352 $self->_set_error('setpixel: missing x or y parameter');
3358 if (ref $x || ref $y) {
3359 $x = ref $x ? $x : [ $x ];
3360 $y = ref $y ? $y : [ $y ];
3362 $self->_set_error("setpixel: x is a reference to an empty array");
3366 $self->_set_error("setpixel: y is a reference to an empty array");
3370 # make both the same length, replicating the last element
3372 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3375 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3379 if ($color->isa('Imager::Color')) {
3380 for my $i (0..$#$x) {
3381 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3386 for my $i (0..$#$x) {
3387 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3395 if ($color->isa('Imager::Color')) {
3396 i_ppix($self->{IMG}, $x, $y, $color)
3397 and return "0 but true";
3400 i_ppixf($self->{IMG}, $x, $y, $color)
3401 and return "0 but true";
3411 my %opts = ( "type"=>'8bit', @_);
3413 $self->_valid_image("getpixel")
3416 unless (exists $opts{'x'} && exists $opts{'y'}) {
3417 $self->_set_error('getpixel: missing x or y parameter');
3423 my $type = $opts{'type'};
3424 if (ref $x || ref $y) {
3425 $x = ref $x ? $x : [ $x ];
3426 $y = ref $y ? $y : [ $y ];
3428 $self->_set_error("getpixel: x is a reference to an empty array");
3432 $self->_set_error("getpixel: y is a reference to an empty array");
3436 # make both the same length, replicating the last element
3438 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3441 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3445 if ($type eq '8bit') {
3446 for my $i (0..$#$x) {
3447 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3450 elsif ($type eq 'float' || $type eq 'double') {
3451 for my $i (0..$#$x) {
3452 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3456 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3459 return wantarray ? @result : \@result;
3462 if ($type eq '8bit') {
3463 return i_get_pixel($self->{IMG}, $x, $y);
3465 elsif ($type eq 'float' || $type eq 'double') {
3466 return i_gpixf($self->{IMG}, $x, $y);
3469 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3477 my %opts = ( type => '8bit', x=>0, @_);
3479 $self->_valid_image("getscanline")
3482 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3484 unless (defined $opts{'y'}) {
3485 $self->_set_error("missing y parameter");
3489 if ($opts{type} eq '8bit') {
3490 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3493 elsif ($opts{type} eq 'float') {
3494 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3497 elsif ($opts{type} eq 'index') {
3498 unless (i_img_type($self->{IMG})) {
3499 $self->_set_error("type => index only valid on paletted images");
3502 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3506 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3513 my %opts = ( x=>0, @_);
3515 $self->_valid_image("setscanline")
3518 unless (defined $opts{'y'}) {
3519 $self->_set_error("missing y parameter");
3524 if (ref $opts{pixels} && @{$opts{pixels}}) {
3525 # try to guess the type
3526 if ($opts{pixels}[0]->isa('Imager::Color')) {
3527 $opts{type} = '8bit';
3529 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3530 $opts{type} = 'float';
3533 $self->_set_error("missing type parameter and could not guess from pixels");
3539 $opts{type} = '8bit';
3543 if ($opts{type} eq '8bit') {
3544 if (ref $opts{pixels}) {
3545 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3548 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3551 elsif ($opts{type} eq 'float') {
3552 if (ref $opts{pixels}) {
3553 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3556 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3559 elsif ($opts{type} eq 'index') {
3560 if (ref $opts{pixels}) {
3561 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3564 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3568 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3575 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3577 $self->_valid_image("getsamples")
3580 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3582 unless (defined $opts{'y'}) {
3583 $self->_set_error("missing y parameter");
3587 if ($opts{target}) {
3588 my $target = $opts{target};
3589 my $offset = $opts{offset};
3590 if ($opts{type} eq '8bit') {
3591 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3592 $opts{y}, $opts{channels})
3594 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3595 return scalar(@samples);
3597 elsif ($opts{type} eq 'float') {
3598 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3599 $opts{y}, $opts{channels});
3600 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3601 return scalar(@samples);
3603 elsif ($opts{type} =~ /^(\d+)bit$/) {
3607 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3608 $opts{y}, $bits, $target,
3609 $offset, $opts{channels});
3610 unless (defined $count) {
3611 $self->_set_error(Imager->_error_as_msg);
3618 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3623 if ($opts{type} eq '8bit') {
3624 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3625 $opts{y}, $opts{channels});
3627 elsif ($opts{type} eq 'float') {
3628 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3629 $opts{y}, $opts{channels});
3631 elsif ($opts{type} =~ /^(\d+)bit$/) {
3635 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3636 $opts{y}, $bits, \@data, 0, $opts{channels})
3641 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3650 $self->_valid_image("setsamples")
3653 my %opts = ( x => 0, offset => 0 );
3655 # avoid duplicating the data parameter, it may be a large scalar
3657 while ($i < @_ -1) {
3658 if ($_[$i] eq 'data') {
3662 $opts{$_[$i]} = $_[$i+1];
3668 unless(defined $data_index) {
3669 $self->_set_error('setsamples: data parameter missing');
3672 unless (defined $_[$data_index]) {
3673 $self->_set_error('setsamples: data parameter not defined');
3677 my $type = $opts{type};
3678 defined $type or $type = '8bit';
3680 my $width = defined $opts{width} ? $opts{width}
3681 : $self->getwidth() - $opts{x};
3684 if ($type eq '8bit') {
3685 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3686 $_[$data_index], $opts{offset}, $width);
3688 elsif ($type eq 'float') {
3689 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3690 $_[$data_index], $opts{offset}, $width);
3692 elsif ($type =~ /^([0-9]+)bit$/) {
3695 unless (ref $_[$data_index]) {
3696 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3700 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3701 $opts{channels}, $_[$data_index], $opts{offset},
3705 $self->_set_error('setsamples: type parameter invalid');
3709 unless (defined $count) {
3710 $self->_set_error(Imager->_error_as_msg);
3717 # make an identity matrix of the given size
3721 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3722 for my $c (0 .. ($size-1)) {
3723 $matrix->[$c][$c] = 1;
3728 # general function to convert an image
3730 my ($self, %opts) = @_;
3733 $self->_valid_image("convert")
3736 unless (defined wantarray) {
3737 my @caller = caller;
3738 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3742 # the user can either specify a matrix or preset
3743 # the matrix overrides the preset
3744 if (!exists($opts{matrix})) {
3745 unless (exists($opts{preset})) {
3746 $self->{ERRSTR} = "convert() needs a matrix or preset";
3750 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3751 # convert to greyscale, keeping the alpha channel if any
3752 if ($self->getchannels == 3) {
3753 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3755 elsif ($self->getchannels == 4) {
3756 # preserve the alpha channel
3757 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3762 $matrix = _identity($self->getchannels);
3765 elsif ($opts{preset} eq 'noalpha') {
3766 # strip the alpha channel
3767 if ($self->getchannels == 2 or $self->getchannels == 4) {
3768 $matrix = _identity($self->getchannels);
3769 pop(@$matrix); # lose the alpha entry
3772 $matrix = _identity($self->getchannels);
3775 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3777 $matrix = [ [ 1 ] ];
3779 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3780 $matrix = [ [ 0, 1 ] ];
3782 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3783 $matrix = [ [ 0, 0, 1 ] ];
3785 elsif ($opts{preset} eq 'alpha') {
3786 if ($self->getchannels == 2 or $self->getchannels == 4) {
3787 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3790 # the alpha is just 1 <shrug>
3791 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3794 elsif ($opts{preset} eq 'rgb') {
3795 if ($self->getchannels == 1) {
3796 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3798 elsif ($self->getchannels == 2) {
3799 # preserve the alpha channel
3800 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3803 $matrix = _identity($self->getchannels);
3806 elsif ($opts{preset} eq 'addalpha') {
3807 if ($self->getchannels == 1) {
3808 $matrix = _identity(2);
3810 elsif ($self->getchannels == 3) {
3811 $matrix = _identity(4);
3814 $matrix = _identity($self->getchannels);
3818 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3824 $matrix = $opts{matrix};
3827 my $new = Imager->new;
3828 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3829 unless ($new->{IMG}) {
3830 # most likely a bad matrix
3831 i_push_error(0, "convert");
3832 $self->{ERRSTR} = _error_as_msg();
3838 # combine channels from multiple input images, a class method
3840 my ($class, %opts) = @_;
3842 my $src = delete $opts{src};
3844 $class->_set_error("src parameter missing");
3849 for my $img (@$src) {
3850 unless (eval { $img->isa("Imager") }) {
3851 $class->_set_error("src must contain image objects");
3854 unless ($img->_valid_image("combine")) {
3855 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3858 push @imgs, $img->{IMG};
3861 if (my $channels = delete $opts{channels}) {
3862 $result = i_combine(\@imgs, $channels);
3865 $result = i_combine(\@imgs);
3868 $class->_set_error($class->_error_as_msg);
3872 my $img = $class->new;
3873 $img->{IMG} = $result;
3879 # general function to map an image through lookup tables
3882 my ($self, %opts) = @_;
3883 my @chlist = qw( red green blue alpha );
3885 $self->_valid_image("map")
3888 if (!exists($opts{'maps'})) {
3889 # make maps from channel maps
3891 for $chnum (0..$#chlist) {
3892 if (exists $opts{$chlist[$chnum]}) {
3893 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3894 } elsif (exists $opts{'all'}) {
3895 $opts{'maps'}[$chnum] = $opts{'all'};
3899 if ($opts{'maps'} and $self->{IMG}) {
3900 i_map($self->{IMG}, $opts{'maps'} );
3906 my ($self, %opts) = @_;
3908 $self->_valid_image("difference")
3911 defined $opts{mindist} or $opts{mindist} = 0;
3913 defined $opts{other}
3914 or return $self->_set_error("No 'other' parameter supplied");
3915 unless ($opts{other}->_valid_image("difference")) {
3916 $self->_set_error($opts{other}->errstr . " (other image)");
3920 my $result = Imager->new;
3921 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3923 or return $self->_set_error($self->_error_as_msg());
3928 # destructive border - image is shrunk by one pixel all around
3931 my ($self,%opts)=@_;
3932 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3933 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3937 # Get the width of an image
3942 $self->_valid_image("getwidth")
3945 return i_img_get_width($self->{IMG});
3948 # Get the height of an image
3953 $self->_valid_image("getheight")
3956 return i_img_get_height($self->{IMG});
3959 # Get number of channels in an image
3964 $self->_valid_image("getchannels")
3967 return i_img_getchannels($self->{IMG});
3970 my @model_names = qw(unknown gray graya rgb rgba);
3973 my ($self, %opts) = @_;
3975 $self->_valid_image("colormodel")
3978 my $model = i_img_color_model($self->{IMG});
3980 return $opts{numeric} ? $model : $model_names[$model];
3986 $self->_valid_image("colorchannels")
3989 return i_img_color_channels($self->{IMG});
3995 $self->_valid_image("alphachannel")
3998 return scalar(i_img_alpha_channel($self->{IMG}));
4006 $self->_valid_image("getmask")
4009 return i_img_getmask($self->{IMG});
4018 $self->_valid_image("setmask")
4021 unless (defined $opts{mask}) {
4022 $self->_set_error("mask parameter required");
4026 i_img_setmask( $self->{IMG} , $opts{mask} );
4031 # Get number of colors in an image
4035 my %opts=('maxcolors'=>2**30,@_);
4037 $self->_valid_image("getcolorcount")
4040 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
4041 return ($rc==-1? undef : $rc);
4044 # Returns a reference to a hash. The keys are colour named (packed) and the
4045 # values are the number of pixels in this colour.
4046 sub getcolorusagehash {
4049 $self->_valid_image("getcolorusagehash")
4052 my %opts = ( maxcolors => 2**30, @_ );
4053 my $max_colors = $opts{maxcolors};
4054 unless (defined $max_colors && $max_colors > 0) {
4055 $self->_set_error('maxcolors must be a positive integer');
4059 my $channels= $self->getchannels;
4060 # We don't want to look at the alpha channel, because some gifs using it
4061 # doesn't define it for every colour (but only for some)
4062 $channels -= 1 if $channels == 2 or $channels == 4;
4064 my $height = $self->getheight;
4065 for my $y (0 .. $height - 1) {
4066 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4067 while (length $colors) {
4068 $color_use{ substr($colors, 0, $channels, '') }++;
4070 keys %color_use > $max_colors
4076 # This will return a ordered array of the colour usage. Kind of the sorted
4077 # version of the values of the hash returned by getcolorusagehash.
4078 # You might want to add safety checks and change the names, etc...
4082 $self->_valid_image("getcolorusage")
4085 my %opts = ( maxcolors => 2**30, @_ );
4086 my $max_colors = $opts{maxcolors};
4087 unless (defined $max_colors && $max_colors > 0) {
4088 $self->_set_error('maxcolors must be a positive integer');
4092 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4095 # draw string to an image
4100 $self->_valid_image("string")
4103 my %input=('x'=>0, 'y'=>0, @_);
4104 defined($input{string}) or $input{string} = $input{text};
4106 unless(defined $input{string}) {
4107 $self->{ERRSTR}="missing required parameter 'string'";
4111 unless($input{font}) {
4112 $self->{ERRSTR}="missing required parameter 'font'";
4116 unless ($input{font}->draw(image=>$self, %input)) {
4128 $self->_valid_image("align_string")
4137 my %input=('x'=>0, 'y'=>0, @_);
4138 defined $input{string}
4139 or $input{string} = $input{text};
4141 unless(exists $input{string}) {
4142 $self->_set_error("missing required parameter 'string'");
4146 unless($input{font}) {
4147 $self->_set_error("missing required parameter 'font'");
4152 unless (@result = $input{font}->align(image=>$img, %input)) {
4156 return wantarray ? @result : $result[0];
4159 my @file_limit_names = qw/width height bytes/;
4161 sub set_file_limits {
4168 @values{@file_limit_names} = (0) x @file_limit_names;
4171 @values{@file_limit_names} = i_get_image_file_limits();
4174 for my $key (keys %values) {
4175 defined $opts{$key} and $values{$key} = $opts{$key};
4178 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4181 sub get_file_limits {
4182 i_get_image_file_limits();
4185 my @check_args = qw(width height channels sample_size);
4187 sub check_file_limits {
4197 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4198 $opts{sample_size} = length(pack("d", 0));
4201 for my $name (@check_args) {
4202 unless (defined $opts{$name}) {
4203 $class->_set_error("check_file_limits: $name must be defined");
4206 unless ($opts{$name} == int($opts{$name})) {
4207 $class->_set_error("check_file_limits: $name must be a positive integer");
4212 my $result = i_int_check_image_file_limits(@opts{@check_args});
4214 $class->_set_error($class->_error_as_msg());
4220 # Shortcuts that can be exported
4222 sub newcolor { Imager::Color->new(@_); }
4223 sub newfont { Imager::Font->new(@_); }
4225 require Imager::Color::Float;
4226 return Imager::Color::Float->new(@_);
4229 *NC=*newcolour=*newcolor;
4236 #### Utility routines
4239 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4243 my ($self, $msg) = @_;
4246 $self->{ERRSTR} = $msg;
4254 # Default guess for the type of an image from extension
4256 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps webp xwd xpm dng ras);
4260 ( map { $_ => $_ } @simple_types ),
4266 pnm => "pnm", # technically wrong, but historically it works in Imager
4279 sub def_guess_type {
4282 my ($ext) = $name =~ /\.([^.]+)$/
4285 my $type = $ext_types{$ext}
4291 sub add_type_extensions {
4292 my ($class, $type, @exts) = @_;
4294 for my $ext (@exts) {
4295 exists $ext_types{lc $ext} or $ext_types{lc $ext} = lc $type;
4301 return @combine_types;
4304 # get the minimum of a list
4308 for(@_) { if ($_<$mx) { $mx=$_; }}
4312 # get the maximum of a list
4316 for(@_) { if ($_>$mx) { $mx=$_; }}
4320 # string stuff for iptc headers
4324 $str = substr($str,3);
4325 $str =~ s/[\n\r]//g;
4332 # A little hack to parse iptc headers.
4337 my($caption,$photogr,$headln,$credit);
4339 my $str=$self->{IPTCRAW};
4344 @ar=split(/8BIM/,$str);
4349 @sar=split(/\034\002/);
4350 foreach $item (@sar) {
4351 if ($item =~ m/^x/) {
4352 $caption = _clean($item);
4355 if ($item =~ m/^P/) {
4356 $photogr = _clean($item);
4359 if ($item =~ m/^i/) {
4360 $headln = _clean($item);
4363 if ($item =~ m/^n/) {
4364 $credit = _clean($item);
4370 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4374 # Inline added a new argument at the beginning
4378 or die "Only C language supported";
4380 require Imager::ExtUtils;
4381 return Imager::ExtUtils->inline_config;
4384 # threads shouldn't try to close raw Imager objects
4385 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4388 # this serves two purposes:
4389 # - a class method to load the file support modules included with Imager
4390 # (or were included, once the library dependent modules are split out)
4391 # - something for Module::ScanDeps to analyze
4392 # https://rt.cpan.org/Ticket/Display.html?id=6566
4395 pop @INC if $INC[-1] eq '.';
4396 eval { require Imager::File::GIF };
4397 eval { require Imager::File::JPEG };
4398 eval { require Imager::File::PNG };
4399 eval { require Imager::File::SGI };
4400 eval { require Imager::File::TIFF };
4401 eval { require Imager::File::ICO };
4402 eval { require Imager::Font::W32 };
4403 eval { require Imager::Font::FT2 };
4404 eval { require Imager::Font::T1 };
4405 eval { require Imager::Color::Table };
4414 my ($class, $fh) = @_;
4417 return $class->new_cb
4422 return print $fh $_[0];
4426 my $count = CORE::read $fh, $tmp, $_[1];
4434 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4435 unless (CORE::seek $fh, $_[0], $_[1]) {
4446 return $class->_new_perlio($fh);
4450 # backward compatibility for %formats
4451 package Imager::FORMATS;
4453 use constant IX_FORMATS => 0;
4454 use constant IX_LIST => 1;
4455 use constant IX_INDEX => 2;
4456 use constant IX_CLASSES => 3;
4459 my ($class, $formats, $classes) = @_;
4461 return bless [ $formats, [ ], 0, $classes ], $class;
4465 my ($self, $key) = @_;
4467 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4470 my $loaded = Imager::_load_file($file, \$error);
4475 if ($error =~ /^Can't locate /) {
4476 $error = "Can't locate $file";
4478 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4481 $self->[IX_FORMATS]{$key} = $value;
4487 my ($self, $key) = @_;
4489 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4491 $self->[IX_CLASSES]{$key} or return undef;
4493 return $self->_check($key);
4497 die "%Imager::formats is not user monifiable";
4501 die "%Imager::formats is not user monifiable";
4505 die "%Imager::formats is not user monifiable";
4509 my ($self, $key) = @_;
4511 if (exists $self->[IX_FORMATS]{$key}) {
4512 my $value = $self->[IX_FORMATS]{$key}
4517 $self->_check($key) or return 1==0;
4525 unless (@{$self->[IX_LIST]}) {
4527 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4528 keys %{$self->[IX_FORMATS]};
4530 for my $key (keys %{$self->[IX_CLASSES]}) {
4531 $self->[IX_FORMATS]{$key} and next;
4533 and push @{$self->[IX_LIST]}, $key;
4537 @{$self->[IX_LIST]} or return;
4538 $self->[IX_INDEX] = 1;
4539 return $self->[IX_LIST][0];
4545 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4548 return $self->[IX_LIST][$self->[IX_INDEX]++];
4554 return scalar @{$self->[IX_LIST]};
4559 # Below is the stub of documentation for your module. You better edit it!
4563 Imager - Perl extension for Generating 24 bit Images
4573 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4578 # see Imager::Files for information on the read() method
4579 my $img = Imager->new(file=>$file)
4580 or die Imager->errstr();
4582 $file =~ s/\.[^.]*$//;
4584 # Create smaller version
4585 # documented in Imager::Transformations
4586 my $thumb = $img->scale(scalefactor=>.3);
4588 # Autostretch individual channels
4589 $thumb->filter(type=>'autolevels');
4591 # try to save in one of these formats
4594 for $format ( qw( png gif jpeg tiff ppm ) ) {
4595 # Check if given format is supported
4596 if ($Imager::formats{$format}) {
4597 $file.="_low.$format";
4598 print "Storing image as: $file\n";
4599 # documented in Imager::Files
4600 $thumb->write(file=>$file) or
4608 Imager is a module for creating and altering images. It can read and
4609 write various image formats, draw primitive shapes like lines,and
4610 polygons, blend multiple images together in various ways, scale, crop,
4611 render text and more.
4613 =head2 Overview of documentation
4619 Imager - This document - Synopsis, Example, Table of Contents and
4624 L<Imager::Install> - installation notes for Imager.
4628 L<Imager::Tutorial> - a brief introduction to Imager.
4632 L<Imager::Cookbook> - how to do various things with Imager.
4636 L<Imager::ImageTypes> - Basics of constructing image objects with
4637 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4638 8/16/double bits/channel, color maps, channel masks, image tags, color
4639 quantization. Also discusses basic image information methods.
4643 L<Imager::Files> - IO interaction, reading/writing images, format
4648 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4653 L<Imager::Color> - Color specification.
4657 L<Imager::Fill> - Fill pattern specification.
4661 L<Imager::Font> - General font rendering, bounding boxes and font
4666 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4667 blending, pasting, convert and map.
4671 L<Imager::Engines> - Programmable transformations through
4672 C<transform()>, C<transform2()> and C<matrix_transform()>.
4676 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4681 L<Imager::Expr> - Expressions for evaluation engine used by
4686 L<Imager::Matrix2d> - Helper class for affine transformations.
4690 L<Imager::Fountain> - Helper for making gradient profiles.
4694 L<Imager::IO> - Imager I/O abstraction.
4698 L<Imager::API> - using Imager's C API
4702 L<Imager::APIRef> - API function reference
4706 L<Imager::Inline> - using Imager's C API from Inline::C
4710 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4714 L<Imager::Security> - brief security notes.
4718 L<Imager::Threads> - brief information on working with threads.
4722 =head2 Basic Overview
4724 An Image object is created with C<$img = Imager-E<gt>new()>.
4727 $img=Imager->new(); # create empty image
4728 $img->read(file=>'lena.png',type=>'png') or # read image from file
4729 die $img->errstr(); # give an explanation
4730 # if something failed
4732 or if you want to create an empty image:
4734 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4736 This example creates a completely black image of width 400 and height
4739 =head1 ERROR HANDLING
4741 In general a method will return false when it fails, if it does use
4742 the C<errstr()> method to find out why:
4748 Returns the last error message in that context.
4750 If the last error you received was from calling an object method, such
4751 as read, call errstr() as an object method to find out why:
4753 my $image = Imager->new;
4754 $image->read(file => 'somefile.gif')
4755 or die $image->errstr;
4757 If it was a class method then call errstr() as a class method:
4759 my @imgs = Imager->read_multi(file => 'somefile.gif')
4760 or die Imager->errstr;
4762 Note that in some cases object methods are implemented in terms of
4763 class methods so a failing object method may set both.
4767 The C<Imager-E<gt>new> method is described in detail in
4768 L<Imager::ImageTypes>.
4772 Where to find information on methods for Imager class objects.
4774 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4777 add_file_magic() - L<Imager::Files/add_file_magic()> - add magic to
4778 Imager's file type detector.
4780 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4782 add_type_extensions() - L<Imager::Files/add_file_magic()> - add magic
4783 for new image file types.
4785 L<Imager::Files/add_type_extensions($type, $ext, ...)> - add extensions for
4786 new image file types.
4788 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4791 alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
4792 channel index of the alpha channel (if any).
4794 arc() - L<Imager::Draw/arc()> - draw a filled arc
4796 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4799 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4801 check_file_limits() - L<Imager::Files/check_file_limits()>
4803 circle() - L<Imager::Draw/circle()> - draw a filled circle
4805 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4808 colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
4809 of channels used for color.
4811 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4812 colors in an image's palette (paletted images only)
4814 colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
4817 combine() - L<Imager::Transformations/combine()> - combine channels
4818 from one or more images.
4820 combines() - L<Imager::Draw/combines()> - return a list of the
4821 different combine type keywords
4823 compose() - L<Imager::Transformations/compose()> - compose one image
4826 convert() - L<Imager::Transformations/convert()> - transform the color
4829 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4832 crop() - L<Imager::Transformations/crop()> - extract part of an image
4834 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4835 used to guess the output file format based on the output file name
4837 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4839 difference() - L<Imager::Filters/difference()> - produce a difference
4840 images from two input images.
4842 errstr() - L</errstr()> - the error from the last failed operation.
4844 filter() - L<Imager::Filters/filter()> - image filtering
4846 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4847 palette, if it has one
4849 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4852 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4855 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4856 samples per pixel for an image
4858 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4859 different colors used by an image (works for direct color images)
4861 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4862 palette, if it has one
4864 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4866 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4868 get_file_limits() - L<Imager::Files/get_file_limits()>
4870 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4873 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4875 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4878 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4879 row or partial row of pixels.
4881 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4882 row or partial row of pixels.
4884 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4887 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4890 init() - L<Imager::ImageTypes/init()>
4892 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4893 image write functions should write the image in their bilevel (blank
4894 and white, no gray levels) format
4896 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4899 line() - L<Imager::Draw/line()> - draw an interval
4901 load_plugin() - L<Imager::Filters/load_plugin()>
4903 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4906 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4907 color palette from one or more input images.
4909 map() - L<Imager::Transformations/map()> - remap color
4912 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4914 matrix_transform() - L<Imager::Engines/matrix_transform()>
4916 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4918 NC() - L<Imager::Handy/NC()>
4920 NCF() - L<Imager::Handy/NCF()>
4922 new() - L<Imager::ImageTypes/new()>
4924 newcolor() - L<Imager::Handy/newcolor()>
4926 newcolour() - L<Imager::Handy/newcolour()>
4928 newfont() - L<Imager::Handy/newfont()>
4930 NF() - L<Imager::Handy/NF()>
4932 open() - L<Imager::Files/read()> - an alias for read()
4934 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4938 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4941 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4944 polygon() - L<Imager::Draw/polygon()>
4946 polyline() - L<Imager::Draw/polyline()>
4948 polypolygon() - L<Imager::Draw/polypolygon()>
4950 preload() - L<Imager::Files/preload()>
4952 read() - L<Imager::Files/read()> - read a single image from an image file
4954 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4957 read_types() - L<Imager::Files/read_types()> - list image types Imager
4960 register_filter() - L<Imager::Filters/register_filter()>
4962 register_reader() - L<Imager::Files/register_reader()>
4964 register_writer() - L<Imager::Files/register_writer()>
4966 rotate() - L<Imager::Transformations/rotate()>
4968 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4969 onto an image and use the alpha channel
4971 scale() - L<Imager::Transformations/scale()>
4973 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4975 scaleX() - L<Imager::Transformations/scaleX()>
4977 scaleY() - L<Imager::Transformations/scaleY()>
4979 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4982 set_file_limits() - L<Imager::Files/set_file_limits()>
4984 setmask() - L<Imager::ImageTypes/setmask()>
4986 setpixel() - L<Imager::Draw/setpixel()>
4988 setsamples() - L<Imager::Draw/setsamples()>
4990 setscanline() - L<Imager::Draw/setscanline()>
4992 settag() - L<Imager::ImageTypes/settag()>
4994 string() - L<Imager::Draw/string()> - draw text on an image
4996 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4998 to_paletted() - L<Imager::ImageTypes/to_paletted()>
5000 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
5002 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
5004 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
5005 double per sample image.
5007 transform() - L<Imager::Engines/"transform()">
5009 transform2() - L<Imager::Engines/"transform2()">
5011 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
5013 unload_plugin() - L<Imager::Filters/unload_plugin()>
5015 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
5018 write() - L<Imager::Files/write()> - write an image to a file
5020 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
5023 write_types() - L<Imager::Files/read_types()> - list image types Imager
5026 =head1 CONCEPT INDEX
5028 animated GIF - L<Imager::Files/"Writing an animated GIF">
5030 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
5031 L<Imager::ImageTypes/"Common Tags">.
5033 blend - alpha blending one image onto another
5034 L<Imager::Transformations/rubthrough()>
5036 blur - L<< Imager::Filters/C<gaussian> >>, L<< Imager::Filters/C<conv> >>
5038 boxes, drawing - L<Imager::Draw/box()>
5040 changes between image - L<Imager::Filters/"Image Difference">
5042 channels, combine into one image - L<Imager::Transformations/combine()>
5044 color - L<Imager::Color>
5046 color names - L<Imager::Color>, L<Imager::Color::Table>
5048 combine modes - L<Imager::Draw/"Combine Types">
5050 compare images - L<Imager::Filters/"Image Difference">
5052 contrast - L<< Imager::Filters/C<contrast> >>, L<< Imager::Filters/C<autolevels> >>
5054 convolution - L<< Imager::Filters/C<conv> >>
5056 cropping - L<Imager::Transformations/crop()>
5058 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5060 C<diff> images - L<Imager::Filters/"Image Difference">
5062 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
5063 L<Imager::Cookbook/"Image spatial resolution">
5065 drawing boxes - L<Imager::Draw/box()>
5067 drawing lines - L<Imager::Draw/line()>
5069 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
5071 error message - L</"ERROR HANDLING">
5073 files, font - L<Imager::Font>
5075 files, image - L<Imager::Files>
5077 filling, types of fill - L<Imager::Fill>
5079 filling, boxes - L<Imager::Draw/box()>
5081 filling, flood fill - L<Imager::Draw/flood_fill()>
5083 flood fill - L<Imager::Draw/flood_fill()>
5085 fonts - L<Imager::Font>
5087 fonts, drawing with - L<Imager::Draw/string()>,
5088 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
5090 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5092 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
5094 fountain fill - L<Imager::Fill/"Fountain fills">,
5095 L<< Imager::Filters/C<fountain> >>, L<Imager::Fountain>,
5096 L<< Imager::Filters/C<gradgen> >>
5098 GIF files - L<Imager::Files/"GIF">
5100 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
5102 gradient fill - L<Imager::Fill/"Fountain fills">,
5103 L<< Imager::Filters/C<fountain> >>, L<Imager::Fountain>,
5104 L<< Imager::Filters/C<gradgen> >>
5106 gray scale, convert image to - L<Imager::Transformations/convert()>
5108 gaussian blur - L<< Imager::Filters/C<gaussian> >>, L<< Imager::Filters/C<gaussian2> >>
5110 hatch fills - L<Imager::Fill/"Hatched fills">
5112 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5114 invert image - L<< Imager::Filters/C<hardinvert> >>,
5115 L<< Imager::Filters/C<hardinvertall> >>
5117 JPEG - L<Imager::Files/"JPEG">
5119 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
5121 lines, drawing - L<Imager::Draw/line()>
5123 matrix - L<Imager::Matrix2d>,
5124 L<Imager::Engines/"Matrix Transformations">,
5125 L<Imager::Font/transform()>
5127 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5129 mosaic - L<< Imager::Filters/C<mosaic> >>
5131 noise, filter - L<< Imager::Filters/C<noise> >>
5133 noise, rendered - L<< Imager::Filters/C<turbnoise> >>,
5134 L<< Imager::Filters/C<radnoise> >>
5136 paste - L<Imager::Transformations/paste()>,
5137 L<Imager::Transformations/rubthrough()>
5139 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5140 L<Imager::ImageTypes/new()>
5142 =for stopwords posterize
5144 posterize - L<< Imager::Filters/C<postlevels> >>
5146 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5148 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5150 rectangles, drawing - L<Imager::Draw/box()>
5152 resizing an image - L<Imager::Transformations/scale()>,
5153 L<Imager::Transformations/crop()>
5155 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5157 saving an image - L<Imager::Files>
5159 scaling - L<Imager::Transformations/scale()>
5161 security - L<Imager::Security>
5163 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5165 sharpen - L<< Imager::Filters/C<unsharpmask> >>, L<< Imager::Filters/C<conv> >>
5167 size, image - L<Imager::ImageTypes/getwidth()>,
5168 L<Imager::ImageTypes/getheight()>
5170 size, text - L<Imager::Font/bounding_box()>
5172 tags, image metadata - L<Imager::ImageTypes/"Tags">
5174 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5175 L<Imager::Font::Wrap>
5177 text, wrapping text in an area - L<Imager::Font::Wrap>
5179 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5181 threads - L<Imager::Threads>
5183 tiles, color - L<< Imager::Filters/C<mosaic> >>
5185 transparent images - L<Imager::ImageTypes>,
5186 L<Imager::Cookbook/"Transparent PNG">
5188 =for stopwords unsharp
5190 unsharp mask - L<< Imager::Filters/C<unsharpmask> >>
5192 watermark - L<< Imager::Filters/C<watermark> >>
5194 writing an image to a file - L<Imager::Files>
5198 The best place to get help with Imager is the mailing list.
5200 To subscribe send a message with C<subscribe> in the body to:
5202 imager-devel+request@molar.is
5208 L<http://www.molar.is/en/lists/imager-devel/>
5212 where you can also find the mailing list archive.
5214 You can report bugs by pointing your browser at:
5218 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5222 or by sending an email to:
5226 bug-Imager@rt.cpan.org
5230 Please remember to include the versions of Imager, perl, supporting
5231 libraries, and any relevant code. If you have specific images that
5232 cause the problems, please include those too.
5234 If you don't want to publish your email address on a mailing list you
5235 can use CPAN::Forum:
5237 http://www.cpanforum.com/dist/Imager
5239 You will need to register to post.
5241 =head1 CONTRIBUTING TO IMAGER
5247 If you like or dislike Imager, you can add a public review of Imager
5250 http://cpanratings.perl.org/dist/Imager
5252 =for stopwords Bitcard
5254 This requires a Bitcard account (http://www.bitcard.org).
5256 You can also send email to the maintainer below.
5258 If you send me a bug report via email, it will be copied to Request
5263 I accept patches, preferably against the master branch in git. Please
5264 include an explanation of the reason for why the patch is needed or
5267 Your patch should include regression tests where possible, otherwise
5268 it will be delayed until I get a chance to write them.
5270 To browse Imager's git repository:
5272 http://git.imager.perl.org/imager.git
5276 git clone git://git.imager.perl.org/imager.git
5278 My preference is that patches are provided in the format produced by
5279 C<git format-patch>, for example, if you made your changes in a branch
5280 from master you might do:
5282 git format-patch -k --stdout master >my-patch.txt
5284 and then attach that to your bug report, either by adding it as an
5285 attachment in your email client, or by using the Request Tracker
5286 attachment mechanism.
5290 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5292 Arnar M. Hrafnkelsson is the original author of Imager.
5294 Many others have contributed to Imager, please see the C<README> for a
5299 Imager is licensed under the same terms as perl itself.
5302 makeblendedfont Fontforge
5304 A test font, generated by the Debian packaged Fontforge,
5305 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5306 copyrighted by Adobe. See F<adobe.txt> in the source for license
5311 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5312 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5313 L<Imager::Font>(3), L<Imager::Transformations>(3),
5314 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5315 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5317 L<http://imager.perl.org/>
5319 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5321 Other perl imaging modules include:
5323 L<GD>(3), L<Image::Magick>(3),
5324 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5325 L<Prima::Image>, L<IPA>.
5327 For manipulating image metadata see L<Image::ExifTool>.
5329 If you're trying to use Imager for array processing, you should
5330 probably using L<PDL>.