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) = @_;
1342 return $input->{io};
1344 elsif ($input->{fd}) {
1345 return io_new_fd($input->{fd});
1347 elsif ($input->{fh}) {
1348 my $fd = fileno($input->{fh});
1349 unless (defined $fd) {
1350 $self->_set_error("Handle in fh option not opened");
1354 my $oldfh = select($input->{fh});
1355 # flush anything that's buffered, and make sure anything else is flushed
1358 return io_new_fd($fd);
1360 elsif ($input->{file}) {
1361 my $fh = new IO::File($input->{file},"w+");
1363 $self->_set_error("Could not open file $input->{file}: $!");
1366 binmode($fh) or die;
1367 return (io_new_fd(fileno($fh)), $fh);
1369 elsif ($input->{data}) {
1370 return io_new_bufchain();
1372 elsif ($input->{callback} || $input->{writecb}) {
1373 if ($input->{maxbuffer}) {
1374 return io_new_cb($input->{callback} || $input->{writecb},
1376 $input->{seekcb}, $input->{closecb},
1377 $input->{maxbuffer});
1380 return io_new_cb($input->{callback} || $input->{writecb},
1382 $input->{seekcb}, $input->{closecb});
1386 $self->_set_error("file/fd/fh/data/callback parameter missing");
1391 # Read an image from file
1397 if (defined($self->{IMG})) {
1398 # let IIM_DESTROY do the destruction, since the image may be
1399 # referenced from elsewhere
1400 #i_img_destroy($self->{IMG});
1401 undef($self->{IMG});
1404 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1406 my $type = $input{'type'};
1408 $type = i_test_format_probe($IO, -1);
1412 $self->_set_error('type parameter missing and not possible to guess from extension');
1416 _reader_autoload($type);
1418 if ($readers{$type} && $readers{$type}{single}) {
1419 return $readers{$type}{single}->($self, $IO, %input);
1422 unless ($formats_low{$type}) {
1423 my $read_types = join ', ', sort Imager->read_types();
1424 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1428 my $allow_incomplete = $input{allow_incomplete};
1429 defined $allow_incomplete or $allow_incomplete = 0;
1431 if ( $type eq 'pnm' ) {
1432 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1433 if ( !defined($self->{IMG}) ) {
1434 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1437 $self->{DEBUG} && print "loading a pnm file\n";
1441 if ( $type eq 'bmp' ) {
1442 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1443 if ( !defined($self->{IMG}) ) {
1444 $self->{ERRSTR}=$self->_error_as_msg();
1447 $self->{DEBUG} && print "loading a bmp file\n";
1450 if ( $type eq 'gif' ) {
1451 if ($input{colors} && !ref($input{colors})) {
1452 # must be a reference to a scalar that accepts the colour map
1453 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1456 if ($input{'gif_consolidate'}) {
1457 if ($input{colors}) {
1459 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1461 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1465 $self->{IMG} =i_readgif_wiol( $IO );
1469 my $page = $input{'page'};
1470 defined $page or $page = 0;
1471 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1472 if ($self->{IMG} && $input{colors}) {
1473 ${ $input{colors} } =
1474 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1478 if ( !defined($self->{IMG}) ) {
1479 $self->{ERRSTR}=$self->_error_as_msg();
1482 $self->{DEBUG} && print "loading a gif file\n";
1485 if ( $type eq 'tga' ) {
1486 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1487 if ( !defined($self->{IMG}) ) {
1488 $self->{ERRSTR}=$self->_error_as_msg();
1491 $self->{DEBUG} && print "loading a tga file\n";
1494 if ( $type eq 'raw' ) {
1495 unless ( $input{xsize} && $input{ysize} ) {
1496 $self->_set_error('missing xsize or ysize parameter for raw');
1500 my $interleave = _first($input{raw_interleave}, $input{interleave});
1501 unless (defined $interleave) {
1502 my @caller = caller;
1503 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1506 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1507 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1509 $self->{IMG} = i_readraw_wiol( $IO,
1515 if ( !defined($self->{IMG}) ) {
1516 $self->{ERRSTR}=$self->_error_as_msg();
1519 $self->{DEBUG} && print "loading a raw file\n";
1525 sub register_reader {
1526 my ($class, %opts) = @_;
1529 or die "register_reader called with no type parameter\n";
1531 my $type = $opts{type};
1533 defined $opts{single} || defined $opts{multiple}
1534 or die "register_reader called with no single or multiple parameter\n";
1536 $readers{$type} = { };
1537 if ($opts{single}) {
1538 $readers{$type}{single} = $opts{single};
1540 if ($opts{multiple}) {
1541 $readers{$type}{multiple} = $opts{multiple};
1547 sub register_writer {
1548 my ($class, %opts) = @_;
1551 or die "register_writer called with no type parameter\n";
1553 my $type = $opts{type};
1555 defined $opts{single} || defined $opts{multiple}
1556 or die "register_writer called with no single or multiple parameter\n";
1558 $writers{$type} = { };
1559 if ($opts{single}) {
1560 $writers{$type}{single} = $opts{single};
1562 if ($opts{multiple}) {
1563 $writers{$type}{multiple} = $opts{multiple};
1574 grep($file_formats{$_}, keys %formats),
1575 qw(ico sgi), # formats not handled directly, but supplied with Imager
1586 grep($file_formats{$_}, keys %formats),
1587 qw(ico sgi), # formats not handled directly, but supplied with Imager
1594 my ($file, $error) = @_;
1596 if ($attempted_to_load{$file}) {
1597 if ($file_load_errors{$file}) {
1598 $$error = $file_load_errors{$file};
1606 local $SIG{__DIE__};
1608 ++$attempted_to_load{$file};
1616 my $work = $@ || "Unknown error loading $file";
1618 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1619 $work =~ s/\n/\\n/g;
1620 $file_load_errors{$file} = $work;
1627 # probes for an Imager::File::whatever module
1628 sub _reader_autoload {
1631 return if $formats_low{$type} || $readers{$type};
1633 return unless $type =~ /^\w+$/;
1635 my $file = "Imager/File/\U$type\E.pm";
1638 my $loaded = _load_file($file, \$error);
1639 if (!$loaded && $error =~ /^Can't locate /) {
1640 my $filer = "Imager/File/\U$type\EReader.pm";
1641 $loaded = _load_file($filer, \$error);
1642 if ($error =~ /^Can't locate /) {
1643 $error = "Can't locate $file or $filer";
1647 $reader_load_errors{$type} = $error;
1651 # probes for an Imager::File::whatever module
1652 sub _writer_autoload {
1655 return if $formats_low{$type} || $writers{$type};
1657 return unless $type =~ /^\w+$/;
1659 my $file = "Imager/File/\U$type\E.pm";
1662 my $loaded = _load_file($file, \$error);
1663 if (!$loaded && $error =~ /^Can't locate /) {
1664 my $filew = "Imager/File/\U$type\EWriter.pm";
1665 $loaded = _load_file($filew, \$error);
1666 if ($error =~ /^Can't locate /) {
1667 $error = "Can't locate $file or $filew";
1671 $writer_load_errors{$type} = $error;
1675 sub _fix_gif_positions {
1676 my ($opts, $opt, $msg, @imgs) = @_;
1678 my $positions = $opts->{'gif_positions'};
1680 for my $pos (@$positions) {
1681 my ($x, $y) = @$pos;
1682 my $img = $imgs[$index++];
1683 $img->settag(name=>'gif_left', value=>$x);
1684 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1686 $$msg .= "replaced with the gif_left and gif_top tags";
1691 gif_each_palette=>'gif_local_map',
1692 interlace => 'gif_interlace',
1693 gif_delays => 'gif_delay',
1694 gif_positions => \&_fix_gif_positions,
1695 gif_loop_count => 'gif_loop',
1698 # options that should be converted to colors
1699 my %color_opts = map { $_ => 1 } qw/i_background/;
1702 my ($self, $opts, $prefix, @imgs) = @_;
1704 for my $opt (keys %$opts) {
1706 if ($obsolete_opts{$opt}) {
1707 my $new = $obsolete_opts{$opt};
1708 my $msg = "Obsolete option $opt ";
1710 $new->($opts, $opt, \$msg, @imgs);
1713 $msg .= "replaced with the $new tag ";
1716 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1717 warn $msg if $warn_obsolete && $^W;
1719 next unless $tagname =~ /^\Q$prefix/;
1720 my $value = $opts->{$opt};
1721 if ($color_opts{$opt}) {
1722 $value = _color($value);
1724 $self->_set_error($Imager::ERRSTR);
1729 if (UNIVERSAL::isa($value, "Imager::Color")) {
1730 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1731 for my $img (@imgs) {
1732 $img->settag(name=>$tagname, value=>$tag);
1735 elsif (ref($value) eq 'ARRAY') {
1736 for my $i (0..$#$value) {
1737 my $val = $value->[$i];
1739 if (UNIVERSAL::isa($val, "Imager::Color")) {
1740 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1742 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1745 $self->_set_error("Unknown reference type " . ref($value) .
1746 " supplied in array for $opt");
1752 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1757 $self->_set_error("Unknown reference type " . ref($value) .
1758 " supplied for $opt");
1763 # set it as a tag for every image
1764 for my $img (@imgs) {
1765 $img->settag(name=>$tagname, value=>$value);
1773 # Write an image to file
1776 my %input=(jpegquality=>75,
1786 $self->_set_opts(\%input, "i_", $self)
1789 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1791 my $type = $input{'type'};
1792 if (!$type and $input{file}) {
1793 $type = $FORMATGUESS->($input{file});
1796 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1800 _writer_autoload($type);
1803 if ($writers{$type} && $writers{$type}{single}) {
1804 ($IO, $fh) = $self->_get_writer_io(\%input)
1807 $writers{$type}{single}->($self, $IO, %input, type => $type)
1811 if (!$formats_low{$type}) {
1812 my $write_types = join ', ', sort Imager->write_types();
1813 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1817 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1820 if ( $type eq 'pnm' ) {
1821 $self->_set_opts(\%input, "pnm_", $self)
1823 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1824 $self->{ERRSTR} = $self->_error_as_msg();
1827 $self->{DEBUG} && print "writing a pnm file\n";
1829 elsif ( $type eq 'raw' ) {
1830 $self->_set_opts(\%input, "raw_", $self)
1832 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1833 $self->{ERRSTR} = $self->_error_as_msg();
1836 $self->{DEBUG} && print "writing a raw file\n";
1838 elsif ( $type eq 'bmp' ) {
1839 $self->_set_opts(\%input, "bmp_", $self)
1841 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1842 $self->{ERRSTR} = $self->_error_as_msg;
1845 $self->{DEBUG} && print "writing a bmp file\n";
1847 elsif ( $type eq 'tga' ) {
1848 $self->_set_opts(\%input, "tga_", $self)
1851 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1852 $self->{ERRSTR}=$self->_error_as_msg();
1855 $self->{DEBUG} && print "writing a tga file\n";
1859 if (exists $input{'data'}) {
1860 my $data = io_slurp($IO);
1862 $self->{ERRSTR}='Could not slurp from buffer';
1865 ${$input{data}} = $data;
1871 my ($class, $opts, @images) = @_;
1873 my $type = $opts->{type};
1875 if (!$type && $opts->{'file'}) {
1876 $type = $FORMATGUESS->($opts->{'file'});
1879 $class->_set_error('type parameter missing and not possible to guess from extension');
1882 # translate to ImgRaw
1883 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1884 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1887 $class->_set_opts($opts, "i_", @images)
1889 my @work = map $_->{IMG}, @images;
1891 _writer_autoload($type);
1894 if ($writers{$type} && $writers{$type}{multiple}) {
1895 ($IO, $file) = $class->_get_writer_io($opts, $type)
1898 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1902 if (!$formats{$type}) {
1903 my $write_types = join ', ', sort Imager->write_types();
1904 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1908 ($IO, $file) = $class->_get_writer_io($opts, $type)
1911 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1915 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1920 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1926 if (exists $opts->{'data'}) {
1927 my $data = io_slurp($IO);
1929 Imager->_set_error('Could not slurp from buffer');
1932 ${$opts->{data}} = $data;
1937 # read multiple images from a file
1939 my ($class, %opts) = @_;
1941 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1944 my $type = $opts{'type'};
1946 $type = i_test_format_probe($IO, -1);
1949 if ($opts{file} && !$type) {
1951 $type = $FORMATGUESS->($opts{file});
1955 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1959 _reader_autoload($type);
1961 if ($readers{$type} && $readers{$type}{multiple}) {
1962 return $readers{$type}{multiple}->($IO, %opts);
1965 unless ($formats{$type}) {
1966 my $read_types = join ', ', sort Imager->read_types();
1967 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1972 if ($type eq 'pnm') {
1973 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1976 my $img = Imager->new;
1977 if ($img->read(%opts, io => $IO, type => $type)) {
1980 Imager->_set_error($img->errstr);
1985 $ERRSTR = _error_as_msg();
1989 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1993 # Destroy an Imager object
1997 # delete $instances{$self};
1998 if (defined($self->{IMG})) {
1999 # the following is now handled by the XS DESTROY method for
2000 # Imager::ImgRaw object
2001 # Re-enabling this will break virtual images
2002 # tested for in t/t020masked.t
2003 # i_img_destroy($self->{IMG});
2004 undef($self->{IMG});
2006 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2010 # Perform an inplace filter of an image
2011 # that is the image will be overwritten with the data
2017 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2019 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2021 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2022 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2025 if ($filters{$input{'type'}}{names}) {
2026 my $names = $filters{$input{'type'}}{names};
2027 for my $name (keys %$names) {
2028 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2029 $input{$name} = $names->{$name}{$input{$name}};
2033 if (defined($filters{$input{'type'}}{defaults})) {
2034 %hsh=( image => $self->{IMG},
2036 %{$filters{$input{'type'}}{defaults}},
2039 %hsh=( image => $self->{IMG},
2044 my @cs=@{$filters{$input{'type'}}{callseq}};
2047 if (!defined($hsh{$_})) {
2048 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2053 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2054 &{$filters{$input{'type'}}{callsub}}(%hsh);
2057 chomp($self->{ERRSTR} = $@);
2063 $self->{DEBUG} && print "callseq is: @cs\n";
2064 $self->{DEBUG} && print "matching callseq is: @b\n";
2069 sub register_filter {
2071 my %hsh = ( defaults => {}, @_ );
2074 or die "register_filter() with no type\n";
2075 defined $hsh{callsub}
2076 or die "register_filter() with no callsub\n";
2077 defined $hsh{callseq}
2078 or die "register_filter() with no callseq\n";
2080 exists $filters{$hsh{type}}
2083 $filters{$hsh{type}} = \%hsh;
2088 sub scale_calculate {
2091 my %opts = ('type'=>'max', @_);
2093 # none of these should be references
2094 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2095 if (defined $opts{$name} && ref $opts{$name}) {
2096 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2101 my ($x_scale, $y_scale);
2102 my $width = $opts{width};
2103 my $height = $opts{height};
2105 defined $width or $width = $self->getwidth;
2106 defined $height or $height = $self->getheight;
2109 unless (defined $width && defined $height) {
2110 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2115 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2116 $x_scale = $opts{'xscalefactor'};
2117 $y_scale = $opts{'yscalefactor'};
2119 elsif ($opts{'xscalefactor'}) {
2120 $x_scale = $opts{'xscalefactor'};
2121 $y_scale = $opts{'scalefactor'} || $x_scale;
2123 elsif ($opts{'yscalefactor'}) {
2124 $y_scale = $opts{'yscalefactor'};
2125 $x_scale = $opts{'scalefactor'} || $y_scale;
2128 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2131 # work out the scaling
2132 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2133 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2134 $opts{ypixels} / $height );
2135 if ($opts{'type'} eq 'min') {
2136 $x_scale = $y_scale = _min($xpix,$ypix);
2138 elsif ($opts{'type'} eq 'max') {
2139 $x_scale = $y_scale = _max($xpix,$ypix);
2141 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2146 $self->_set_error('invalid value for type parameter');
2149 } elsif ($opts{xpixels}) {
2150 $x_scale = $y_scale = $opts{xpixels} / $width;
2152 elsif ($opts{ypixels}) {
2153 $x_scale = $y_scale = $opts{ypixels}/$height;
2155 elsif ($opts{constrain} && ref $opts{constrain}
2156 && $opts{constrain}->can('constrain')) {
2157 # we've been passed an Image::Math::Constrain object or something
2158 # that looks like one
2160 (undef, undef, $scalefactor)
2161 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2162 unless ($scalefactor) {
2163 $self->_set_error('constrain method failed on constrain parameter');
2166 $x_scale = $y_scale = $scalefactor;
2169 my $new_width = int($x_scale * $width + 0.5);
2170 $new_width > 0 or $new_width = 1;
2171 my $new_height = int($y_scale * $height + 0.5);
2172 $new_height > 0 or $new_height = 1;
2174 return ($x_scale, $y_scale, $new_width, $new_height);
2178 # Scale an image to requested size and return the scaled version
2182 my %opts = (qtype=>'normal' ,@_);
2183 my $img = Imager->new();
2184 my $tmp = Imager->new();
2186 unless (defined wantarray) {
2187 my @caller = caller;
2188 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2192 unless ($self->{IMG}) {
2193 $self->_set_error('empty input image');
2197 my ($x_scale, $y_scale, $new_width, $new_height) =
2198 $self->scale_calculate(%opts)
2201 if ($opts{qtype} eq 'normal') {
2202 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2203 if ( !defined($tmp->{IMG}) ) {
2204 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2207 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2208 if ( !defined($img->{IMG}) ) {
2209 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2215 elsif ($opts{'qtype'} eq 'preview') {
2216 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2217 if ( !defined($img->{IMG}) ) {
2218 $self->{ERRSTR}='unable to scale image';
2223 elsif ($opts{'qtype'} eq 'mixing') {
2224 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2225 unless ($img->{IMG}) {
2226 $self->_set_error(Imager->_error_as_msg);
2232 $self->_set_error('invalid value for qtype parameter');
2237 # Scales only along the X axis
2241 my %opts = ( scalefactor=>0.5, @_ );
2243 unless (defined wantarray) {
2244 my @caller = caller;
2245 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2249 unless ($self->{IMG}) {
2250 $self->{ERRSTR} = 'empty input image';
2254 my $img = Imager->new();
2256 my $scalefactor = $opts{scalefactor};
2258 if ($opts{pixels}) {
2259 $scalefactor = $opts{pixels} / $self->getwidth();
2262 unless ($self->{IMG}) {
2263 $self->{ERRSTR}='empty input image';
2267 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2269 if ( !defined($img->{IMG}) ) {
2270 $self->{ERRSTR} = 'unable to scale image';
2277 # Scales only along the Y axis
2281 my %opts = ( scalefactor => 0.5, @_ );
2283 unless (defined wantarray) {
2284 my @caller = caller;
2285 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2289 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2291 my $img = Imager->new();
2293 my $scalefactor = $opts{scalefactor};
2295 if ($opts{pixels}) {
2296 $scalefactor = $opts{pixels} / $self->getheight();
2299 unless ($self->{IMG}) {
2300 $self->{ERRSTR} = 'empty input image';
2303 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2305 if ( !defined($img->{IMG}) ) {
2306 $self->{ERRSTR} = 'unable to scale image';
2313 # Transform returns a spatial transformation of the input image
2314 # this moves pixels to a new location in the returned image.
2315 # NOTE - should make a utility function to check transforms for
2320 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2322 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2324 # print Dumper(\%opts);
2327 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2329 eval ("use Affix::Infix2Postfix;");
2332 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2335 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2336 {op=>'-',trans=>'Sub'},
2337 {op=>'*',trans=>'Mult'},
2338 {op=>'/',trans=>'Div'},
2339 {op=>'-','type'=>'unary',trans=>'u-'},
2341 {op=>'func','type'=>'unary'}],
2342 'grouping'=>[qw( \( \) )],
2343 'func'=>[qw( sin cos )],
2348 @xt=$I2P->translate($opts{'xexpr'});
2349 @yt=$I2P->translate($opts{'yexpr'});
2351 $numre=$I2P->{'numre'};
2354 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2355 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2356 @{$opts{'parm'}}=@pt;
2359 # print Dumper(\%opts);
2361 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2362 $self->{ERRSTR}='transform: no xopcodes given.';
2366 @op=@{$opts{'xopcodes'}};
2368 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2369 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2372 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2378 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2379 $self->{ERRSTR}='transform: no yopcodes given.';
2383 @op=@{$opts{'yopcodes'}};
2385 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2386 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2389 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2394 if ( !exists $opts{'parm'}) {
2395 $self->{ERRSTR}='transform: no parameter arg given.';
2399 # print Dumper(\@ropx);
2400 # print Dumper(\@ropy);
2401 # print Dumper(\@ropy);
2403 my $img = Imager->new();
2404 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2405 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2411 my ($opts, @imgs) = @_;
2413 require "Imager/Expr.pm";
2415 $opts->{variables} = [ qw(x y) ];
2416 my ($width, $height) = @{$opts}{qw(width height)};
2418 $width ||= $imgs[0]->getwidth();
2419 $height ||= $imgs[0]->getheight();
2421 for my $img (@imgs) {
2422 $opts->{constants}{"w$img_num"} = $img->getwidth();
2423 $opts->{constants}{"h$img_num"} = $img->getheight();
2424 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2425 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2430 $opts->{constants}{w} = $width;
2431 $opts->{constants}{cx} = $width/2;
2434 $Imager::ERRSTR = "No width supplied";
2438 $opts->{constants}{h} = $height;
2439 $opts->{constants}{cy} = $height/2;
2442 $Imager::ERRSTR = "No height supplied";
2445 my $code = Imager::Expr->new($opts);
2447 $Imager::ERRSTR = Imager::Expr::error();
2450 my $channels = $opts->{channels} || 3;
2451 unless ($channels >= 1 && $channels <= 4) {
2452 return Imager->_set_error("channels must be an integer between 1 and 4");
2455 my $img = Imager->new();
2456 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2457 $channels, $code->code(),
2458 $code->nregs(), $code->cregs(),
2459 [ map { $_->{IMG} } @imgs ]);
2460 if (!defined $img->{IMG}) {
2461 $Imager::ERRSTR = Imager->_error_as_msg();
2472 unless ($self->{IMG}) {
2473 $self->{ERRSTR}='empty input image';
2476 unless ($opts{src} && $opts{src}->{IMG}) {
2477 $self->{ERRSTR}='empty input image for src';
2481 %opts = (src_minx => 0,
2483 src_maxx => $opts{src}->getwidth(),
2484 src_maxy => $opts{src}->getheight(),
2488 defined $tx or $tx = $opts{left};
2489 defined $tx or $tx = 0;
2492 defined $ty or $ty = $opts{top};
2493 defined $ty or $ty = 0;
2495 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2496 $opts{src_minx}, $opts{src_miny},
2497 $opts{src_maxx}, $opts{src_maxy})) {
2498 $self->_set_error($self->_error_as_msg());
2515 unless ($self->{IMG}) {
2516 $self->_set_error("compose: empty input image");
2520 unless ($opts{src}) {
2521 $self->_set_error("compose: src parameter missing");
2525 unless ($opts{src}{IMG}) {
2526 $self->_set_error("compose: src parameter empty image");
2529 my $src = $opts{src};
2531 my $left = $opts{left};
2532 defined $left or $left = $opts{tx};
2533 defined $left or $left = 0;
2535 my $top = $opts{top};
2536 defined $top or $top = $opts{ty};
2537 defined $top or $top = 0;
2539 my $src_left = $opts{src_left};
2540 defined $src_left or $src_left = $opts{src_minx};
2541 defined $src_left or $src_left = 0;
2543 my $src_top = $opts{src_top};
2544 defined $src_top or $src_top = $opts{src_miny};
2545 defined $src_top or $src_top = 0;
2547 my $width = $opts{width};
2548 if (!defined $width && defined $opts{src_maxx}) {
2549 $width = $opts{src_maxx} - $src_left;
2551 defined $width or $width = $src->getwidth() - $src_left;
2553 my $height = $opts{height};
2554 if (!defined $height && defined $opts{src_maxy}) {
2555 $height = $opts{src_maxy} - $src_top;
2557 defined $height or $height = $src->getheight() - $src_top;
2559 my $combine = $self->_combine($opts{combine}, 'normal');
2562 unless ($opts{mask}{IMG}) {
2563 $self->_set_error("compose: mask parameter empty image");
2567 my $mask_left = $opts{mask_left};
2568 defined $mask_left or $mask_left = $opts{mask_minx};
2569 defined $mask_left or $mask_left = 0;
2571 my $mask_top = $opts{mask_top};
2572 defined $mask_top or $mask_top = $opts{mask_miny};
2573 defined $mask_top or $mask_top = 0;
2575 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2576 $left, $top, $src_left, $src_top,
2577 $mask_left, $mask_top, $width, $height,
2578 $combine, $opts{opacity})) {
2579 $self->_set_error(Imager->_error_as_msg);
2584 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2585 $width, $height, $combine, $opts{opacity})) {
2586 $self->_set_error(Imager->_error_as_msg);
2597 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2599 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2600 $dir = $xlate{$opts{'dir'}};
2601 return $self if i_flipxy($self->{IMG}, $dir);
2609 unless (defined wantarray) {
2610 my @caller = caller;
2611 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2615 if (defined $opts{right}) {
2616 my $degrees = $opts{right};
2618 $degrees += 360 * int(((-$degrees)+360)/360);
2620 $degrees = $degrees % 360;
2621 if ($degrees == 0) {
2622 return $self->copy();
2624 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2625 my $result = Imager->new();
2626 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2630 $self->{ERRSTR} = $self->_error_as_msg();
2635 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2639 elsif (defined $opts{radians} || defined $opts{degrees}) {
2640 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2642 my $back = $opts{back};
2643 my $result = Imager->new;
2645 $back = _color($back);
2647 $self->_set_error(Imager->errstr);
2651 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2654 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2656 if ($result->{IMG}) {
2660 $self->{ERRSTR} = $self->_error_as_msg();
2665 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2670 sub matrix_transform {
2674 unless (defined wantarray) {
2675 my @caller = caller;
2676 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2680 if ($opts{matrix}) {
2681 my $xsize = $opts{xsize} || $self->getwidth;
2682 my $ysize = $opts{ysize} || $self->getheight;
2684 my $result = Imager->new;
2686 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2687 $opts{matrix}, $opts{back})
2691 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2699 $self->{ERRSTR} = "matrix parameter required";
2705 *yatf = \&matrix_transform;
2707 # These two are supported for legacy code only
2710 return Imager::Color->new(@_);
2714 return Imager::Color::set(@_);
2717 # Draws a box between the specified corner points.
2720 my $raw = $self->{IMG};
2723 $self->{ERRSTR}='empty input image';
2729 my ($xmin, $ymin, $xmax, $ymax);
2730 if (exists $opts{'box'}) {
2731 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2732 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2733 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2734 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2737 defined($xmin = $opts{xmin}) or $xmin = 0;
2738 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2739 defined($ymin = $opts{ymin}) or $ymin = 0;
2740 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2743 if ($opts{filled}) {
2744 my $color = $opts{'color'};
2746 if (defined $color) {
2747 unless (_is_color_object($color)) {
2748 $color = _color($color);
2750 $self->{ERRSTR} = $Imager::ERRSTR;
2756 $color = i_color_new(255,255,255,255);
2759 if ($color->isa("Imager::Color")) {
2760 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2763 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2766 elsif ($opts{fill}) {
2767 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2768 # assume it's a hash ref
2769 require 'Imager/Fill.pm';
2770 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2771 $self->{ERRSTR} = $Imager::ERRSTR;
2775 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2778 my $color = $opts{'color'};
2779 if (defined $color) {
2780 unless (_is_color_object($color)) {
2781 $color = _color($color);
2783 $self->{ERRSTR} = $Imager::ERRSTR;
2789 $color = i_color_new(255, 255, 255, 255);
2792 $self->{ERRSTR} = $Imager::ERRSTR;
2795 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2803 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2804 my $dflcl= [ 255, 255, 255, 255];
2809 'r'=>_min($self->getwidth(),$self->getheight())/3,
2810 'x'=>$self->getwidth()/2,
2811 'y'=>$self->getheight()/2,
2818 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2819 # assume it's a hash ref
2820 require 'Imager/Fill.pm';
2821 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2822 $self->{ERRSTR} = $Imager::ERRSTR;
2826 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2827 $opts{'d2'}, $opts{fill}{fill});
2829 elsif ($opts{filled}) {
2830 my $color = _color($opts{'color'});
2832 $self->{ERRSTR} = $Imager::ERRSTR;
2835 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2836 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2840 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2841 $opts{'d1'}, $opts{'d2'}, $color);
2845 my $color = _color($opts{'color'});
2846 if ($opts{d2} - $opts{d1} >= 360) {
2847 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2850 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2856 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2857 # assume it's a hash ref
2858 require 'Imager/Fill.pm';
2859 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2860 $self->{ERRSTR} = $Imager::ERRSTR;
2864 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2865 $opts{'d2'}, $opts{fill}{fill});
2868 my $color = _color($opts{'color'});
2870 $self->{ERRSTR} = $Imager::ERRSTR;
2873 if ($opts{filled}) {
2874 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2875 $opts{'d1'}, $opts{'d2'}, $color);
2878 if ($opts{d1} == 0 && $opts{d2} == 361) {
2879 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2882 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2888 $self->_set_error($self->_error_as_msg);
2895 # Draws a line from one point to the other
2896 # the endpoint is set if the endp parameter is set which it is by default.
2897 # to turn of the endpoint being set use endp=>0 when calling line.
2901 my $dflcl=i_color_new(0,0,0,0);
2902 my %opts=(color=>$dflcl,
2905 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2907 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2908 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2910 my $color = _color($opts{'color'});
2912 $self->{ERRSTR} = $Imager::ERRSTR;
2916 $opts{antialias} = $opts{aa} if defined $opts{aa};
2917 if ($opts{antialias}) {
2918 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2919 $color, $opts{endp});
2921 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2922 $color, $opts{endp});
2927 # Draws a line between an ordered set of points - It more or less just transforms this
2928 # into a list of lines.
2932 my ($pt,$ls,@points);
2933 my $dflcl=i_color_new(0,0,0,0);
2934 my %opts=(color=>$dflcl,@_);
2936 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2938 if (exists($opts{points})) { @points=@{$opts{points}}; }
2939 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2940 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2943 # print Dumper(\@points);
2945 my $color = _color($opts{'color'});
2947 $self->{ERRSTR} = $Imager::ERRSTR;
2950 $opts{antialias} = $opts{aa} if defined $opts{aa};
2951 if ($opts{antialias}) {
2954 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2961 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2971 my ($pt,$ls,@points);
2972 my $dflcl = i_color_new(0,0,0,0);
2973 my %opts = (color=>$dflcl, @_);
2975 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2977 if (exists($opts{points})) {
2978 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2979 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2982 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2983 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2986 if ($opts{'fill'}) {
2987 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2988 # assume it's a hash ref
2989 require 'Imager/Fill.pm';
2990 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2991 $self->{ERRSTR} = $Imager::ERRSTR;
2995 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2996 $opts{'fill'}{'fill'});
2999 my $color = _color($opts{'color'});
3001 $self->{ERRSTR} = $Imager::ERRSTR;
3004 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3011 # this the multipoint bezier curve
3012 # this is here more for testing that actual usage since
3013 # this is not a good algorithm. Usually the curve would be
3014 # broken into smaller segments and each done individually.
3018 my ($pt,$ls,@points);
3019 my $dflcl=i_color_new(0,0,0,0);
3020 my %opts=(color=>$dflcl,@_);
3022 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3024 if (exists $opts{points}) {
3025 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3026 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3029 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3030 $self->{ERRSTR}='Missing or invalid points.';
3034 my $color = _color($opts{'color'});
3036 $self->{ERRSTR} = $Imager::ERRSTR;
3039 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3045 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3048 unless (exists $opts{'x'} && exists $opts{'y'}) {
3049 $self->{ERRSTR} = "missing seed x and y parameters";
3053 if ($opts{border}) {
3054 my $border = _color($opts{border});
3056 $self->_set_error($Imager::ERRSTR);
3060 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3061 # assume it's a hash ref
3062 require Imager::Fill;
3063 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3064 $self->{ERRSTR} = $Imager::ERRSTR;
3068 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3069 $opts{fill}{fill}, $border);
3072 my $color = _color($opts{'color'});
3074 $self->{ERRSTR} = $Imager::ERRSTR;
3077 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3084 $self->{ERRSTR} = $self->_error_as_msg();
3090 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3091 # assume it's a hash ref
3092 require 'Imager/Fill.pm';
3093 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3094 $self->{ERRSTR} = $Imager::ERRSTR;
3098 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3101 my $color = _color($opts{'color'});
3103 $self->{ERRSTR} = $Imager::ERRSTR;
3106 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3112 $self->{ERRSTR} = $self->_error_as_msg();
3119 my ($self, %opts) = @_;
3121 my $color = $opts{color};
3122 unless (defined $color) {
3123 $color = $self->{fg};
3124 defined $color or $color = NC(255, 255, 255);
3127 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3128 $color = _color($color)
3132 unless (exists $opts{'x'} && exists $opts{'y'}) {
3133 $self->{ERRSTR} = 'missing x and y parameters';
3139 if (ref $x && ref $y) {
3140 unless (@$x == @$y) {
3141 $self->{ERRSTR} = 'length of x and y mismatch';
3145 if ($color->isa('Imager::Color')) {
3146 for my $i (0..$#{$opts{'x'}}) {
3147 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3152 for my $i (0..$#{$opts{'x'}}) {
3153 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3161 if ($color->isa('Imager::Color')) {
3162 i_ppix($self->{IMG}, $x, $y, $color)
3166 i_ppixf($self->{IMG}, $x, $y, $color)
3177 my %opts = ( "type"=>'8bit', @_);
3179 unless (exists $opts{'x'} && exists $opts{'y'}) {
3180 $self->{ERRSTR} = 'missing x and y parameters';
3186 if (ref $x && ref $y) {
3187 unless (@$x == @$y) {
3188 $self->{ERRSTR} = 'length of x and y mismatch';
3192 if ($opts{"type"} eq '8bit') {
3193 for my $i (0..$#{$opts{'x'}}) {
3194 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3198 for my $i (0..$#{$opts{'x'}}) {
3199 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3202 return wantarray ? @result : \@result;
3205 if ($opts{"type"} eq '8bit') {
3206 return i_get_pixel($self->{IMG}, $x, $y);
3209 return i_gpixf($self->{IMG}, $x, $y);
3218 my %opts = ( type => '8bit', x=>0, @_);
3220 $self->_valid_image or return;
3222 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3224 unless (defined $opts{'y'}) {
3225 $self->_set_error("missing y parameter");
3229 if ($opts{type} eq '8bit') {
3230 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3233 elsif ($opts{type} eq 'float') {
3234 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3237 elsif ($opts{type} eq 'index') {
3238 unless (i_img_type($self->{IMG})) {
3239 $self->_set_error("type => index only valid on paletted images");
3242 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3246 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3253 my %opts = ( x=>0, @_);
3255 $self->_valid_image or return;
3257 unless (defined $opts{'y'}) {
3258 $self->_set_error("missing y parameter");
3263 if (ref $opts{pixels} && @{$opts{pixels}}) {
3264 # try to guess the type
3265 if ($opts{pixels}[0]->isa('Imager::Color')) {
3266 $opts{type} = '8bit';
3268 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3269 $opts{type} = 'float';
3272 $self->_set_error("missing type parameter and could not guess from pixels");
3278 $opts{type} = '8bit';
3282 if ($opts{type} eq '8bit') {
3283 if (ref $opts{pixels}) {
3284 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3287 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3290 elsif ($opts{type} eq 'float') {
3291 if (ref $opts{pixels}) {
3292 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3295 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3298 elsif ($opts{type} eq 'index') {
3299 if (ref $opts{pixels}) {
3300 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3303 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3307 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3314 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3316 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3318 unless (defined $opts{'y'}) {
3319 $self->_set_error("missing y parameter");
3323 unless ($opts{channels}) {
3324 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3327 if ($opts{target}) {
3328 my $target = $opts{target};
3329 my $offset = $opts{offset};
3330 if ($opts{type} eq '8bit') {
3331 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3332 $opts{y}, @{$opts{channels}})
3334 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3335 return scalar(@samples);
3337 elsif ($opts{type} eq 'float') {
3338 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3339 $opts{y}, @{$opts{channels}});
3340 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3341 return scalar(@samples);
3343 elsif ($opts{type} =~ /^(\d+)bit$/) {
3347 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3348 $opts{y}, $bits, $target,
3349 $offset, @{$opts{channels}});
3350 unless (defined $count) {
3351 $self->_set_error(Imager->_error_as_msg);
3358 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3363 if ($opts{type} eq '8bit') {
3364 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3365 $opts{y}, @{$opts{channels}});
3367 elsif ($opts{type} eq 'float') {
3368 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3369 $opts{y}, @{$opts{channels}});
3371 elsif ($opts{type} =~ /^(\d+)bit$/) {
3375 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3376 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3381 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3389 my %opts = ( x => 0, offset => 0, @_ );
3391 unless ($self->{IMG}) {
3392 $self->_set_error('setsamples: empty input image');
3396 unless(defined $opts{data} && ref $opts{data}) {
3397 $self->_set_error('setsamples: data parameter missing or invalid');
3401 unless ($opts{channels}) {
3402 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3405 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3406 $self->_set_error('setsamples: type parameter missing or invalid');
3411 unless (defined $opts{width}) {
3412 $opts{width} = $self->getwidth() - $opts{x};
3415 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3416 $opts{channels}, $opts{data}, $opts{offset},
3418 unless (defined $count) {
3419 $self->_set_error(Imager->_error_as_msg);
3426 # make an identity matrix of the given size
3430 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3431 for my $c (0 .. ($size-1)) {
3432 $matrix->[$c][$c] = 1;
3437 # general function to convert an image
3439 my ($self, %opts) = @_;
3442 unless (defined wantarray) {
3443 my @caller = caller;
3444 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3448 # the user can either specify a matrix or preset
3449 # the matrix overrides the preset
3450 if (!exists($opts{matrix})) {
3451 unless (exists($opts{preset})) {
3452 $self->{ERRSTR} = "convert() needs a matrix or preset";
3456 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3457 # convert to greyscale, keeping the alpha channel if any
3458 if ($self->getchannels == 3) {
3459 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3461 elsif ($self->getchannels == 4) {
3462 # preserve the alpha channel
3463 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3468 $matrix = _identity($self->getchannels);
3471 elsif ($opts{preset} eq 'noalpha') {
3472 # strip the alpha channel
3473 if ($self->getchannels == 2 or $self->getchannels == 4) {
3474 $matrix = _identity($self->getchannels);
3475 pop(@$matrix); # lose the alpha entry
3478 $matrix = _identity($self->getchannels);
3481 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3483 $matrix = [ [ 1 ] ];
3485 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3486 $matrix = [ [ 0, 1 ] ];
3488 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3489 $matrix = [ [ 0, 0, 1 ] ];
3491 elsif ($opts{preset} eq 'alpha') {
3492 if ($self->getchannels == 2 or $self->getchannels == 4) {
3493 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3496 # the alpha is just 1 <shrug>
3497 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3500 elsif ($opts{preset} eq 'rgb') {
3501 if ($self->getchannels == 1) {
3502 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3504 elsif ($self->getchannels == 2) {
3505 # preserve the alpha channel
3506 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3509 $matrix = _identity($self->getchannels);
3512 elsif ($opts{preset} eq 'addalpha') {
3513 if ($self->getchannels == 1) {
3514 $matrix = _identity(2);
3516 elsif ($self->getchannels == 3) {
3517 $matrix = _identity(4);
3520 $matrix = _identity($self->getchannels);
3524 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3530 $matrix = $opts{matrix};
3533 my $new = Imager->new;
3534 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3535 unless ($new->{IMG}) {
3536 # most likely a bad matrix
3537 $self->{ERRSTR} = _error_as_msg();
3543 # combine channels from multiple input images, a class method
3545 my ($class, %opts) = @_;
3547 my $src = delete $opts{src};
3549 $class->_set_error("src parameter missing");
3554 for my $img (@$src) {
3555 unless (eval { $img->isa("Imager") }) {
3556 $class->_set_error("src must contain image objects");
3559 unless ($img->{IMG}) {
3560 $class->_set_error("empty input image");
3563 push @imgs, $img->{IMG};
3566 if (my $channels = delete $opts{channels}) {
3567 $result = i_combine(\@imgs, $channels);
3570 $result = i_combine(\@imgs);
3573 $class->_set_error($class->_error_as_msg);
3577 my $img = $class->new;
3578 $img->{IMG} = $result;
3584 # general function to map an image through lookup tables
3587 my ($self, %opts) = @_;
3588 my @chlist = qw( red green blue alpha );
3590 if (!exists($opts{'maps'})) {
3591 # make maps from channel maps
3593 for $chnum (0..$#chlist) {
3594 if (exists $opts{$chlist[$chnum]}) {
3595 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3596 } elsif (exists $opts{'all'}) {
3597 $opts{'maps'}[$chnum] = $opts{'all'};
3601 if ($opts{'maps'} and $self->{IMG}) {
3602 i_map($self->{IMG}, $opts{'maps'} );
3608 my ($self, %opts) = @_;
3610 defined $opts{mindist} or $opts{mindist} = 0;
3612 defined $opts{other}
3613 or return $self->_set_error("No 'other' parameter supplied");
3614 defined $opts{other}{IMG}
3615 or return $self->_set_error("No image data in 'other' image");
3618 or return $self->_set_error("No image data");
3620 my $result = Imager->new;
3621 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3623 or return $self->_set_error($self->_error_as_msg());
3628 # destructive border - image is shrunk by one pixel all around
3631 my ($self,%opts)=@_;
3632 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3633 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3637 # Get the width of an image
3642 if (my $raw = $self->{IMG}) {
3643 return i_img_get_width($raw);
3646 $self->{ERRSTR} = 'image is empty'; return undef;
3650 # Get the height of an image
3655 if (my $raw = $self->{IMG}) {
3656 return i_img_get_height($raw);
3659 $self->{ERRSTR} = 'image is empty'; return undef;
3663 # Get number of channels in an image
3667 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3668 return i_img_getchannels($self->{IMG});
3675 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3676 return i_img_getmask($self->{IMG});
3684 if (!defined($self->{IMG})) {
3685 $self->{ERRSTR} = 'image is empty';
3688 unless (defined $opts{mask}) {
3689 $self->_set_error("mask parameter required");
3692 i_img_setmask( $self->{IMG} , $opts{mask} );
3697 # Get number of colors in an image
3701 my %opts=('maxcolors'=>2**30,@_);
3702 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3703 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3704 return ($rc==-1? undef : $rc);
3707 # Returns a reference to a hash. The keys are colour named (packed) and the
3708 # values are the number of pixels in this colour.
3709 sub getcolorusagehash {
3712 my %opts = ( maxcolors => 2**30, @_ );
3713 my $max_colors = $opts{maxcolors};
3714 unless (defined $max_colors && $max_colors > 0) {
3715 $self->_set_error('maxcolors must be a positive integer');
3719 unless (defined $self->{IMG}) {
3720 $self->_set_error('empty input image');
3724 my $channels= $self->getchannels;
3725 # We don't want to look at the alpha channel, because some gifs using it
3726 # doesn't define it for every colour (but only for some)
3727 $channels -= 1 if $channels == 2 or $channels == 4;
3729 my $height = $self->getheight;
3730 for my $y (0 .. $height - 1) {
3731 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3732 while (length $colors) {
3733 $color_use{ substr($colors, 0, $channels, '') }++;
3735 keys %color_use > $max_colors
3741 # This will return a ordered array of the colour usage. Kind of the sorted
3742 # version of the values of the hash returned by getcolorusagehash.
3743 # You might want to add safety checks and change the names, etc...
3747 my %opts = ( maxcolors => 2**30, @_ );
3748 my $max_colors = $opts{maxcolors};
3749 unless (defined $max_colors && $max_colors > 0) {
3750 $self->_set_error('maxcolors must be a positive integer');
3754 unless (defined $self->{IMG}) {
3755 $self->_set_error('empty input image');
3759 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3762 # draw string to an image
3766 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3768 my %input=('x'=>0, 'y'=>0, @_);
3769 defined($input{string}) or $input{string} = $input{text};
3771 unless(defined $input{string}) {
3772 $self->{ERRSTR}="missing required parameter 'string'";
3776 unless($input{font}) {
3777 $self->{ERRSTR}="missing required parameter 'font'";
3781 unless ($input{font}->draw(image=>$self, %input)) {
3793 unless ($self->{IMG}) {
3794 $self->{ERRSTR}='empty input image';
3803 my %input=('x'=>0, 'y'=>0, @_);
3804 defined $input{string}
3805 or $input{string} = $input{text};
3807 unless(exists $input{string}) {
3808 $self->_set_error("missing required parameter 'string'");
3812 unless($input{font}) {
3813 $self->_set_error("missing required parameter 'font'");
3818 unless (@result = $input{font}->align(image=>$img, %input)) {
3822 return wantarray ? @result : $result[0];
3825 my @file_limit_names = qw/width height bytes/;
3827 sub set_file_limits {
3834 @values{@file_limit_names} = (0) x @file_limit_names;
3837 @values{@file_limit_names} = i_get_image_file_limits();
3840 for my $key (keys %values) {
3841 defined $opts{$key} and $values{$key} = $opts{$key};
3844 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3847 sub get_file_limits {
3848 i_get_image_file_limits();
3851 # Shortcuts that can be exported
3853 sub newcolor { Imager::Color->new(@_); }
3854 sub newfont { Imager::Font->new(@_); }
3856 require Imager::Color::Float;
3857 return Imager::Color::Float->new(@_);
3860 *NC=*newcolour=*newcolor;
3867 #### Utility routines
3870 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3874 my ($self, $msg) = @_;
3877 $self->{ERRSTR} = $msg;
3885 # Default guess for the type of an image from extension
3887 sub def_guess_type {
3890 $ext=($name =~ m/\.([^\.]+)$/)[0];
3891 return 'tiff' if ($ext =~ m/^tiff?$/);
3892 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3893 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3894 return 'png' if ($ext eq "png");
3895 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3896 return 'tga' if ($ext eq "tga");
3897 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3898 return 'gif' if ($ext eq "gif");
3899 return 'raw' if ($ext eq "raw");
3900 return lc $ext; # best guess
3905 return @combine_types;
3908 # get the minimum of a list
3912 for(@_) { if ($_<$mx) { $mx=$_; }}
3916 # get the maximum of a list
3920 for(@_) { if ($_>$mx) { $mx=$_; }}
3924 # string stuff for iptc headers
3928 $str = substr($str,3);
3929 $str =~ s/[\n\r]//g;
3936 # A little hack to parse iptc headers.
3941 my($caption,$photogr,$headln,$credit);
3943 my $str=$self->{IPTCRAW};
3948 @ar=split(/8BIM/,$str);
3953 @sar=split(/\034\002/);
3954 foreach $item (@sar) {
3955 if ($item =~ m/^x/) {
3956 $caption = _clean($item);
3959 if ($item =~ m/^P/) {
3960 $photogr = _clean($item);
3963 if ($item =~ m/^i/) {
3964 $headln = _clean($item);
3967 if ($item =~ m/^n/) {
3968 $credit = _clean($item);
3974 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3981 or die "Only C language supported";
3983 require Imager::ExtUtils;
3984 return Imager::ExtUtils->inline_config;
3987 # threads shouldn't try to close raw Imager objects
3988 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3991 # this serves two purposes:
3992 # - a class method to load the file support modules included with Image
3993 # (or were included, once the library dependent modules are split out)
3994 # - something for Module::ScanDeps to analyze
3995 # https://rt.cpan.org/Ticket/Display.html?id=6566
3997 eval { require Imager::File::GIF };
3998 eval { require Imager::File::JPEG };
3999 eval { require Imager::File::PNG };
4000 eval { require Imager::File::SGI };
4001 eval { require Imager::File::TIFF };
4002 eval { require Imager::File::ICO };
4003 eval { require Imager::Font::W32 };
4004 eval { require Imager::Font::FT2 };
4005 eval { require Imager::Font::T1 };
4008 # backward compatibility for %formats
4009 package Imager::FORMATS;
4011 use constant IX_FORMATS => 0;
4012 use constant IX_LIST => 1;
4013 use constant IX_INDEX => 2;
4014 use constant IX_CLASSES => 3;
4017 my ($class, $formats, $classes) = @_;
4019 return bless [ $formats, [ ], 0, $classes ], $class;
4023 my ($self, $key) = @_;
4025 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4028 my $loaded = Imager::_load_file($file, \$error);
4033 if ($error =~ /^Can't locate /) {
4034 $error = "Can't locate $file";
4036 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4039 $self->[IX_FORMATS]{$key} = $value;
4045 my ($self, $key) = @_;
4047 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4049 $self->[IX_CLASSES]{$key} or return undef;
4051 return $self->_check($key);
4055 die "%Imager::formats is not user monifiable";
4059 die "%Imager::formats is not user monifiable";
4063 die "%Imager::formats is not user monifiable";
4067 my ($self, $key) = @_;
4069 if (exists $self->[IX_FORMATS]{$key}) {
4070 my $value = $self->[IX_FORMATS]{$key}
4075 $self->_check($key) or return 1==0;
4083 unless (@{$self->[IX_LIST]}) {
4085 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4086 keys %{$self->[IX_FORMATS]};
4088 for my $key (keys %{$self->[IX_CLASSES]}) {
4089 $self->[IX_FORMATS]{$key} and next;
4091 and push @{$self->[IX_LIST]}, $key;
4095 @{$self->[IX_LIST]} or return;
4096 $self->[IX_INDEX] = 1;
4097 return $self->[IX_LIST][0];
4103 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4106 return $self->[IX_LIST][$self->[IX_INDEX]++];
4112 return scalar @{$self->[IX_LIST]};
4117 # Below is the stub of documentation for your module. You better edit it!
4121 Imager - Perl extension for Generating 24 bit Images
4131 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4136 # see Imager::Files for information on the read() method
4137 my $img = Imager->new(file=>$file)
4138 or die Imager->errstr();
4140 $file =~ s/\.[^.]*$//;
4142 # Create smaller version
4143 # documented in Imager::Transformations
4144 my $thumb = $img->scale(scalefactor=>.3);
4146 # Autostretch individual channels
4147 $thumb->filter(type=>'autolevels');
4149 # try to save in one of these formats
4152 for $format ( qw( png gif jpeg tiff ppm ) ) {
4153 # Check if given format is supported
4154 if ($Imager::formats{$format}) {
4155 $file.="_low.$format";
4156 print "Storing image as: $file\n";
4157 # documented in Imager::Files
4158 $thumb->write(file=>$file) or
4166 Imager is a module for creating and altering images. It can read and
4167 write various image formats, draw primitive shapes like lines,and
4168 polygons, blend multiple images together in various ways, scale, crop,
4169 render text and more.
4171 =head2 Overview of documentation
4177 Imager - This document - Synopsis, Example, Table of Contents and
4182 L<Imager::Tutorial> - a brief introduction to Imager.
4186 L<Imager::Cookbook> - how to do various things with Imager.
4190 L<Imager::ImageTypes> - Basics of constructing image objects with
4191 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4192 8/16/double bits/channel, color maps, channel masks, image tags, color
4193 quantization. Also discusses basic image information methods.
4197 L<Imager::Files> - IO interaction, reading/writing images, format
4202 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4207 L<Imager::Color> - Color specification.
4211 L<Imager::Fill> - Fill pattern specification.
4215 L<Imager::Font> - General font rendering, bounding boxes and font
4220 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4221 blending, pasting, convert and map.
4225 L<Imager::Engines> - Programmable transformations through
4226 C<transform()>, C<transform2()> and C<matrix_transform()>.
4230 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4235 L<Imager::Expr> - Expressions for evaluation engine used by
4240 L<Imager::Matrix2d> - Helper class for affine transformations.
4244 L<Imager::Fountain> - Helper for making gradient profiles.
4248 L<Imager::API> - using Imager's C API
4252 L<Imager::APIRef> - API function reference
4256 L<Imager::Inline> - using Imager's C API from Inline::C
4260 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4264 =head2 Basic Overview
4266 An Image object is created with C<$img = Imager-E<gt>new()>.
4269 $img=Imager->new(); # create empty image
4270 $img->read(file=>'lena.png',type=>'png') or # read image from file
4271 die $img->errstr(); # give an explanation
4272 # if something failed
4274 or if you want to create an empty image:
4276 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4278 This example creates a completely black image of width 400 and height
4281 =head1 ERROR HANDLING
4283 In general a method will return false when it fails, if it does use
4284 the C<errstr()> method to find out why:
4290 Returns the last error message in that context.
4292 If the last error you received was from calling an object method, such
4293 as read, call errstr() as an object method to find out why:
4295 my $image = Imager->new;
4296 $image->read(file => 'somefile.gif')
4297 or die $image->errstr;
4299 If it was a class method then call errstr() as a class method:
4301 my @imgs = Imager->read_multi(file => 'somefile.gif')
4302 or die Imager->errstr;
4304 Note that in some cases object methods are implemented in terms of
4305 class methods so a failing object method may set both.
4309 The C<Imager-E<gt>new> method is described in detail in
4310 L<Imager::ImageTypes>.
4314 Where to find information on methods for Imager class objects.
4316 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4319 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4321 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4324 arc() - L<Imager::Draw/arc()> - draw a filled arc
4326 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4329 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4331 circle() - L<Imager::Draw/circle()> - draw a filled circle
4333 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4336 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4337 colors in an image's palette (paletted images only)
4339 combine() - L<Imager::Transformations/combine()> - combine channels
4340 from one or more images.
4342 combines() - L<Imager::Draw/combines()> - return a list of the
4343 different combine type keywords
4345 compose() - L<Imager::Transformations/compose()> - compose one image
4348 convert() - L<Imager::Transformations/"Color transformations"> -
4349 transform the color space
4351 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4354 crop() - L<Imager::Transformations/crop()> - extract part of an image
4356 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4357 used to guess the output file format based on the output file name
4359 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4361 difference() - L<Imager::Filters/"Image Difference"> - produce a
4362 difference images from two input images.
4364 errstr() - L</"Basic Overview"> - the error from the last failed
4367 filter() - L<Imager::Filters> - image filtering
4369 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4370 palette, if it has one
4372 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4375 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4378 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4379 samples per pixel for an image
4381 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4382 different colors used by an image (works for direct color images)
4384 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4385 palette, if it has one
4387 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4389 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4391 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4393 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4396 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4398 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4401 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4402 row or partial row of pixels.
4404 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4405 row or partial row of pixels.
4407 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4410 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4413 init() - L<Imager::ImageTypes/init()>
4415 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4416 image write functions should write the image in their bilevel (blank
4417 and white, no gray levels) format
4419 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4422 line() - L<Imager::Draw/line()> - draw an interval
4424 load_plugin() - L<Imager::Filters/load_plugin()>
4426 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4429 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4432 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4434 matrix_transform() - L<Imager::Engines/matrix_transform()>
4436 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4438 NC() - L<Imager::Handy/NC()>
4440 NCF() - L<Imager::Handy/NCF()>
4442 new() - L<Imager::ImageTypes/new()>
4444 newcolor() - L<Imager::Handy/newcolor()>
4446 newcolour() - L<Imager::Handy/newcolour()>
4448 newfont() - L<Imager::Handy/newfont()>
4450 NF() - L<Imager::Handy/NF()>
4452 open() - L<Imager::Files> - an alias for read()
4454 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4458 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4461 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4464 polygon() - L<Imager::Draw/polygon()>
4466 polyline() - L<Imager::Draw/polyline()>
4468 preload() - L<Imager::Files/preload()>
4470 read() - L<Imager::Files> - read a single image from an image file
4472 read_multi() - L<Imager::Files> - read multiple images from an image
4475 read_types() - L<Imager::Files/read_types()> - list image types Imager
4478 register_filter() - L<Imager::Filters/register_filter()>
4480 register_reader() - L<Imager::Files/register_reader()>
4482 register_writer() - L<Imager::Files/register_writer()>
4484 rotate() - L<Imager::Transformations/rotate()>
4486 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4487 onto an image and use the alpha channel
4489 scale() - L<Imager::Transformations/scale()>
4491 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4493 scaleX() - L<Imager::Transformations/scaleX()>
4495 scaleY() - L<Imager::Transformations/scaleY()>
4497 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4500 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4502 setmask() - L<Imager::ImageTypes/setmask()>
4504 setpixel() - L<Imager::Draw/setpixel()>
4506 setsamples() - L<Imager::Draw/setsamples()>
4508 setscanline() - L<Imager::Draw/setscanline()>
4510 settag() - L<Imager::ImageTypes/settag()>
4512 string() - L<Imager::Draw/string()> - draw text on an image
4514 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4516 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4518 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4520 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4522 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4523 double per sample image.
4525 transform() - L<Imager::Engines/"transform()">
4527 transform2() - L<Imager::Engines/"transform2()">
4529 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4531 unload_plugin() - L<Imager::Filters/unload_plugin()>
4533 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4536 write() - L<Imager::Files> - write an image to a file
4538 write_multi() - L<Imager::Files> - write multiple image to an image
4541 write_types() - L<Imager::Files/read_types()> - list image types Imager
4544 =head1 CONCEPT INDEX
4546 animated GIF - L<Imager::Files/"Writing an animated GIF">
4548 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4549 L<Imager::ImageTypes/"Common Tags">.
4551 blend - alpha blending one image onto another
4552 L<Imager::Transformations/rubthrough()>
4554 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4556 boxes, drawing - L<Imager::Draw/box()>
4558 changes between image - L<Imager::Filters/"Image Difference">
4560 channels, combine into one image - L<Imager::Transformations/combine()>
4562 color - L<Imager::Color>
4564 color names - L<Imager::Color>, L<Imager::Color::Table>
4566 combine modes - L<Imager::Draw/"Combine Types">
4568 compare images - L<Imager::Filters/"Image Difference">
4570 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4572 convolution - L<Imager::Filters/conv>
4574 cropping - L<Imager::Transformations/crop()>
4576 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4578 C<diff> images - L<Imager::Filters/"Image Difference">
4580 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4581 L<Imager::Cookbook/"Image spatial resolution">
4583 drawing boxes - L<Imager::Draw/box()>
4585 drawing lines - L<Imager::Draw/line()>
4587 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4589 error message - L</"ERROR HANDLING">
4591 files, font - L<Imager::Font>
4593 files, image - L<Imager::Files>
4595 filling, types of fill - L<Imager::Fill>
4597 filling, boxes - L<Imager::Draw/box()>
4599 filling, flood fill - L<Imager::Draw/flood_fill()>
4601 flood fill - L<Imager::Draw/flood_fill()>
4603 fonts - L<Imager::Font>
4605 fonts, drawing with - L<Imager::Draw/string()>,
4606 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4608 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4610 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4612 fountain fill - L<Imager::Fill/"Fountain fills">,
4613 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4614 L<Imager::Filters/gradgen>
4616 GIF files - L<Imager::Files/"GIF">
4618 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4620 gradient fill - L<Imager::Fill/"Fountain fills">,
4621 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4622 L<Imager::Filters/gradgen>
4624 gray scale, convert image to - L<Imager::Transformations/convert()>
4626 gaussian blur - L<Imager::Filters/gaussian>
4628 hatch fills - L<Imager::Fill/"Hatched fills">
4630 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4632 invert image - L<Imager::Filters/hardinvert>,
4633 L<Imager::Filters/hardinvertall>
4635 JPEG - L<Imager::Files/"JPEG">
4637 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4639 lines, drawing - L<Imager::Draw/line()>
4641 matrix - L<Imager::Matrix2d>,
4642 L<Imager::Engines/"Matrix Transformations">,
4643 L<Imager::Font/transform()>
4645 metadata, image - L<Imager::ImageTypes/"Tags">
4647 mosaic - L<Imager::Filters/mosaic>
4649 noise, filter - L<Imager::Filters/noise>
4651 noise, rendered - L<Imager::Filters/turbnoise>,
4652 L<Imager::Filters/radnoise>
4654 paste - L<Imager::Transformations/paste()>,
4655 L<Imager::Transformations/rubthrough()>
4657 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4658 L<Imager::ImageTypes/new()>
4660 =for stopwords posterize
4662 posterize - L<Imager::Filters/postlevels>
4664 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4666 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4668 rectangles, drawing - L<Imager::Draw/box()>
4670 resizing an image - L<Imager::Transformations/scale()>,
4671 L<Imager::Transformations/crop()>
4673 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4675 saving an image - L<Imager::Files>
4677 scaling - L<Imager::Transformations/scale()>
4679 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4681 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4683 size, image - L<Imager::ImageTypes/getwidth()>,
4684 L<Imager::ImageTypes/getheight()>
4686 size, text - L<Imager::Font/bounding_box()>
4688 tags, image metadata - L<Imager::ImageTypes/"Tags">
4690 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4691 L<Imager::Font::Wrap>
4693 text, wrapping text in an area - L<Imager::Font::Wrap>
4695 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4697 tiles, color - L<Imager::Filters/mosaic>
4699 transparent images - L<Imager::ImageTypes>,
4700 L<Imager::Cookbook/"Transparent PNG">
4702 =for stopwords unsharp
4704 unsharp mask - L<Imager::Filters/unsharpmask>
4706 watermark - L<Imager::Filters/watermark>
4708 writing an image to a file - L<Imager::Files>
4712 Imager doesn't support perl threads.
4714 Imager has limited code to prevent double frees if you create images,
4715 colors etc, and then create a thread, but has no code to prevent two
4716 threads entering Imager's error handling code, and none is likely to
4721 The best place to get help with Imager is the mailing list.
4723 To subscribe send a message with C<subscribe> in the body to:
4725 imager-devel+request@molar.is
4731 L<http://www.molar.is/en/lists/imager-devel/>
4735 where you can also find the mailing list archive.
4737 You can report bugs by pointing your browser at:
4741 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4745 or by sending an email to:
4749 bug-Imager@rt.cpan.org
4753 Please remember to include the versions of Imager, perl, supporting
4754 libraries, and any relevant code. If you have specific images that
4755 cause the problems, please include those too.
4757 If you don't want to publish your email address on a mailing list you
4758 can use CPAN::Forum:
4760 http://www.cpanforum.com/dist/Imager
4762 You will need to register to post.
4764 =head1 CONTRIBUTING TO IMAGER
4770 If you like or dislike Imager, you can add a public review of Imager
4773 http://cpanratings.perl.org/dist/Imager
4775 =for stopwords Bitcard
4777 This requires a Bitcard account (http://www.bitcard.org).
4779 You can also send email to the maintainer below.
4781 If you send me a bug report via email, it will be copied to Request
4786 I accept patches, preferably against the main branch in subversion.
4787 You should include an explanation of the reason for why the patch is
4790 Your patch should include regression tests where possible, otherwise
4791 it will be delayed until I get a chance to write them.
4795 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
4797 Arnar M. Hrafnkelsson is the original author of Imager.
4799 Many others have contributed to Imager, please see the C<README> for a
4804 Imager is licensed under the same terms as perl itself.
4807 makeblendedfont Fontforge
4809 A test font, FT2/fontfiles/MMOne.pfb, contains a Postscript operator
4810 definition copyrighted by Adobe. See F<adobe.txt> in the source for
4811 license information.
4815 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4816 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4817 L<Imager::Font>(3), L<Imager::Transformations>(3),
4818 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4819 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4821 L<http://imager.perl.org/>
4823 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4825 Other perl imaging modules include:
4827 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).