4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
113 # registered file readers
116 # registered file writers
119 # modules we attempted to autoload
120 my %attempted_to_load;
122 # errors from loading files
123 my %file_load_errors;
125 # what happened when we tried to load
126 my %reader_load_errors;
127 my %writer_load_errors;
129 # library keys that are image file formats
130 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
132 # image pixel combine types
134 qw/none normal multiply dissolve add subtract diff lighten darken
135 hue saturation value color/;
137 @combine_types{@combine_types} = 0 .. $#combine_types;
138 $combine_types{mult} = $combine_types{multiply};
139 $combine_types{'sub'} = $combine_types{subtract};
140 $combine_types{sat} = $combine_types{saturation};
142 # this will be used to store global defaults at some point
147 my $ex_version = eval $Exporter::VERSION;
148 if ($ex_version < 5.57) {
154 XSLoader::load(Imager => $VERSION);
158 push @ISA, 'DynaLoader';
159 bootstrap Imager $VERSION;
166 png => "Imager::File::PNG",
167 gif => "Imager::File::GIF",
168 tiff => "Imager::File::TIFF",
169 jpeg => "Imager::File::JPEG",
170 w32 => "Imager::Font::W32",
171 ft2 => "Imager::Font::FT2",
172 t1 => "Imager::Font::T1",
175 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
178 for(i_list_formats()) { $formats_low{$_}++; }
180 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
184 # the members of the subhashes under %filters are:
185 # callseq - a list of the parameters to the underlying filter in the
186 # order they are passed
187 # callsub - a code ref that takes a named parameter list and calls the
189 # defaults - a hash of default values
190 # names - defines names for value of given parameters so if the names
191 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
192 # foo parameter, the filter will receive 1 for the foo
195 callseq => ['image','intensity'],
196 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
200 callseq => ['image', 'amount', 'subtype'],
201 defaults => { amount=>3,subtype=>0 },
202 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
205 $filters{hardinvert} ={
206 callseq => ['image'],
208 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
211 $filters{hardinvertall} =
213 callseq => ['image'],
215 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
218 $filters{autolevels} ={
219 callseq => ['image','lsat','usat','skew'],
220 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
221 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
224 $filters{turbnoise} ={
225 callseq => ['image'],
226 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
227 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
230 $filters{radnoise} ={
231 callseq => ['image'],
232 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
233 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
238 callseq => ['image', 'coef'],
243 i_conv($hsh{image},$hsh{coef})
244 or die Imager->_error_as_msg() . "\n";
250 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
251 defaults => { dist => 0 },
255 my @colors = @{$hsh{colors}};
258 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
262 $filters{nearest_color} =
264 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
269 # make sure the segments are specified with colors
271 for my $color (@{$hsh{colors}}) {
272 my $new_color = _color($color)
273 or die $Imager::ERRSTR."\n";
274 push @colors, $new_color;
277 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
279 or die Imager->_error_as_msg() . "\n";
282 $filters{gaussian} = {
283 callseq => [ 'image', 'stddev' ],
285 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
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
534 my ($DSO_handle,$str)=DSO_open($filename);
535 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
536 my %funcs=DSO_funclist($DSO_handle);
537 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
539 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
541 $DSOs{$filename}=[$DSO_handle,\%funcs];
544 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
545 $DEBUG && print "eval string:\n",$evstr,"\n";
557 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
558 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
559 for(keys %{$funcref}) {
561 $DEBUG && print "unloading: $_\n";
563 my $rc=DSO_close($DSO_handle);
564 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
568 # take the results of i_error() and make a message out of it
570 return join(": ", map $_->[0], i_errors());
573 # this function tries to DWIM for color parameters
574 # color objects are used as is
575 # simple scalars are simply treated as single parameters to Imager::Color->new
576 # hashrefs are treated as named argument lists to Imager::Color->new
577 # arrayrefs are treated as list arguments to Imager::Color->new iff any
579 # other arrayrefs are treated as list arguments to Imager::Color::Float
583 # perl 5.6.0 seems to do weird things to $arg if we don't make an
584 # explicitly stringified copy
585 # I vaguely remember a bug on this on p5p, but couldn't find it
586 # through bugs.perl.org (I had trouble getting it to find any bugs)
587 my $copy = $arg . "";
591 if (UNIVERSAL::isa($arg, "Imager::Color")
592 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
596 if ($copy =~ /^HASH\(/) {
597 $result = Imager::Color->new(%$arg);
599 elsif ($copy =~ /^ARRAY\(/) {
600 $result = Imager::Color->new(@$arg);
603 $Imager::ERRSTR = "Not a color";
608 # assume Imager::Color::new knows how to handle it
609 $result = Imager::Color->new($arg);
616 my ($self, $combine, $default) = @_;
618 if (!defined $combine && ref $self) {
619 $combine = $self->{combine};
621 defined $combine or $combine = $defaults{combine};
622 defined $combine or $combine = $default;
624 if (exists $combine_types{$combine}) {
625 $combine = $combine_types{$combine};
634 $self->{IMG} and return 1;
636 $self->_set_error('empty input image');
641 # returns first defined parameter
644 return $_ if defined $_;
650 # Methods to be called on objects.
653 # Create a new Imager object takes very few parameters.
654 # usually you call this method and then call open from
655 # the resulting object
662 $self->{IMG}=undef; # Just to indicate what exists
663 $self->{ERRSTR}=undef; #
664 $self->{DEBUG}=$DEBUG;
665 $self->{DEBUG} and print "Initialized Imager\n";
666 if (defined $hsh{xsize} || defined $hsh{ysize}) {
667 unless ($self->img_set(%hsh)) {
668 $Imager::ERRSTR = $self->{ERRSTR};
672 elsif (defined $hsh{file} ||
675 defined $hsh{callback} ||
676 defined $hsh{readcb} ||
677 defined $hsh{data}) {
678 # allow $img = Imager->new(file => $filename)
681 # type is already used as a parameter to new(), rename it for the
683 if ($hsh{filetype}) {
684 $extras{type} = $hsh{filetype};
686 unless ($self->read(%hsh, %extras)) {
687 $Imager::ERRSTR = $self->{ERRSTR};
695 # Copy an entire image with no changes
696 # - if an image has magic the copy of it will not be magical
700 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
702 unless (defined wantarray) {
704 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
708 my $newcopy=Imager->new();
709 $newcopy->{IMG} = i_copy($self->{IMG});
718 unless ($self->{IMG}) {
719 $self->_set_error('empty input image');
722 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
723 my $src = $input{img} || $input{src};
725 $self->_set_error("no source image");
728 $input{left}=0 if $input{left} <= 0;
729 $input{top}=0 if $input{top} <= 0;
731 my($r,$b)=i_img_info($src->{IMG});
732 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
733 my ($src_right, $src_bottom);
734 if ($input{src_coords}) {
735 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
738 if (defined $input{src_maxx}) {
739 $src_right = $input{src_maxx};
741 elsif (defined $input{width}) {
742 if ($input{width} <= 0) {
743 $self->_set_error("paste: width must me positive");
746 $src_right = $src_left + $input{width};
751 if (defined $input{src_maxy}) {
752 $src_bottom = $input{src_maxy};
754 elsif (defined $input{height}) {
755 if ($input{height} < 0) {
756 $self->_set_error("paste: height must be positive");
759 $src_bottom = $src_top + $input{height};
766 $src_right > $r and $src_right = $r;
767 $src_bottom > $b and $src_bottom = $b;
769 if ($src_right <= $src_left
770 || $src_bottom < $src_top) {
771 $self->_set_error("nothing to paste");
775 i_copyto($self->{IMG}, $src->{IMG},
776 $src_left, $src_top, $src_right, $src_bottom,
777 $input{left}, $input{top});
779 return $self; # What should go here??
782 # Crop an image - i.e. return a new image that is smaller
786 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
788 unless (defined wantarray) {
790 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
796 my ($w, $h, $l, $r, $b, $t) =
797 @hsh{qw(width height left right bottom top)};
799 # work through the various possibilities
804 elsif (!defined $r) {
805 $r = $self->getwidth;
817 $l = int(0.5+($self->getwidth()-$w)/2);
822 $r = $self->getwidth;
828 elsif (!defined $b) {
829 $b = $self->getheight;
841 $t=int(0.5+($self->getheight()-$h)/2);
846 $b = $self->getheight;
849 ($l,$r)=($r,$l) if $l>$r;
850 ($t,$b)=($b,$t) if $t>$b;
853 $r > $self->getwidth and $r = $self->getwidth;
855 $b > $self->getheight and $b = $self->getheight;
857 if ($l == $r || $t == $b) {
858 $self->_set_error("resulting image would have no content");
861 if( $r < $l or $b < $t ) {
862 $self->_set_error("attempting to crop outside of the image");
865 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
867 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
872 my ($self, %opts) = @_;
874 $self->{IMG} or return $self->_set_error("Not a valid image");
876 my $x = $opts{xsize} || $self->getwidth;
877 my $y = $opts{ysize} || $self->getheight;
878 my $channels = $opts{channels} || $self->getchannels;
880 my $out = Imager->new;
881 if ($channels == $self->getchannels) {
882 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
885 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
887 unless ($out->{IMG}) {
888 $self->{ERRSTR} = $self->_error_as_msg;
895 # Sets an image to a certain size and channel number
896 # if there was previously data in the image it is discarded
901 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
903 if (defined($self->{IMG})) {
904 # let IIM_DESTROY destroy it, it's possible this image is
905 # referenced from a virtual image (like masked)
906 #i_img_destroy($self->{IMG});
910 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
911 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
912 $hsh{maxcolors} || 256);
914 elsif ($hsh{bits} eq 'double') {
915 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
917 elsif ($hsh{bits} == 16) {
918 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
921 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
925 unless ($self->{IMG}) {
926 $self->{ERRSTR} = Imager->_error_as_msg();
933 # created a masked version of the current image
937 $self or return undef;
938 my %opts = (left => 0,
940 right => $self->getwidth,
941 bottom => $self->getheight,
943 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
945 my $result = Imager->new;
946 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
947 $opts{top}, $opts{right} - $opts{left},
948 $opts{bottom} - $opts{top});
949 unless ($result->{IMG}) {
950 $self->_set_error(Imager->_error_as_msg);
954 # keep references to the mask and base images so they don't
956 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
961 # convert an RGB image into a paletted image
965 if (@_ != 1 && !ref $_[0]) {
972 unless (defined wantarray) {
974 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
981 my $result = Imager->new;
982 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
983 $self->_set_error(Imager->_error_as_msg);
990 # convert a paletted (or any image) to an 8-bit/channel RGB image
994 unless (defined wantarray) {
996 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1003 my $result = Imager->new;
1004 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1005 $self->_set_error(Imager->_error_as_msg());
1012 # convert a paletted (or any image) to a 16-bit/channel RGB image
1016 unless (defined wantarray) {
1017 my @caller = caller;
1018 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1025 my $result = Imager->new;
1026 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1027 $self->_set_error(Imager->_error_as_msg());
1034 # convert a paletted (or any image) to an double/channel RGB image
1038 unless (defined wantarray) {
1039 my @caller = caller;
1040 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1047 my $result = Imager->new;
1048 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1049 $self->_set_error(Imager->_error_as_msg());
1058 my %opts = (colors=>[], @_);
1060 unless ($self->{IMG}) {
1061 $self->_set_error("empty input image");
1065 my @colors = @{$opts{colors}}
1068 for my $color (@colors) {
1069 $color = _color($color);
1071 $self->_set_error($Imager::ERRSTR);
1076 return i_addcolors($self->{IMG}, @colors);
1081 my %opts = (start=>0, colors=>[], @_);
1083 unless ($self->{IMG}) {
1084 $self->_set_error("empty input image");
1088 my @colors = @{$opts{colors}}
1091 for my $color (@colors) {
1092 $color = _color($color);
1094 $self->_set_error($Imager::ERRSTR);
1099 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1105 if (!exists $opts{start} && !exists $opts{count}) {
1108 $opts{count} = $self->colorcount;
1110 elsif (!exists $opts{count}) {
1113 elsif (!exists $opts{start}) {
1118 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1122 i_colorcount($_[0]{IMG});
1126 i_maxcolors($_[0]{IMG});
1132 $opts{color} or return undef;
1134 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1139 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1140 if ($bits && $bits == length(pack("d", 1)) * 8) {
1149 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1155 $self->{IMG} and i_img_virtual($self->{IMG});
1161 $self->{IMG} or return;
1163 return i_img_is_monochrome($self->{IMG});
1167 my ($self, %opts) = @_;
1169 $self->{IMG} or return;
1171 if (defined $opts{name}) {
1175 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1176 push @result, (i_tags_get($self->{IMG}, $found))[1];
1179 return wantarray ? @result : $result[0];
1181 elsif (defined $opts{code}) {
1185 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1186 push @result, (i_tags_get($self->{IMG}, $found))[1];
1193 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1196 return i_tags_count($self->{IMG});
1205 return -1 unless $self->{IMG};
1207 if (defined $opts{value}) {
1208 if ($opts{value} =~ /^\d+$/) {
1210 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1213 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1216 elsif (defined $opts{data}) {
1217 # force addition as a string
1218 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1221 $self->{ERRSTR} = "No value supplied";
1225 elsif ($opts{code}) {
1226 if (defined $opts{value}) {
1227 if ($opts{value} =~ /^\d+$/) {
1229 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1232 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1235 elsif (defined $opts{data}) {
1236 # force addition as a string
1237 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1240 $self->{ERRSTR} = "No value supplied";
1253 return 0 unless $self->{IMG};
1255 if (defined $opts{'index'}) {
1256 return i_tags_delete($self->{IMG}, $opts{'index'});
1258 elsif (defined $opts{name}) {
1259 return i_tags_delbyname($self->{IMG}, $opts{name});
1261 elsif (defined $opts{code}) {
1262 return i_tags_delbycode($self->{IMG}, $opts{code});
1265 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1271 my ($self, %opts) = @_;
1274 $self->deltag(name=>$opts{name});
1275 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1277 elsif (defined $opts{code}) {
1278 $self->deltag(code=>$opts{code});
1279 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1287 sub _get_reader_io {
1288 my ($self, $input) = @_;
1291 return $input->{io}, undef;
1293 elsif ($input->{fd}) {
1294 return io_new_fd($input->{fd});
1296 elsif ($input->{fh}) {
1297 my $fd = fileno($input->{fh});
1298 unless (defined $fd) {
1299 $self->_set_error("Handle in fh option not opened");
1302 return io_new_fd($fd);
1304 elsif ($input->{file}) {
1305 my $file = IO::File->new($input->{file}, "r");
1307 $self->_set_error("Could not open $input->{file}: $!");
1311 return (io_new_fd(fileno($file)), $file);
1313 elsif ($input->{data}) {
1314 return io_new_buffer($input->{data});
1316 elsif ($input->{callback} || $input->{readcb}) {
1317 if (!$input->{seekcb}) {
1318 $self->_set_error("Need a seekcb parameter");
1320 if ($input->{maxbuffer}) {
1321 return io_new_cb($input->{writecb},
1322 $input->{callback} || $input->{readcb},
1323 $input->{seekcb}, $input->{closecb},
1324 $input->{maxbuffer});
1327 return io_new_cb($input->{writecb},
1328 $input->{callback} || $input->{readcb},
1329 $input->{seekcb}, $input->{closecb});
1333 $self->_set_error("file/fd/fh/data/callback parameter missing");
1338 sub _get_writer_io {
1339 my ($self, $input) = @_;
1341 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1346 return $input->{io};
1348 elsif ($input->{fd}) {
1349 $io = io_new_fd($input->{fd});
1351 elsif ($input->{fh}) {
1352 my $fd = fileno($input->{fh});
1353 unless (defined $fd) {
1354 $self->_set_error("Handle in fh option not opened");
1358 my $oldfh = select($input->{fh});
1359 # flush anything that's buffered, and make sure anything else is flushed
1362 $io = io_new_fd($fd);
1364 elsif ($input->{file}) {
1365 my $fh = new IO::File($input->{file},"w+");
1367 $self->_set_error("Could not open file $input->{file}: $!");
1370 binmode($fh) or die;
1371 $io = io_new_fd(fileno($fh));
1374 elsif ($input->{data}) {
1375 $io = io_new_bufchain();
1377 elsif ($input->{callback} || $input->{writecb}) {
1378 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1381 $io = io_new_cb($input->{callback} || $input->{writecb},
1383 $input->{seekcb}, $input->{closecb});
1386 $self->_set_error("file/fd/fh/data/callback parameter missing");
1390 unless ($buffered) {
1391 $io->set_buffered(0);
1394 return ($io, @extras);
1397 # Read an image from file
1403 if (defined($self->{IMG})) {
1404 # let IIM_DESTROY do the destruction, since the image may be
1405 # referenced from elsewhere
1406 #i_img_destroy($self->{IMG});
1407 undef($self->{IMG});
1410 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1412 my $type = $input{'type'};
1414 $type = i_test_format_probe($IO, -1);
1418 $self->_set_error('type parameter missing and not possible to guess from extension');
1422 _reader_autoload($type);
1424 if ($readers{$type} && $readers{$type}{single}) {
1425 return $readers{$type}{single}->($self, $IO, %input);
1428 unless ($formats_low{$type}) {
1429 my $read_types = join ', ', sort Imager->read_types();
1430 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1434 my $allow_incomplete = $input{allow_incomplete};
1435 defined $allow_incomplete or $allow_incomplete = 0;
1437 if ( $type eq 'pnm' ) {
1438 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1439 if ( !defined($self->{IMG}) ) {
1440 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1443 $self->{DEBUG} && print "loading a pnm file\n";
1447 if ( $type eq 'bmp' ) {
1448 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1449 if ( !defined($self->{IMG}) ) {
1450 $self->{ERRSTR}=$self->_error_as_msg();
1453 $self->{DEBUG} && print "loading a bmp file\n";
1456 if ( $type eq 'gif' ) {
1457 if ($input{colors} && !ref($input{colors})) {
1458 # must be a reference to a scalar that accepts the colour map
1459 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1462 if ($input{'gif_consolidate'}) {
1463 if ($input{colors}) {
1465 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1467 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1471 $self->{IMG} =i_readgif_wiol( $IO );
1475 my $page = $input{'page'};
1476 defined $page or $page = 0;
1477 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1478 if ($self->{IMG} && $input{colors}) {
1479 ${ $input{colors} } =
1480 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1484 if ( !defined($self->{IMG}) ) {
1485 $self->{ERRSTR}=$self->_error_as_msg();
1488 $self->{DEBUG} && print "loading a gif file\n";
1491 if ( $type eq 'tga' ) {
1492 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1493 if ( !defined($self->{IMG}) ) {
1494 $self->{ERRSTR}=$self->_error_as_msg();
1497 $self->{DEBUG} && print "loading a tga file\n";
1500 if ( $type eq 'raw' ) {
1501 unless ( $input{xsize} && $input{ysize} ) {
1502 $self->_set_error('missing xsize or ysize parameter for raw');
1506 my $interleave = _first($input{raw_interleave}, $input{interleave});
1507 unless (defined $interleave) {
1508 my @caller = caller;
1509 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1512 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1513 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1515 $self->{IMG} = i_readraw_wiol( $IO,
1521 if ( !defined($self->{IMG}) ) {
1522 $self->{ERRSTR}=$self->_error_as_msg();
1525 $self->{DEBUG} && print "loading a raw file\n";
1531 sub register_reader {
1532 my ($class, %opts) = @_;
1535 or die "register_reader called with no type parameter\n";
1537 my $type = $opts{type};
1539 defined $opts{single} || defined $opts{multiple}
1540 or die "register_reader called with no single or multiple parameter\n";
1542 $readers{$type} = { };
1543 if ($opts{single}) {
1544 $readers{$type}{single} = $opts{single};
1546 if ($opts{multiple}) {
1547 $readers{$type}{multiple} = $opts{multiple};
1553 sub register_writer {
1554 my ($class, %opts) = @_;
1557 or die "register_writer called with no type parameter\n";
1559 my $type = $opts{type};
1561 defined $opts{single} || defined $opts{multiple}
1562 or die "register_writer called with no single or multiple parameter\n";
1564 $writers{$type} = { };
1565 if ($opts{single}) {
1566 $writers{$type}{single} = $opts{single};
1568 if ($opts{multiple}) {
1569 $writers{$type}{multiple} = $opts{multiple};
1580 grep($file_formats{$_}, keys %formats),
1581 qw(ico sgi), # formats not handled directly, but supplied with Imager
1592 grep($file_formats{$_}, keys %formats),
1593 qw(ico sgi), # formats not handled directly, but supplied with Imager
1600 my ($file, $error) = @_;
1602 if ($attempted_to_load{$file}) {
1603 if ($file_load_errors{$file}) {
1604 $$error = $file_load_errors{$file};
1612 local $SIG{__DIE__};
1614 ++$attempted_to_load{$file};
1622 my $work = $@ || "Unknown error loading $file";
1624 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1625 $work =~ s/\n/\\n/g;
1626 $file_load_errors{$file} = $work;
1633 # probes for an Imager::File::whatever module
1634 sub _reader_autoload {
1637 return if $formats_low{$type} || $readers{$type};
1639 return unless $type =~ /^\w+$/;
1641 my $file = "Imager/File/\U$type\E.pm";
1644 my $loaded = _load_file($file, \$error);
1645 if (!$loaded && $error =~ /^Can't locate /) {
1646 my $filer = "Imager/File/\U$type\EReader.pm";
1647 $loaded = _load_file($filer, \$error);
1648 if ($error =~ /^Can't locate /) {
1649 $error = "Can't locate $file or $filer";
1653 $reader_load_errors{$type} = $error;
1657 # probes for an Imager::File::whatever module
1658 sub _writer_autoload {
1661 return if $formats_low{$type} || $writers{$type};
1663 return unless $type =~ /^\w+$/;
1665 my $file = "Imager/File/\U$type\E.pm";
1668 my $loaded = _load_file($file, \$error);
1669 if (!$loaded && $error =~ /^Can't locate /) {
1670 my $filew = "Imager/File/\U$type\EWriter.pm";
1671 $loaded = _load_file($filew, \$error);
1672 if ($error =~ /^Can't locate /) {
1673 $error = "Can't locate $file or $filew";
1677 $writer_load_errors{$type} = $error;
1681 sub _fix_gif_positions {
1682 my ($opts, $opt, $msg, @imgs) = @_;
1684 my $positions = $opts->{'gif_positions'};
1686 for my $pos (@$positions) {
1687 my ($x, $y) = @$pos;
1688 my $img = $imgs[$index++];
1689 $img->settag(name=>'gif_left', value=>$x);
1690 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1692 $$msg .= "replaced with the gif_left and gif_top tags";
1697 gif_each_palette=>'gif_local_map',
1698 interlace => 'gif_interlace',
1699 gif_delays => 'gif_delay',
1700 gif_positions => \&_fix_gif_positions,
1701 gif_loop_count => 'gif_loop',
1704 # options that should be converted to colors
1705 my %color_opts = map { $_ => 1 } qw/i_background/;
1708 my ($self, $opts, $prefix, @imgs) = @_;
1710 for my $opt (keys %$opts) {
1712 if ($obsolete_opts{$opt}) {
1713 my $new = $obsolete_opts{$opt};
1714 my $msg = "Obsolete option $opt ";
1716 $new->($opts, $opt, \$msg, @imgs);
1719 $msg .= "replaced with the $new tag ";
1722 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1723 warn $msg if $warn_obsolete && $^W;
1725 next unless $tagname =~ /^\Q$prefix/;
1726 my $value = $opts->{$opt};
1727 if ($color_opts{$opt}) {
1728 $value = _color($value);
1730 $self->_set_error($Imager::ERRSTR);
1735 if (UNIVERSAL::isa($value, "Imager::Color")) {
1736 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1737 for my $img (@imgs) {
1738 $img->settag(name=>$tagname, value=>$tag);
1741 elsif (ref($value) eq 'ARRAY') {
1742 for my $i (0..$#$value) {
1743 my $val = $value->[$i];
1745 if (UNIVERSAL::isa($val, "Imager::Color")) {
1746 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1748 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1751 $self->_set_error("Unknown reference type " . ref($value) .
1752 " supplied in array for $opt");
1758 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1763 $self->_set_error("Unknown reference type " . ref($value) .
1764 " supplied for $opt");
1769 # set it as a tag for every image
1770 for my $img (@imgs) {
1771 $img->settag(name=>$tagname, value=>$value);
1779 # Write an image to file
1782 my %input=(jpegquality=>75,
1792 $self->_set_opts(\%input, "i_", $self)
1795 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1797 my $type = $input{'type'};
1798 if (!$type and $input{file}) {
1799 $type = $FORMATGUESS->($input{file});
1802 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1806 _writer_autoload($type);
1809 if ($writers{$type} && $writers{$type}{single}) {
1810 ($IO, $fh) = $self->_get_writer_io(\%input)
1813 $writers{$type}{single}->($self, $IO, %input, type => $type)
1817 if (!$formats_low{$type}) {
1818 my $write_types = join ', ', sort Imager->write_types();
1819 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1823 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1826 if ( $type eq 'pnm' ) {
1827 $self->_set_opts(\%input, "pnm_", $self)
1829 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1830 $self->{ERRSTR} = $self->_error_as_msg();
1833 $self->{DEBUG} && print "writing a pnm file\n";
1835 elsif ( $type eq 'raw' ) {
1836 $self->_set_opts(\%input, "raw_", $self)
1838 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1839 $self->{ERRSTR} = $self->_error_as_msg();
1842 $self->{DEBUG} && print "writing a raw file\n";
1844 elsif ( $type eq 'bmp' ) {
1845 $self->_set_opts(\%input, "bmp_", $self)
1847 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1848 $self->{ERRSTR} = $self->_error_as_msg;
1851 $self->{DEBUG} && print "writing a bmp file\n";
1853 elsif ( $type eq 'tga' ) {
1854 $self->_set_opts(\%input, "tga_", $self)
1857 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1858 $self->{ERRSTR}=$self->_error_as_msg();
1861 $self->{DEBUG} && print "writing a tga file\n";
1865 if (exists $input{'data'}) {
1866 my $data = io_slurp($IO);
1868 $self->{ERRSTR}='Could not slurp from buffer';
1871 ${$input{data}} = $data;
1877 my ($class, $opts, @images) = @_;
1879 my $type = $opts->{type};
1881 if (!$type && $opts->{'file'}) {
1882 $type = $FORMATGUESS->($opts->{'file'});
1885 $class->_set_error('type parameter missing and not possible to guess from extension');
1888 # translate to ImgRaw
1889 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1890 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1893 $class->_set_opts($opts, "i_", @images)
1895 my @work = map $_->{IMG}, @images;
1897 _writer_autoload($type);
1900 if ($writers{$type} && $writers{$type}{multiple}) {
1901 ($IO, $file) = $class->_get_writer_io($opts, $type)
1904 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1908 if (!$formats{$type}) {
1909 my $write_types = join ', ', sort Imager->write_types();
1910 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1914 ($IO, $file) = $class->_get_writer_io($opts, $type)
1917 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1921 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1926 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1932 if (exists $opts->{'data'}) {
1933 my $data = io_slurp($IO);
1935 Imager->_set_error('Could not slurp from buffer');
1938 ${$opts->{data}} = $data;
1943 # read multiple images from a file
1945 my ($class, %opts) = @_;
1947 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1950 my $type = $opts{'type'};
1952 $type = i_test_format_probe($IO, -1);
1955 if ($opts{file} && !$type) {
1957 $type = $FORMATGUESS->($opts{file});
1961 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1965 _reader_autoload($type);
1967 if ($readers{$type} && $readers{$type}{multiple}) {
1968 return $readers{$type}{multiple}->($IO, %opts);
1971 unless ($formats{$type}) {
1972 my $read_types = join ', ', sort Imager->read_types();
1973 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1978 if ($type eq 'pnm') {
1979 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1982 my $img = Imager->new;
1983 if ($img->read(%opts, io => $IO, type => $type)) {
1986 Imager->_set_error($img->errstr);
1991 $ERRSTR = _error_as_msg();
1995 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1999 # Destroy an Imager object
2003 # delete $instances{$self};
2004 if (defined($self->{IMG})) {
2005 # the following is now handled by the XS DESTROY method for
2006 # Imager::ImgRaw object
2007 # Re-enabling this will break virtual images
2008 # tested for in t/t020masked.t
2009 # i_img_destroy($self->{IMG});
2010 undef($self->{IMG});
2012 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2016 # Perform an inplace filter of an image
2017 # that is the image will be overwritten with the data
2023 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2025 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2027 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2028 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2031 if ($filters{$input{'type'}}{names}) {
2032 my $names = $filters{$input{'type'}}{names};
2033 for my $name (keys %$names) {
2034 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2035 $input{$name} = $names->{$name}{$input{$name}};
2039 if (defined($filters{$input{'type'}}{defaults})) {
2040 %hsh=( image => $self->{IMG},
2042 %{$filters{$input{'type'}}{defaults}},
2045 %hsh=( image => $self->{IMG},
2050 my @cs=@{$filters{$input{'type'}}{callseq}};
2053 if (!defined($hsh{$_})) {
2054 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2059 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2060 &{$filters{$input{'type'}}{callsub}}(%hsh);
2063 chomp($self->{ERRSTR} = $@);
2069 $self->{DEBUG} && print "callseq is: @cs\n";
2070 $self->{DEBUG} && print "matching callseq is: @b\n";
2075 sub register_filter {
2077 my %hsh = ( defaults => {}, @_ );
2080 or die "register_filter() with no type\n";
2081 defined $hsh{callsub}
2082 or die "register_filter() with no callsub\n";
2083 defined $hsh{callseq}
2084 or die "register_filter() with no callseq\n";
2086 exists $filters{$hsh{type}}
2089 $filters{$hsh{type}} = \%hsh;
2094 sub scale_calculate {
2097 my %opts = ('type'=>'max', @_);
2099 # none of these should be references
2100 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2101 if (defined $opts{$name} && ref $opts{$name}) {
2102 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2107 my ($x_scale, $y_scale);
2108 my $width = $opts{width};
2109 my $height = $opts{height};
2111 defined $width or $width = $self->getwidth;
2112 defined $height or $height = $self->getheight;
2115 unless (defined $width && defined $height) {
2116 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2121 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2122 $x_scale = $opts{'xscalefactor'};
2123 $y_scale = $opts{'yscalefactor'};
2125 elsif ($opts{'xscalefactor'}) {
2126 $x_scale = $opts{'xscalefactor'};
2127 $y_scale = $opts{'scalefactor'} || $x_scale;
2129 elsif ($opts{'yscalefactor'}) {
2130 $y_scale = $opts{'yscalefactor'};
2131 $x_scale = $opts{'scalefactor'} || $y_scale;
2134 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2137 # work out the scaling
2138 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2139 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2140 $opts{ypixels} / $height );
2141 if ($opts{'type'} eq 'min') {
2142 $x_scale = $y_scale = _min($xpix,$ypix);
2144 elsif ($opts{'type'} eq 'max') {
2145 $x_scale = $y_scale = _max($xpix,$ypix);
2147 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2152 $self->_set_error('invalid value for type parameter');
2155 } elsif ($opts{xpixels}) {
2156 $x_scale = $y_scale = $opts{xpixels} / $width;
2158 elsif ($opts{ypixels}) {
2159 $x_scale = $y_scale = $opts{ypixels}/$height;
2161 elsif ($opts{constrain} && ref $opts{constrain}
2162 && $opts{constrain}->can('constrain')) {
2163 # we've been passed an Image::Math::Constrain object or something
2164 # that looks like one
2166 (undef, undef, $scalefactor)
2167 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2168 unless ($scalefactor) {
2169 $self->_set_error('constrain method failed on constrain parameter');
2172 $x_scale = $y_scale = $scalefactor;
2175 my $new_width = int($x_scale * $width + 0.5);
2176 $new_width > 0 or $new_width = 1;
2177 my $new_height = int($y_scale * $height + 0.5);
2178 $new_height > 0 or $new_height = 1;
2180 return ($x_scale, $y_scale, $new_width, $new_height);
2184 # Scale an image to requested size and return the scaled version
2188 my %opts = (qtype=>'normal' ,@_);
2189 my $img = Imager->new();
2190 my $tmp = Imager->new();
2192 unless (defined wantarray) {
2193 my @caller = caller;
2194 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2198 unless ($self->{IMG}) {
2199 $self->_set_error('empty input image');
2203 my ($x_scale, $y_scale, $new_width, $new_height) =
2204 $self->scale_calculate(%opts)
2207 if ($opts{qtype} eq 'normal') {
2208 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2209 if ( !defined($tmp->{IMG}) ) {
2210 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2213 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2214 if ( !defined($img->{IMG}) ) {
2215 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2221 elsif ($opts{'qtype'} eq 'preview') {
2222 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2223 if ( !defined($img->{IMG}) ) {
2224 $self->{ERRSTR}='unable to scale image';
2229 elsif ($opts{'qtype'} eq 'mixing') {
2230 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2231 unless ($img->{IMG}) {
2232 $self->_set_error(Imager->_error_as_msg);
2238 $self->_set_error('invalid value for qtype parameter');
2243 # Scales only along the X axis
2247 my %opts = ( scalefactor=>0.5, @_ );
2249 unless (defined wantarray) {
2250 my @caller = caller;
2251 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2255 unless ($self->{IMG}) {
2256 $self->{ERRSTR} = 'empty input image';
2260 my $img = Imager->new();
2262 my $scalefactor = $opts{scalefactor};
2264 if ($opts{pixels}) {
2265 $scalefactor = $opts{pixels} / $self->getwidth();
2268 unless ($self->{IMG}) {
2269 $self->{ERRSTR}='empty input image';
2273 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2275 if ( !defined($img->{IMG}) ) {
2276 $self->{ERRSTR} = 'unable to scale image';
2283 # Scales only along the Y axis
2287 my %opts = ( scalefactor => 0.5, @_ );
2289 unless (defined wantarray) {
2290 my @caller = caller;
2291 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2295 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2297 my $img = Imager->new();
2299 my $scalefactor = $opts{scalefactor};
2301 if ($opts{pixels}) {
2302 $scalefactor = $opts{pixels} / $self->getheight();
2305 unless ($self->{IMG}) {
2306 $self->{ERRSTR} = 'empty input image';
2309 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2311 if ( !defined($img->{IMG}) ) {
2312 $self->{ERRSTR} = 'unable to scale image';
2319 # Transform returns a spatial transformation of the input image
2320 # this moves pixels to a new location in the returned image.
2321 # NOTE - should make a utility function to check transforms for
2326 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2328 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2330 # print Dumper(\%opts);
2333 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2335 eval ("use Affix::Infix2Postfix;");
2338 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2341 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2342 {op=>'-',trans=>'Sub'},
2343 {op=>'*',trans=>'Mult'},
2344 {op=>'/',trans=>'Div'},
2345 {op=>'-','type'=>'unary',trans=>'u-'},
2347 {op=>'func','type'=>'unary'}],
2348 'grouping'=>[qw( \( \) )],
2349 'func'=>[qw( sin cos )],
2354 @xt=$I2P->translate($opts{'xexpr'});
2355 @yt=$I2P->translate($opts{'yexpr'});
2357 $numre=$I2P->{'numre'};
2360 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2361 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2362 @{$opts{'parm'}}=@pt;
2365 # print Dumper(\%opts);
2367 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2368 $self->{ERRSTR}='transform: no xopcodes given.';
2372 @op=@{$opts{'xopcodes'}};
2374 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2375 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2378 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2384 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2385 $self->{ERRSTR}='transform: no yopcodes given.';
2389 @op=@{$opts{'yopcodes'}};
2391 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2392 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2395 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2400 if ( !exists $opts{'parm'}) {
2401 $self->{ERRSTR}='transform: no parameter arg given.';
2405 # print Dumper(\@ropx);
2406 # print Dumper(\@ropy);
2407 # print Dumper(\@ropy);
2409 my $img = Imager->new();
2410 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2411 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2417 my ($opts, @imgs) = @_;
2419 require "Imager/Expr.pm";
2421 $opts->{variables} = [ qw(x y) ];
2422 my ($width, $height) = @{$opts}{qw(width height)};
2424 $width ||= $imgs[0]->getwidth();
2425 $height ||= $imgs[0]->getheight();
2427 for my $img (@imgs) {
2428 $opts->{constants}{"w$img_num"} = $img->getwidth();
2429 $opts->{constants}{"h$img_num"} = $img->getheight();
2430 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2431 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2436 $opts->{constants}{w} = $width;
2437 $opts->{constants}{cx} = $width/2;
2440 $Imager::ERRSTR = "No width supplied";
2444 $opts->{constants}{h} = $height;
2445 $opts->{constants}{cy} = $height/2;
2448 $Imager::ERRSTR = "No height supplied";
2451 my $code = Imager::Expr->new($opts);
2453 $Imager::ERRSTR = Imager::Expr::error();
2456 my $channels = $opts->{channels} || 3;
2457 unless ($channels >= 1 && $channels <= 4) {
2458 return Imager->_set_error("channels must be an integer between 1 and 4");
2461 my $img = Imager->new();
2462 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2463 $channels, $code->code(),
2464 $code->nregs(), $code->cregs(),
2465 [ map { $_->{IMG} } @imgs ]);
2466 if (!defined $img->{IMG}) {
2467 $Imager::ERRSTR = Imager->_error_as_msg();
2478 unless ($self->{IMG}) {
2479 $self->{ERRSTR}='empty input image';
2482 unless ($opts{src} && $opts{src}->{IMG}) {
2483 $self->{ERRSTR}='empty input image for src';
2487 %opts = (src_minx => 0,
2489 src_maxx => $opts{src}->getwidth(),
2490 src_maxy => $opts{src}->getheight(),
2494 defined $tx or $tx = $opts{left};
2495 defined $tx or $tx = 0;
2498 defined $ty or $ty = $opts{top};
2499 defined $ty or $ty = 0;
2501 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2502 $opts{src_minx}, $opts{src_miny},
2503 $opts{src_maxx}, $opts{src_maxy})) {
2504 $self->_set_error($self->_error_as_msg());
2521 unless ($self->{IMG}) {
2522 $self->_set_error("compose: empty input image");
2526 unless ($opts{src}) {
2527 $self->_set_error("compose: src parameter missing");
2531 unless ($opts{src}{IMG}) {
2532 $self->_set_error("compose: src parameter empty image");
2535 my $src = $opts{src};
2537 my $left = $opts{left};
2538 defined $left or $left = $opts{tx};
2539 defined $left or $left = 0;
2541 my $top = $opts{top};
2542 defined $top or $top = $opts{ty};
2543 defined $top or $top = 0;
2545 my $src_left = $opts{src_left};
2546 defined $src_left or $src_left = $opts{src_minx};
2547 defined $src_left or $src_left = 0;
2549 my $src_top = $opts{src_top};
2550 defined $src_top or $src_top = $opts{src_miny};
2551 defined $src_top or $src_top = 0;
2553 my $width = $opts{width};
2554 if (!defined $width && defined $opts{src_maxx}) {
2555 $width = $opts{src_maxx} - $src_left;
2557 defined $width or $width = $src->getwidth() - $src_left;
2559 my $height = $opts{height};
2560 if (!defined $height && defined $opts{src_maxy}) {
2561 $height = $opts{src_maxy} - $src_top;
2563 defined $height or $height = $src->getheight() - $src_top;
2565 my $combine = $self->_combine($opts{combine}, 'normal');
2568 unless ($opts{mask}{IMG}) {
2569 $self->_set_error("compose: mask parameter empty image");
2573 my $mask_left = $opts{mask_left};
2574 defined $mask_left or $mask_left = $opts{mask_minx};
2575 defined $mask_left or $mask_left = 0;
2577 my $mask_top = $opts{mask_top};
2578 defined $mask_top or $mask_top = $opts{mask_miny};
2579 defined $mask_top or $mask_top = 0;
2581 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2582 $left, $top, $src_left, $src_top,
2583 $mask_left, $mask_top, $width, $height,
2584 $combine, $opts{opacity})) {
2585 $self->_set_error(Imager->_error_as_msg);
2590 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2591 $width, $height, $combine, $opts{opacity})) {
2592 $self->_set_error(Imager->_error_as_msg);
2603 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2605 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2606 $dir = $xlate{$opts{'dir'}};
2607 return $self if i_flipxy($self->{IMG}, $dir);
2615 unless (defined wantarray) {
2616 my @caller = caller;
2617 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2621 if (defined $opts{right}) {
2622 my $degrees = $opts{right};
2624 $degrees += 360 * int(((-$degrees)+360)/360);
2626 $degrees = $degrees % 360;
2627 if ($degrees == 0) {
2628 return $self->copy();
2630 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2631 my $result = Imager->new();
2632 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2636 $self->{ERRSTR} = $self->_error_as_msg();
2641 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2645 elsif (defined $opts{radians} || defined $opts{degrees}) {
2646 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2648 my $back = $opts{back};
2649 my $result = Imager->new;
2651 $back = _color($back);
2653 $self->_set_error(Imager->errstr);
2657 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2660 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2662 if ($result->{IMG}) {
2666 $self->{ERRSTR} = $self->_error_as_msg();
2671 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2676 sub matrix_transform {
2680 unless (defined wantarray) {
2681 my @caller = caller;
2682 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2686 if ($opts{matrix}) {
2687 my $xsize = $opts{xsize} || $self->getwidth;
2688 my $ysize = $opts{ysize} || $self->getheight;
2690 my $result = Imager->new;
2692 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2693 $opts{matrix}, $opts{back})
2697 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2705 $self->{ERRSTR} = "matrix parameter required";
2711 *yatf = \&matrix_transform;
2713 # These two are supported for legacy code only
2716 return Imager::Color->new(@_);
2720 return Imager::Color::set(@_);
2723 # Draws a box between the specified corner points.
2726 my $raw = $self->{IMG};
2729 $self->{ERRSTR}='empty input image';
2735 my ($xmin, $ymin, $xmax, $ymax);
2736 if (exists $opts{'box'}) {
2737 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2738 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2739 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2740 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2743 defined($xmin = $opts{xmin}) or $xmin = 0;
2744 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2745 defined($ymin = $opts{ymin}) or $ymin = 0;
2746 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2749 if ($opts{filled}) {
2750 my $color = $opts{'color'};
2752 if (defined $color) {
2753 unless (_is_color_object($color)) {
2754 $color = _color($color);
2756 $self->{ERRSTR} = $Imager::ERRSTR;
2762 $color = i_color_new(255,255,255,255);
2765 if ($color->isa("Imager::Color")) {
2766 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2769 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2772 elsif ($opts{fill}) {
2773 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2774 # assume it's a hash ref
2775 require 'Imager/Fill.pm';
2776 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2777 $self->{ERRSTR} = $Imager::ERRSTR;
2781 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2784 my $color = $opts{'color'};
2785 if (defined $color) {
2786 unless (_is_color_object($color)) {
2787 $color = _color($color);
2789 $self->{ERRSTR} = $Imager::ERRSTR;
2795 $color = i_color_new(255, 255, 255, 255);
2798 $self->{ERRSTR} = $Imager::ERRSTR;
2801 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2809 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2810 my $dflcl= [ 255, 255, 255, 255];
2815 'r'=>_min($self->getwidth(),$self->getheight())/3,
2816 'x'=>$self->getwidth()/2,
2817 'y'=>$self->getheight()/2,
2824 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2825 # assume it's a hash ref
2826 require 'Imager/Fill.pm';
2827 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2828 $self->{ERRSTR} = $Imager::ERRSTR;
2832 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2833 $opts{'d2'}, $opts{fill}{fill});
2835 elsif ($opts{filled}) {
2836 my $color = _color($opts{'color'});
2838 $self->{ERRSTR} = $Imager::ERRSTR;
2841 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2842 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2846 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2847 $opts{'d1'}, $opts{'d2'}, $color);
2851 my $color = _color($opts{'color'});
2852 if ($opts{d2} - $opts{d1} >= 360) {
2853 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2856 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2862 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2863 # assume it's a hash ref
2864 require 'Imager/Fill.pm';
2865 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2866 $self->{ERRSTR} = $Imager::ERRSTR;
2870 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2871 $opts{'d2'}, $opts{fill}{fill});
2874 my $color = _color($opts{'color'});
2876 $self->{ERRSTR} = $Imager::ERRSTR;
2879 if ($opts{filled}) {
2880 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2881 $opts{'d1'}, $opts{'d2'}, $color);
2884 if ($opts{d1} == 0 && $opts{d2} == 361) {
2885 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2888 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2894 $self->_set_error($self->_error_as_msg);
2901 # Draws a line from one point to the other
2902 # the endpoint is set if the endp parameter is set which it is by default.
2903 # to turn of the endpoint being set use endp=>0 when calling line.
2907 my $dflcl=i_color_new(0,0,0,0);
2908 my %opts=(color=>$dflcl,
2911 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2913 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2914 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2916 my $color = _color($opts{'color'});
2918 $self->{ERRSTR} = $Imager::ERRSTR;
2922 $opts{antialias} = $opts{aa} if defined $opts{aa};
2923 if ($opts{antialias}) {
2924 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2925 $color, $opts{endp});
2927 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2928 $color, $opts{endp});
2933 # Draws a line between an ordered set of points - It more or less just transforms this
2934 # into a list of lines.
2938 my ($pt,$ls,@points);
2939 my $dflcl=i_color_new(0,0,0,0);
2940 my %opts=(color=>$dflcl,@_);
2942 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2944 if (exists($opts{points})) { @points=@{$opts{points}}; }
2945 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2946 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2949 # print Dumper(\@points);
2951 my $color = _color($opts{'color'});
2953 $self->{ERRSTR} = $Imager::ERRSTR;
2956 $opts{antialias} = $opts{aa} if defined $opts{aa};
2957 if ($opts{antialias}) {
2960 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2967 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2977 my ($pt,$ls,@points);
2978 my $dflcl = i_color_new(0,0,0,0);
2979 my %opts = (color=>$dflcl, @_);
2981 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2983 if (exists($opts{points})) {
2984 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2985 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2988 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2989 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2992 if ($opts{'fill'}) {
2993 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2994 # assume it's a hash ref
2995 require 'Imager/Fill.pm';
2996 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2997 $self->{ERRSTR} = $Imager::ERRSTR;
3001 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
3002 $opts{'fill'}{'fill'});
3005 my $color = _color($opts{'color'});
3007 $self->{ERRSTR} = $Imager::ERRSTR;
3010 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3017 # this the multipoint bezier curve
3018 # this is here more for testing that actual usage since
3019 # this is not a good algorithm. Usually the curve would be
3020 # broken into smaller segments and each done individually.
3024 my ($pt,$ls,@points);
3025 my $dflcl=i_color_new(0,0,0,0);
3026 my %opts=(color=>$dflcl,@_);
3028 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3030 if (exists $opts{points}) {
3031 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3032 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3035 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3036 $self->{ERRSTR}='Missing or invalid points.';
3040 my $color = _color($opts{'color'});
3042 $self->{ERRSTR} = $Imager::ERRSTR;
3045 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3051 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3054 unless (exists $opts{'x'} && exists $opts{'y'}) {
3055 $self->{ERRSTR} = "missing seed x and y parameters";
3059 if ($opts{border}) {
3060 my $border = _color($opts{border});
3062 $self->_set_error($Imager::ERRSTR);
3066 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3067 # assume it's a hash ref
3068 require Imager::Fill;
3069 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3070 $self->{ERRSTR} = $Imager::ERRSTR;
3074 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3075 $opts{fill}{fill}, $border);
3078 my $color = _color($opts{'color'});
3080 $self->{ERRSTR} = $Imager::ERRSTR;
3083 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3090 $self->{ERRSTR} = $self->_error_as_msg();
3096 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3097 # assume it's a hash ref
3098 require 'Imager/Fill.pm';
3099 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3100 $self->{ERRSTR} = $Imager::ERRSTR;
3104 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3107 my $color = _color($opts{'color'});
3109 $self->{ERRSTR} = $Imager::ERRSTR;
3112 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3118 $self->{ERRSTR} = $self->_error_as_msg();
3125 my ($self, %opts) = @_;
3127 my $color = $opts{color};
3128 unless (defined $color) {
3129 $color = $self->{fg};
3130 defined $color or $color = NC(255, 255, 255);
3133 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3134 $color = _color($color)
3138 unless (exists $opts{'x'} && exists $opts{'y'}) {
3139 $self->{ERRSTR} = 'missing x and y parameters';
3145 if (ref $x && ref $y) {
3146 unless (@$x == @$y) {
3147 $self->{ERRSTR} = 'length of x and y mismatch';
3151 if ($color->isa('Imager::Color')) {
3152 for my $i (0..$#{$opts{'x'}}) {
3153 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3158 for my $i (0..$#{$opts{'x'}}) {
3159 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3167 if ($color->isa('Imager::Color')) {
3168 i_ppix($self->{IMG}, $x, $y, $color)
3172 i_ppixf($self->{IMG}, $x, $y, $color)
3183 my %opts = ( "type"=>'8bit', @_);
3185 unless (exists $opts{'x'} && exists $opts{'y'}) {
3186 $self->{ERRSTR} = 'missing x and y parameters';
3192 if (ref $x && ref $y) {
3193 unless (@$x == @$y) {
3194 $self->{ERRSTR} = 'length of x and y mismatch';
3198 if ($opts{"type"} eq '8bit') {
3199 for my $i (0..$#{$opts{'x'}}) {
3200 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3204 for my $i (0..$#{$opts{'x'}}) {
3205 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3208 return wantarray ? @result : \@result;
3211 if ($opts{"type"} eq '8bit') {
3212 return i_get_pixel($self->{IMG}, $x, $y);
3215 return i_gpixf($self->{IMG}, $x, $y);
3224 my %opts = ( type => '8bit', x=>0, @_);
3226 $self->_valid_image or return;
3228 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3230 unless (defined $opts{'y'}) {
3231 $self->_set_error("missing y parameter");
3235 if ($opts{type} eq '8bit') {
3236 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3239 elsif ($opts{type} eq 'float') {
3240 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3243 elsif ($opts{type} eq 'index') {
3244 unless (i_img_type($self->{IMG})) {
3245 $self->_set_error("type => index only valid on paletted images");
3248 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3252 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3259 my %opts = ( x=>0, @_);
3261 $self->_valid_image or return;
3263 unless (defined $opts{'y'}) {
3264 $self->_set_error("missing y parameter");
3269 if (ref $opts{pixels} && @{$opts{pixels}}) {
3270 # try to guess the type
3271 if ($opts{pixels}[0]->isa('Imager::Color')) {
3272 $opts{type} = '8bit';
3274 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3275 $opts{type} = 'float';
3278 $self->_set_error("missing type parameter and could not guess from pixels");
3284 $opts{type} = '8bit';
3288 if ($opts{type} eq '8bit') {
3289 if (ref $opts{pixels}) {
3290 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3293 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3296 elsif ($opts{type} eq 'float') {
3297 if (ref $opts{pixels}) {
3298 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3301 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3304 elsif ($opts{type} eq 'index') {
3305 if (ref $opts{pixels}) {
3306 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3309 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3313 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3320 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3322 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3324 unless (defined $opts{'y'}) {
3325 $self->_set_error("missing y parameter");
3329 unless ($opts{channels}) {
3330 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3333 if ($opts{target}) {
3334 my $target = $opts{target};
3335 my $offset = $opts{offset};
3336 if ($opts{type} eq '8bit') {
3337 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3338 $opts{y}, @{$opts{channels}})
3340 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3341 return scalar(@samples);
3343 elsif ($opts{type} eq 'float') {
3344 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3345 $opts{y}, @{$opts{channels}});
3346 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3347 return scalar(@samples);
3349 elsif ($opts{type} =~ /^(\d+)bit$/) {
3353 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3354 $opts{y}, $bits, $target,
3355 $offset, @{$opts{channels}});
3356 unless (defined $count) {
3357 $self->_set_error(Imager->_error_as_msg);
3364 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3369 if ($opts{type} eq '8bit') {
3370 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3371 $opts{y}, @{$opts{channels}});
3373 elsif ($opts{type} eq 'float') {
3374 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3375 $opts{y}, @{$opts{channels}});
3377 elsif ($opts{type} =~ /^(\d+)bit$/) {
3381 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3382 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3387 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3395 my %opts = ( x => 0, offset => 0, @_ );
3397 unless ($self->{IMG}) {
3398 $self->_set_error('setsamples: empty input image');
3402 unless(defined $opts{data} && ref $opts{data}) {
3403 $self->_set_error('setsamples: data parameter missing or invalid');
3407 unless ($opts{channels}) {
3408 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3411 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3412 $self->_set_error('setsamples: type parameter missing or invalid');
3417 unless (defined $opts{width}) {
3418 $opts{width} = $self->getwidth() - $opts{x};
3421 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3422 $opts{channels}, $opts{data}, $opts{offset},
3424 unless (defined $count) {
3425 $self->_set_error(Imager->_error_as_msg);
3432 # make an identity matrix of the given size
3436 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3437 for my $c (0 .. ($size-1)) {
3438 $matrix->[$c][$c] = 1;
3443 # general function to convert an image
3445 my ($self, %opts) = @_;
3448 unless (defined wantarray) {
3449 my @caller = caller;
3450 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3454 # the user can either specify a matrix or preset
3455 # the matrix overrides the preset
3456 if (!exists($opts{matrix})) {
3457 unless (exists($opts{preset})) {
3458 $self->{ERRSTR} = "convert() needs a matrix or preset";
3462 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3463 # convert to greyscale, keeping the alpha channel if any
3464 if ($self->getchannels == 3) {
3465 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3467 elsif ($self->getchannels == 4) {
3468 # preserve the alpha channel
3469 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3474 $matrix = _identity($self->getchannels);
3477 elsif ($opts{preset} eq 'noalpha') {
3478 # strip the alpha channel
3479 if ($self->getchannels == 2 or $self->getchannels == 4) {
3480 $matrix = _identity($self->getchannels);
3481 pop(@$matrix); # lose the alpha entry
3484 $matrix = _identity($self->getchannels);
3487 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3489 $matrix = [ [ 1 ] ];
3491 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3492 $matrix = [ [ 0, 1 ] ];
3494 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3495 $matrix = [ [ 0, 0, 1 ] ];
3497 elsif ($opts{preset} eq 'alpha') {
3498 if ($self->getchannels == 2 or $self->getchannels == 4) {
3499 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3502 # the alpha is just 1 <shrug>
3503 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3506 elsif ($opts{preset} eq 'rgb') {
3507 if ($self->getchannels == 1) {
3508 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3510 elsif ($self->getchannels == 2) {
3511 # preserve the alpha channel
3512 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3515 $matrix = _identity($self->getchannels);
3518 elsif ($opts{preset} eq 'addalpha') {
3519 if ($self->getchannels == 1) {
3520 $matrix = _identity(2);
3522 elsif ($self->getchannels == 3) {
3523 $matrix = _identity(4);
3526 $matrix = _identity($self->getchannels);
3530 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3536 $matrix = $opts{matrix};
3539 my $new = Imager->new;
3540 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3541 unless ($new->{IMG}) {
3542 # most likely a bad matrix
3543 $self->{ERRSTR} = _error_as_msg();
3549 # combine channels from multiple input images, a class method
3551 my ($class, %opts) = @_;
3553 my $src = delete $opts{src};
3555 $class->_set_error("src parameter missing");
3560 for my $img (@$src) {
3561 unless (eval { $img->isa("Imager") }) {
3562 $class->_set_error("src must contain image objects");
3565 unless ($img->{IMG}) {
3566 $class->_set_error("empty input image");
3569 push @imgs, $img->{IMG};
3572 if (my $channels = delete $opts{channels}) {
3573 $result = i_combine(\@imgs, $channels);
3576 $result = i_combine(\@imgs);
3579 $class->_set_error($class->_error_as_msg);
3583 my $img = $class->new;
3584 $img->{IMG} = $result;
3590 # general function to map an image through lookup tables
3593 my ($self, %opts) = @_;
3594 my @chlist = qw( red green blue alpha );
3596 if (!exists($opts{'maps'})) {
3597 # make maps from channel maps
3599 for $chnum (0..$#chlist) {
3600 if (exists $opts{$chlist[$chnum]}) {
3601 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3602 } elsif (exists $opts{'all'}) {
3603 $opts{'maps'}[$chnum] = $opts{'all'};
3607 if ($opts{'maps'} and $self->{IMG}) {
3608 i_map($self->{IMG}, $opts{'maps'} );
3614 my ($self, %opts) = @_;
3616 defined $opts{mindist} or $opts{mindist} = 0;
3618 defined $opts{other}
3619 or return $self->_set_error("No 'other' parameter supplied");
3620 defined $opts{other}{IMG}
3621 or return $self->_set_error("No image data in 'other' image");
3624 or return $self->_set_error("No image data");
3626 my $result = Imager->new;
3627 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3629 or return $self->_set_error($self->_error_as_msg());
3634 # destructive border - image is shrunk by one pixel all around
3637 my ($self,%opts)=@_;
3638 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3639 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3643 # Get the width of an image
3648 if (my $raw = $self->{IMG}) {
3649 return i_img_get_width($raw);
3652 $self->{ERRSTR} = 'image is empty'; return undef;
3656 # Get the height of an image
3661 if (my $raw = $self->{IMG}) {
3662 return i_img_get_height($raw);
3665 $self->{ERRSTR} = 'image is empty'; return undef;
3669 # Get number of channels in an image
3673 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3674 return i_img_getchannels($self->{IMG});
3681 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3682 return i_img_getmask($self->{IMG});
3690 if (!defined($self->{IMG})) {
3691 $self->{ERRSTR} = 'image is empty';
3694 unless (defined $opts{mask}) {
3695 $self->_set_error("mask parameter required");
3698 i_img_setmask( $self->{IMG} , $opts{mask} );
3703 # Get number of colors in an image
3707 my %opts=('maxcolors'=>2**30,@_);
3708 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3709 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3710 return ($rc==-1? undef : $rc);
3713 # Returns a reference to a hash. The keys are colour named (packed) and the
3714 # values are the number of pixels in this colour.
3715 sub getcolorusagehash {
3718 my %opts = ( maxcolors => 2**30, @_ );
3719 my $max_colors = $opts{maxcolors};
3720 unless (defined $max_colors && $max_colors > 0) {
3721 $self->_set_error('maxcolors must be a positive integer');
3725 unless (defined $self->{IMG}) {
3726 $self->_set_error('empty input image');
3730 my $channels= $self->getchannels;
3731 # We don't want to look at the alpha channel, because some gifs using it
3732 # doesn't define it for every colour (but only for some)
3733 $channels -= 1 if $channels == 2 or $channels == 4;
3735 my $height = $self->getheight;
3736 for my $y (0 .. $height - 1) {
3737 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3738 while (length $colors) {
3739 $color_use{ substr($colors, 0, $channels, '') }++;
3741 keys %color_use > $max_colors
3747 # This will return a ordered array of the colour usage. Kind of the sorted
3748 # version of the values of the hash returned by getcolorusagehash.
3749 # You might want to add safety checks and change the names, etc...
3753 my %opts = ( maxcolors => 2**30, @_ );
3754 my $max_colors = $opts{maxcolors};
3755 unless (defined $max_colors && $max_colors > 0) {
3756 $self->_set_error('maxcolors must be a positive integer');
3760 unless (defined $self->{IMG}) {
3761 $self->_set_error('empty input image');
3765 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3768 # draw string to an image
3772 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3774 my %input=('x'=>0, 'y'=>0, @_);
3775 defined($input{string}) or $input{string} = $input{text};
3777 unless(defined $input{string}) {
3778 $self->{ERRSTR}="missing required parameter 'string'";
3782 unless($input{font}) {
3783 $self->{ERRSTR}="missing required parameter 'font'";
3787 unless ($input{font}->draw(image=>$self, %input)) {
3799 unless ($self->{IMG}) {
3800 $self->{ERRSTR}='empty input image';
3809 my %input=('x'=>0, 'y'=>0, @_);
3810 defined $input{string}
3811 or $input{string} = $input{text};
3813 unless(exists $input{string}) {
3814 $self->_set_error("missing required parameter 'string'");
3818 unless($input{font}) {
3819 $self->_set_error("missing required parameter 'font'");
3824 unless (@result = $input{font}->align(image=>$img, %input)) {
3828 return wantarray ? @result : $result[0];
3831 my @file_limit_names = qw/width height bytes/;
3833 sub set_file_limits {
3840 @values{@file_limit_names} = (0) x @file_limit_names;
3843 @values{@file_limit_names} = i_get_image_file_limits();
3846 for my $key (keys %values) {
3847 defined $opts{$key} and $values{$key} = $opts{$key};
3850 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3853 sub get_file_limits {
3854 i_get_image_file_limits();
3857 # Shortcuts that can be exported
3859 sub newcolor { Imager::Color->new(@_); }
3860 sub newfont { Imager::Font->new(@_); }
3862 require Imager::Color::Float;
3863 return Imager::Color::Float->new(@_);
3866 *NC=*newcolour=*newcolor;
3873 #### Utility routines
3876 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3880 my ($self, $msg) = @_;
3883 $self->{ERRSTR} = $msg;
3891 # Default guess for the type of an image from extension
3893 sub def_guess_type {
3896 $ext=($name =~ m/\.([^\.]+)$/)[0];
3897 return 'tiff' if ($ext =~ m/^tiff?$/);
3898 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3899 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3900 return 'png' if ($ext eq "png");
3901 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3902 return 'tga' if ($ext eq "tga");
3903 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3904 return 'gif' if ($ext eq "gif");
3905 return 'raw' if ($ext eq "raw");
3906 return lc $ext; # best guess
3911 return @combine_types;
3914 # get the minimum of a list
3918 for(@_) { if ($_<$mx) { $mx=$_; }}
3922 # get the maximum of a list
3926 for(@_) { if ($_>$mx) { $mx=$_; }}
3930 # string stuff for iptc headers
3934 $str = substr($str,3);
3935 $str =~ s/[\n\r]//g;
3942 # A little hack to parse iptc headers.
3947 my($caption,$photogr,$headln,$credit);
3949 my $str=$self->{IPTCRAW};
3954 @ar=split(/8BIM/,$str);
3959 @sar=split(/\034\002/);
3960 foreach $item (@sar) {
3961 if ($item =~ m/^x/) {
3962 $caption = _clean($item);
3965 if ($item =~ m/^P/) {
3966 $photogr = _clean($item);
3969 if ($item =~ m/^i/) {
3970 $headln = _clean($item);
3973 if ($item =~ m/^n/) {
3974 $credit = _clean($item);
3980 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3987 or die "Only C language supported";
3989 require Imager::ExtUtils;
3990 return Imager::ExtUtils->inline_config;
3993 # threads shouldn't try to close raw Imager objects
3994 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3997 # this serves two purposes:
3998 # - a class method to load the file support modules included with Image
3999 # (or were included, once the library dependent modules are split out)
4000 # - something for Module::ScanDeps to analyze
4001 # https://rt.cpan.org/Ticket/Display.html?id=6566
4003 eval { require Imager::File::GIF };
4004 eval { require Imager::File::JPEG };
4005 eval { require Imager::File::PNG };
4006 eval { require Imager::File::SGI };
4007 eval { require Imager::File::TIFF };
4008 eval { require Imager::File::ICO };
4009 eval { require Imager::Font::W32 };
4010 eval { require Imager::Font::FT2 };
4011 eval { require Imager::Font::T1 };
4014 # backward compatibility for %formats
4015 package Imager::FORMATS;
4017 use constant IX_FORMATS => 0;
4018 use constant IX_LIST => 1;
4019 use constant IX_INDEX => 2;
4020 use constant IX_CLASSES => 3;
4023 my ($class, $formats, $classes) = @_;
4025 return bless [ $formats, [ ], 0, $classes ], $class;
4029 my ($self, $key) = @_;
4031 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4034 my $loaded = Imager::_load_file($file, \$error);
4039 if ($error =~ /^Can't locate /) {
4040 $error = "Can't locate $file";
4042 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4045 $self->[IX_FORMATS]{$key} = $value;
4051 my ($self, $key) = @_;
4053 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4055 $self->[IX_CLASSES]{$key} or return undef;
4057 return $self->_check($key);
4061 die "%Imager::formats is not user monifiable";
4065 die "%Imager::formats is not user monifiable";
4069 die "%Imager::formats is not user monifiable";
4073 my ($self, $key) = @_;
4075 if (exists $self->[IX_FORMATS]{$key}) {
4076 my $value = $self->[IX_FORMATS]{$key}
4081 $self->_check($key) or return 1==0;
4089 unless (@{$self->[IX_LIST]}) {
4091 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4092 keys %{$self->[IX_FORMATS]};
4094 for my $key (keys %{$self->[IX_CLASSES]}) {
4095 $self->[IX_FORMATS]{$key} and next;
4097 and push @{$self->[IX_LIST]}, $key;
4101 @{$self->[IX_LIST]} or return;
4102 $self->[IX_INDEX] = 1;
4103 return $self->[IX_LIST][0];
4109 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4112 return $self->[IX_LIST][$self->[IX_INDEX]++];
4118 return scalar @{$self->[IX_LIST]};
4123 # Below is the stub of documentation for your module. You better edit it!
4127 Imager - Perl extension for Generating 24 bit Images
4137 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4142 # see Imager::Files for information on the read() method
4143 my $img = Imager->new(file=>$file)
4144 or die Imager->errstr();
4146 $file =~ s/\.[^.]*$//;
4148 # Create smaller version
4149 # documented in Imager::Transformations
4150 my $thumb = $img->scale(scalefactor=>.3);
4152 # Autostretch individual channels
4153 $thumb->filter(type=>'autolevels');
4155 # try to save in one of these formats
4158 for $format ( qw( png gif jpeg tiff ppm ) ) {
4159 # Check if given format is supported
4160 if ($Imager::formats{$format}) {
4161 $file.="_low.$format";
4162 print "Storing image as: $file\n";
4163 # documented in Imager::Files
4164 $thumb->write(file=>$file) or
4172 Imager is a module for creating and altering images. It can read and
4173 write various image formats, draw primitive shapes like lines,and
4174 polygons, blend multiple images together in various ways, scale, crop,
4175 render text and more.
4177 =head2 Overview of documentation
4183 Imager - This document - Synopsis, Example, Table of Contents and
4188 L<Imager::Tutorial> - a brief introduction to Imager.
4192 L<Imager::Cookbook> - how to do various things with Imager.
4196 L<Imager::ImageTypes> - Basics of constructing image objects with
4197 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4198 8/16/double bits/channel, color maps, channel masks, image tags, color
4199 quantization. Also discusses basic image information methods.
4203 L<Imager::Files> - IO interaction, reading/writing images, format
4208 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4213 L<Imager::Color> - Color specification.
4217 L<Imager::Fill> - Fill pattern specification.
4221 L<Imager::Font> - General font rendering, bounding boxes and font
4226 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4227 blending, pasting, convert and map.
4231 L<Imager::Engines> - Programmable transformations through
4232 C<transform()>, C<transform2()> and C<matrix_transform()>.
4236 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4241 L<Imager::Expr> - Expressions for evaluation engine used by
4246 L<Imager::Matrix2d> - Helper class for affine transformations.
4250 L<Imager::Fountain> - Helper for making gradient profiles.
4254 L<Imager::API> - using Imager's C API
4258 L<Imager::APIRef> - API function reference
4262 L<Imager::Inline> - using Imager's C API from Inline::C
4266 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4270 =head2 Basic Overview
4272 An Image object is created with C<$img = Imager-E<gt>new()>.
4275 $img=Imager->new(); # create empty image
4276 $img->read(file=>'lena.png',type=>'png') or # read image from file
4277 die $img->errstr(); # give an explanation
4278 # if something failed
4280 or if you want to create an empty image:
4282 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4284 This example creates a completely black image of width 400 and height
4287 =head1 ERROR HANDLING
4289 In general a method will return false when it fails, if it does use
4290 the C<errstr()> method to find out why:
4296 Returns the last error message in that context.
4298 If the last error you received was from calling an object method, such
4299 as read, call errstr() as an object method to find out why:
4301 my $image = Imager->new;
4302 $image->read(file => 'somefile.gif')
4303 or die $image->errstr;
4305 If it was a class method then call errstr() as a class method:
4307 my @imgs = Imager->read_multi(file => 'somefile.gif')
4308 or die Imager->errstr;
4310 Note that in some cases object methods are implemented in terms of
4311 class methods so a failing object method may set both.
4315 The C<Imager-E<gt>new> method is described in detail in
4316 L<Imager::ImageTypes>.
4320 Where to find information on methods for Imager class objects.
4322 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4325 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4327 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4330 arc() - L<Imager::Draw/arc()> - draw a filled arc
4332 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4335 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4337 circle() - L<Imager::Draw/circle()> - draw a filled circle
4339 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4342 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4343 colors in an image's palette (paletted images only)
4345 combine() - L<Imager::Transformations/combine()> - combine channels
4346 from one or more images.
4348 combines() - L<Imager::Draw/combines()> - return a list of the
4349 different combine type keywords
4351 compose() - L<Imager::Transformations/compose()> - compose one image
4354 convert() - L<Imager::Transformations/"Color transformations"> -
4355 transform the color space
4357 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4360 crop() - L<Imager::Transformations/crop()> - extract part of an image
4362 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4363 used to guess the output file format based on the output file name
4365 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4367 difference() - L<Imager::Filters/"Image Difference"> - produce a
4368 difference images from two input images.
4370 errstr() - L</"Basic Overview"> - the error from the last failed
4373 filter() - L<Imager::Filters> - image filtering
4375 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4376 palette, if it has one
4378 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4381 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4384 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4385 samples per pixel for an image
4387 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4388 different colors used by an image (works for direct color images)
4390 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4391 palette, if it has one
4393 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4395 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4397 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4399 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4402 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4404 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4407 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4408 row or partial row of pixels.
4410 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4411 row or partial row of pixels.
4413 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4416 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4419 init() - L<Imager::ImageTypes/init()>
4421 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4422 image write functions should write the image in their bilevel (blank
4423 and white, no gray levels) format
4425 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4428 line() - L<Imager::Draw/line()> - draw an interval
4430 load_plugin() - L<Imager::Filters/load_plugin()>
4432 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4435 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4438 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4440 matrix_transform() - L<Imager::Engines/matrix_transform()>
4442 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4444 NC() - L<Imager::Handy/NC()>
4446 NCF() - L<Imager::Handy/NCF()>
4448 new() - L<Imager::ImageTypes/new()>
4450 newcolor() - L<Imager::Handy/newcolor()>
4452 newcolour() - L<Imager::Handy/newcolour()>
4454 newfont() - L<Imager::Handy/newfont()>
4456 NF() - L<Imager::Handy/NF()>
4458 open() - L<Imager::Files> - an alias for read()
4460 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4464 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4467 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4470 polygon() - L<Imager::Draw/polygon()>
4472 polyline() - L<Imager::Draw/polyline()>
4474 preload() - L<Imager::Files/preload()>
4476 read() - L<Imager::Files> - read a single image from an image file
4478 read_multi() - L<Imager::Files> - read multiple images from an image
4481 read_types() - L<Imager::Files/read_types()> - list image types Imager
4484 register_filter() - L<Imager::Filters/register_filter()>
4486 register_reader() - L<Imager::Files/register_reader()>
4488 register_writer() - L<Imager::Files/register_writer()>
4490 rotate() - L<Imager::Transformations/rotate()>
4492 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4493 onto an image and use the alpha channel
4495 scale() - L<Imager::Transformations/scale()>
4497 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4499 scaleX() - L<Imager::Transformations/scaleX()>
4501 scaleY() - L<Imager::Transformations/scaleY()>
4503 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4506 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4508 setmask() - L<Imager::ImageTypes/setmask()>
4510 setpixel() - L<Imager::Draw/setpixel()>
4512 setsamples() - L<Imager::Draw/setsamples()>
4514 setscanline() - L<Imager::Draw/setscanline()>
4516 settag() - L<Imager::ImageTypes/settag()>
4518 string() - L<Imager::Draw/string()> - draw text on an image
4520 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4522 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4524 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4526 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4528 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4529 double per sample image.
4531 transform() - L<Imager::Engines/"transform()">
4533 transform2() - L<Imager::Engines/"transform2()">
4535 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4537 unload_plugin() - L<Imager::Filters/unload_plugin()>
4539 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4542 write() - L<Imager::Files> - write an image to a file
4544 write_multi() - L<Imager::Files> - write multiple image to an image
4547 write_types() - L<Imager::Files/read_types()> - list image types Imager
4550 =head1 CONCEPT INDEX
4552 animated GIF - L<Imager::Files/"Writing an animated GIF">
4554 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4555 L<Imager::ImageTypes/"Common Tags">.
4557 blend - alpha blending one image onto another
4558 L<Imager::Transformations/rubthrough()>
4560 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4562 boxes, drawing - L<Imager::Draw/box()>
4564 changes between image - L<Imager::Filters/"Image Difference">
4566 channels, combine into one image - L<Imager::Transformations/combine()>
4568 color - L<Imager::Color>
4570 color names - L<Imager::Color>, L<Imager::Color::Table>
4572 combine modes - L<Imager::Draw/"Combine Types">
4574 compare images - L<Imager::Filters/"Image Difference">
4576 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4578 convolution - L<Imager::Filters/conv>
4580 cropping - L<Imager::Transformations/crop()>
4582 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4584 C<diff> images - L<Imager::Filters/"Image Difference">
4586 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4587 L<Imager::Cookbook/"Image spatial resolution">
4589 drawing boxes - L<Imager::Draw/box()>
4591 drawing lines - L<Imager::Draw/line()>
4593 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4595 error message - L</"ERROR HANDLING">
4597 files, font - L<Imager::Font>
4599 files, image - L<Imager::Files>
4601 filling, types of fill - L<Imager::Fill>
4603 filling, boxes - L<Imager::Draw/box()>
4605 filling, flood fill - L<Imager::Draw/flood_fill()>
4607 flood fill - L<Imager::Draw/flood_fill()>
4609 fonts - L<Imager::Font>
4611 fonts, drawing with - L<Imager::Draw/string()>,
4612 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4614 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4616 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4618 fountain fill - L<Imager::Fill/"Fountain fills">,
4619 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4620 L<Imager::Filters/gradgen>
4622 GIF files - L<Imager::Files/"GIF">
4624 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4626 gradient fill - L<Imager::Fill/"Fountain fills">,
4627 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4628 L<Imager::Filters/gradgen>
4630 gray scale, convert image to - L<Imager::Transformations/convert()>
4632 gaussian blur - L<Imager::Filters/gaussian>
4634 hatch fills - L<Imager::Fill/"Hatched fills">
4636 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4638 invert image - L<Imager::Filters/hardinvert>,
4639 L<Imager::Filters/hardinvertall>
4641 JPEG - L<Imager::Files/"JPEG">
4643 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4645 lines, drawing - L<Imager::Draw/line()>
4647 matrix - L<Imager::Matrix2d>,
4648 L<Imager::Engines/"Matrix Transformations">,
4649 L<Imager::Font/transform()>
4651 metadata, image - L<Imager::ImageTypes/"Tags">
4653 mosaic - L<Imager::Filters/mosaic>
4655 noise, filter - L<Imager::Filters/noise>
4657 noise, rendered - L<Imager::Filters/turbnoise>,
4658 L<Imager::Filters/radnoise>
4660 paste - L<Imager::Transformations/paste()>,
4661 L<Imager::Transformations/rubthrough()>
4663 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4664 L<Imager::ImageTypes/new()>
4666 =for stopwords posterize
4668 posterize - L<Imager::Filters/postlevels>
4670 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4672 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4674 rectangles, drawing - L<Imager::Draw/box()>
4676 resizing an image - L<Imager::Transformations/scale()>,
4677 L<Imager::Transformations/crop()>
4679 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4681 saving an image - L<Imager::Files>
4683 scaling - L<Imager::Transformations/scale()>
4685 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4687 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4689 size, image - L<Imager::ImageTypes/getwidth()>,
4690 L<Imager::ImageTypes/getheight()>
4692 size, text - L<Imager::Font/bounding_box()>
4694 tags, image metadata - L<Imager::ImageTypes/"Tags">
4696 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4697 L<Imager::Font::Wrap>
4699 text, wrapping text in an area - L<Imager::Font::Wrap>
4701 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4703 tiles, color - L<Imager::Filters/mosaic>
4705 transparent images - L<Imager::ImageTypes>,
4706 L<Imager::Cookbook/"Transparent PNG">
4708 =for stopwords unsharp
4710 unsharp mask - L<Imager::Filters/unsharpmask>
4712 watermark - L<Imager::Filters/watermark>
4714 writing an image to a file - L<Imager::Files>
4718 Imager doesn't support perl threads.
4720 Imager has limited code to prevent double frees if you create images,
4721 colors etc, and then create a thread, but has no code to prevent two
4722 threads entering Imager's error handling code, and none is likely to
4727 The best place to get help with Imager is the mailing list.
4729 To subscribe send a message with C<subscribe> in the body to:
4731 imager-devel+request@molar.is
4737 L<http://www.molar.is/en/lists/imager-devel/>
4741 where you can also find the mailing list archive.
4743 You can report bugs by pointing your browser at:
4747 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4751 or by sending an email to:
4755 bug-Imager@rt.cpan.org
4759 Please remember to include the versions of Imager, perl, supporting
4760 libraries, and any relevant code. If you have specific images that
4761 cause the problems, please include those too.
4763 If you don't want to publish your email address on a mailing list you
4764 can use CPAN::Forum:
4766 http://www.cpanforum.com/dist/Imager
4768 You will need to register to post.
4770 =head1 CONTRIBUTING TO IMAGER
4776 If you like or dislike Imager, you can add a public review of Imager
4779 http://cpanratings.perl.org/dist/Imager
4781 =for stopwords Bitcard
4783 This requires a Bitcard account (http://www.bitcard.org).
4785 You can also send email to the maintainer below.
4787 If you send me a bug report via email, it will be copied to Request
4792 I accept patches, preferably against the main branch in subversion.
4793 You should include an explanation of the reason for why the patch is
4796 Your patch should include regression tests where possible, otherwise
4797 it will be delayed until I get a chance to write them.
4801 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
4803 Arnar M. Hrafnkelsson is the original author of Imager.
4805 Many others have contributed to Imager, please see the C<README> for a
4810 Imager is licensed under the same terms as perl itself.
4813 makeblendedfont Fontforge
4815 A test font, FT2/fontfiles/MMOne.pfb, contains a Postscript operator
4816 definition copyrighted by Adobe. See F<adobe.txt> in the source for
4817 license information.
4821 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4822 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4823 L<Imager::Font>(3), L<Imager::Transformations>(3),
4824 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4825 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4827 L<http://imager.perl.org/>
4829 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4831 Other perl imaging modules include:
4833 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).