4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR $fontstate %OPCODES $I2P $FORMATGUESS $warn_obsolete);
130 # registered file readers
133 # registered file writers
136 # modules we attempted to autoload
137 my %attempted_to_load;
139 # library keys that are image file formats
140 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
142 # image pixel combine types
144 qw/none normal multiply dissolve add subtract diff lighten darken
145 hue saturation value color/;
147 @combine_types{@combine_types} = 0 .. $#combine_types;
148 $combine_types{mult} = $combine_types{multiply};
149 $combine_types{'sub'} = $combine_types{subtract};
150 $combine_types{sat} = $combine_types{saturation};
152 # this will be used to store global defaults at some point
161 XSLoader::load(Imager => $VERSION);
165 push @ISA, 'DynaLoader';
166 bootstrap Imager $VERSION;
173 png => "Imager::File::PNG",
174 gif => "Imager::File::GIF",
175 tiff => "Imager::File::TIFF",
176 jpeg => "Imager::File::JPEG",
179 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
182 Imager::Font::__init();
183 for(i_list_formats()) { $formats_low{$_}++; }
185 if (!$formats_low{'t1'} and !$formats_low{'tt'}
186 && !$formats_low{'ft2'} && !$formats_low{'w32'}) {
187 $fontstate='no font support';
189 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
193 # the members of the subhashes under %filters are:
194 # callseq - a list of the parameters to the underlying filter in the
195 # order they are passed
196 # callsub - a code ref that takes a named parameter list and calls the
198 # defaults - a hash of default values
199 # names - defines names for value of given parameters so if the names
200 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
201 # foo parameter, the filter will receive 1 for the foo
204 callseq => ['image','intensity'],
205 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
209 callseq => ['image', 'amount', 'subtype'],
210 defaults => { amount=>3,subtype=>0 },
211 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
214 $filters{hardinvert} ={
215 callseq => ['image'],
217 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
220 $filters{hardinvertall} =
222 callseq => ['image'],
224 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
227 $filters{autolevels} ={
228 callseq => ['image','lsat','usat','skew'],
229 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
230 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
233 $filters{turbnoise} ={
234 callseq => ['image'],
235 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
236 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
239 $filters{radnoise} ={
240 callseq => ['image'],
241 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
242 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
247 callseq => ['image', 'coef'],
252 i_conv($hsh{image},$hsh{coef})
253 or die Imager->_error_as_msg() . "\n";
259 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
260 defaults => { dist => 0 },
264 my @colors = @{$hsh{colors}};
267 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
271 $filters{nearest_color} =
273 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
278 # make sure the segments are specified with colors
280 for my $color (@{$hsh{colors}}) {
281 my $new_color = _color($color)
282 or die $Imager::ERRSTR."\n";
283 push @colors, $new_color;
286 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
288 or die Imager->_error_as_msg() . "\n";
291 $filters{gaussian} = {
292 callseq => [ 'image', 'stddev' ],
294 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
298 callseq => [ qw(image size) ],
299 defaults => { size => 20 },
300 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
304 callseq => [ qw(image bump elevation lightx lighty st) ],
305 defaults => { elevation=>0, st=> 2 },
308 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
309 $hsh{lightx}, $hsh{lighty}, $hsh{st});
312 $filters{bumpmap_complex} =
314 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
331 for my $cname (qw/Ia Il Is/) {
332 my $old = $hsh{$cname};
333 my $new_color = _color($old)
334 or die $Imager::ERRSTR, "\n";
335 $hsh{$cname} = $new_color;
337 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
338 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
339 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
343 $filters{postlevels} =
345 callseq => [ qw(image levels) ],
346 defaults => { levels => 10 },
347 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
349 $filters{watermark} =
351 callseq => [ qw(image wmark tx ty pixdiff) ],
352 defaults => { pixdiff=>10, tx=>0, ty=>0 },
356 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
362 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
364 ftype => { linear => 0,
370 repeat => { none => 0,
385 multiply => 2, mult => 2,
388 subtract => 5, 'sub' => 5,
398 defaults => { ftype => 0, repeat => 0, combine => 0,
399 super_sample => 0, ssample_param => 4,
412 # make sure the segments are specified with colors
414 for my $segment (@{$hsh{segments}}) {
415 my @new_segment = @$segment;
417 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
418 push @segments, \@new_segment;
421 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
422 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
423 $hsh{ssample_param}, \@segments)
424 or die Imager->_error_as_msg() . "\n";
427 $filters{unsharpmask} =
429 callseq => [ qw(image stddev scale) ],
430 defaults => { stddev=>2.0, scale=>1.0 },
434 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
438 $FORMATGUESS=\&def_guess_type;
448 # NOTE: this might be moved to an import override later on
453 if ($_[$i] eq '-log-stderr') {
461 goto &Exporter::import;
465 i_init_log($_[0],$_[1]);
466 i_log_entry("Imager $VERSION starting\n", 1);
471 my %parms=(loglevel=>1,@_);
473 init_log($parms{'log'},$parms{'loglevel'});
476 if (exists $parms{'warn_obsolete'}) {
477 $warn_obsolete = $parms{'warn_obsolete'};
480 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
481 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
485 if (exists $parms{'t1log'}) {
486 i_init_fonts($parms{'t1log'});
492 print "shutdown code\n";
493 # for(keys %instances) { $instances{$_}->DESTROY(); }
494 malloc_state(); # how do decide if this should be used? -- store something from the import
495 print "Imager exiting\n";
499 # Load a filter plugin
504 my ($DSO_handle,$str)=DSO_open($filename);
505 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
506 my %funcs=DSO_funclist($DSO_handle);
507 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
509 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
511 $DSOs{$filename}=[$DSO_handle,\%funcs];
514 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
515 $DEBUG && print "eval string:\n",$evstr,"\n";
527 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
528 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
529 for(keys %{$funcref}) {
531 $DEBUG && print "unloading: $_\n";
533 my $rc=DSO_close($DSO_handle);
534 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
538 # take the results of i_error() and make a message out of it
540 return join(": ", map $_->[0], i_errors());
543 # this function tries to DWIM for color parameters
544 # color objects are used as is
545 # simple scalars are simply treated as single parameters to Imager::Color->new
546 # hashrefs are treated as named argument lists to Imager::Color->new
547 # arrayrefs are treated as list arguments to Imager::Color->new iff any
549 # other arrayrefs are treated as list arguments to Imager::Color::Float
553 # perl 5.6.0 seems to do weird things to $arg if we don't make an
554 # explicitly stringified copy
555 # I vaguely remember a bug on this on p5p, but couldn't find it
556 # through bugs.perl.org (I had trouble getting it to find any bugs)
557 my $copy = $arg . "";
561 if (UNIVERSAL::isa($arg, "Imager::Color")
562 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
566 if ($copy =~ /^HASH\(/) {
567 $result = Imager::Color->new(%$arg);
569 elsif ($copy =~ /^ARRAY\(/) {
570 $result = Imager::Color->new(@$arg);
573 $Imager::ERRSTR = "Not a color";
578 # assume Imager::Color::new knows how to handle it
579 $result = Imager::Color->new($arg);
586 my ($self, $combine, $default) = @_;
588 if (!defined $combine && ref $self) {
589 $combine = $self->{combine};
591 defined $combine or $combine = $defaults{combine};
592 defined $combine or $combine = $default;
594 if (exists $combine_types{$combine}) {
595 $combine = $combine_types{$combine};
604 $self->{IMG} and return 1;
606 $self->_set_error('empty input image');
611 # returns first defined parameter
614 return $_ if defined $_;
620 # Methods to be called on objects.
623 # Create a new Imager object takes very few parameters.
624 # usually you call this method and then call open from
625 # the resulting object
632 $self->{IMG}=undef; # Just to indicate what exists
633 $self->{ERRSTR}=undef; #
634 $self->{DEBUG}=$DEBUG;
635 $self->{DEBUG} and print "Initialized Imager\n";
636 if (defined $hsh{xsize} || defined $hsh{ysize}) {
637 unless ($self->img_set(%hsh)) {
638 $Imager::ERRSTR = $self->{ERRSTR};
642 elsif (defined $hsh{file} ||
645 defined $hsh{callback} ||
646 defined $hsh{readcb} ||
647 defined $hsh{data}) {
648 # allow $img = Imager->new(file => $filename)
651 # type is already used as a parameter to new(), rename it for the
653 if ($hsh{filetype}) {
654 $extras{type} = $hsh{filetype};
656 unless ($self->read(%hsh, %extras)) {
657 $Imager::ERRSTR = $self->{ERRSTR};
665 # Copy an entire image with no changes
666 # - if an image has magic the copy of it will not be magical
670 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
672 unless (defined wantarray) {
674 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
678 my $newcopy=Imager->new();
679 $newcopy->{IMG} = i_copy($self->{IMG});
688 unless ($self->{IMG}) {
689 $self->_set_error('empty input image');
692 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
693 my $src = $input{img} || $input{src};
695 $self->_set_error("no source image");
698 $input{left}=0 if $input{left} <= 0;
699 $input{top}=0 if $input{top} <= 0;
701 my($r,$b)=i_img_info($src->{IMG});
702 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
703 my ($src_right, $src_bottom);
704 if ($input{src_coords}) {
705 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
708 if (defined $input{src_maxx}) {
709 $src_right = $input{src_maxx};
711 elsif (defined $input{width}) {
712 if ($input{width} <= 0) {
713 $self->_set_error("paste: width must me positive");
716 $src_right = $src_left + $input{width};
721 if (defined $input{src_maxy}) {
722 $src_bottom = $input{src_maxy};
724 elsif (defined $input{height}) {
725 if ($input{height} < 0) {
726 $self->_set_error("paste: height must be positive");
729 $src_bottom = $src_top + $input{height};
736 $src_right > $r and $src_right = $r;
737 $src_bottom > $b and $src_bottom = $b;
739 if ($src_right <= $src_left
740 || $src_bottom < $src_top) {
741 $self->_set_error("nothing to paste");
745 i_copyto($self->{IMG}, $src->{IMG},
746 $src_left, $src_top, $src_right, $src_bottom,
747 $input{left}, $input{top});
749 return $self; # What should go here??
752 # Crop an image - i.e. return a new image that is smaller
756 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
758 unless (defined wantarray) {
760 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
766 my ($w, $h, $l, $r, $b, $t) =
767 @hsh{qw(width height left right bottom top)};
769 # work through the various possibilities
774 elsif (!defined $r) {
775 $r = $self->getwidth;
787 $l = int(0.5+($self->getwidth()-$w)/2);
792 $r = $self->getwidth;
798 elsif (!defined $b) {
799 $b = $self->getheight;
811 $t=int(0.5+($self->getheight()-$h)/2);
816 $b = $self->getheight;
819 ($l,$r)=($r,$l) if $l>$r;
820 ($t,$b)=($b,$t) if $t>$b;
823 $r > $self->getwidth and $r = $self->getwidth;
825 $b > $self->getheight and $b = $self->getheight;
827 if ($l == $r || $t == $b) {
828 $self->_set_error("resulting image would have no content");
831 if( $r < $l or $b < $t ) {
832 $self->_set_error("attempting to crop outside of the image");
835 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
837 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
842 my ($self, %opts) = @_;
844 $self->{IMG} or return $self->_set_error("Not a valid image");
846 my $x = $opts{xsize} || $self->getwidth;
847 my $y = $opts{ysize} || $self->getheight;
848 my $channels = $opts{channels} || $self->getchannels;
850 my $out = Imager->new;
851 if ($channels == $self->getchannels) {
852 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
855 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
857 unless ($out->{IMG}) {
858 $self->{ERRSTR} = $self->_error_as_msg;
865 # Sets an image to a certain size and channel number
866 # if there was previously data in the image it is discarded
871 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
873 if (defined($self->{IMG})) {
874 # let IIM_DESTROY destroy it, it's possible this image is
875 # referenced from a virtual image (like masked)
876 #i_img_destroy($self->{IMG});
880 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
881 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
882 $hsh{maxcolors} || 256);
884 elsif ($hsh{bits} eq 'double') {
885 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
887 elsif ($hsh{bits} == 16) {
888 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
891 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
895 unless ($self->{IMG}) {
896 $self->{ERRSTR} = Imager->_error_as_msg();
903 # created a masked version of the current image
907 $self or return undef;
908 my %opts = (left => 0,
910 right => $self->getwidth,
911 bottom => $self->getheight,
913 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
915 my $result = Imager->new;
916 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
917 $opts{top}, $opts{right} - $opts{left},
918 $opts{bottom} - $opts{top});
919 # keep references to the mask and base images so they don't
921 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
926 # convert an RGB image into a paletted image
930 if (@_ != 1 && !ref $_[0]) {
937 unless (defined wantarray) {
939 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
943 my $result = Imager->new;
944 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
946 #print "Type ", i_img_type($result->{IMG}), "\n";
948 if ($result->{IMG}) {
952 $self->{ERRSTR} = $self->_error_as_msg;
957 # convert a paletted (or any image) to an 8-bit/channel RGB images
962 unless (defined wantarray) {
964 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
969 $result = Imager->new;
970 $result->{IMG} = i_img_to_rgb($self->{IMG})
977 # convert a paletted (or any image) to an 8-bit/channel RGB images
982 unless (defined wantarray) {
984 warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
989 $result = Imager->new;
990 $result->{IMG} = i_img_to_rgb16($self->{IMG})
999 my %opts = (colors=>[], @_);
1001 unless ($self->{IMG}) {
1002 $self->_set_error("empty input image");
1006 my @colors = @{$opts{colors}}
1009 for my $color (@colors) {
1010 $color = _color($color);
1012 $self->_set_error($Imager::ERRSTR);
1017 return i_addcolors($self->{IMG}, @colors);
1022 my %opts = (start=>0, colors=>[], @_);
1024 unless ($self->{IMG}) {
1025 $self->_set_error("empty input image");
1029 my @colors = @{$opts{colors}}
1032 for my $color (@colors) {
1033 $color = _color($color);
1035 $self->_set_error($Imager::ERRSTR);
1040 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1046 if (!exists $opts{start} && !exists $opts{count}) {
1049 $opts{count} = $self->colorcount;
1051 elsif (!exists $opts{count}) {
1054 elsif (!exists $opts{start}) {
1059 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1063 i_colorcount($_[0]{IMG});
1067 i_maxcolors($_[0]{IMG});
1073 $opts{color} or return undef;
1075 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1080 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1081 if ($bits && $bits == length(pack("d", 1)) * 8) {
1090 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1096 $self->{IMG} and i_img_virtual($self->{IMG});
1102 $self->{IMG} or return;
1104 return i_img_is_monochrome($self->{IMG});
1108 my ($self, %opts) = @_;
1110 $self->{IMG} or return;
1112 if (defined $opts{name}) {
1116 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1117 push @result, (i_tags_get($self->{IMG}, $found))[1];
1120 return wantarray ? @result : $result[0];
1122 elsif (defined $opts{code}) {
1126 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1127 push @result, (i_tags_get($self->{IMG}, $found))[1];
1134 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1137 return i_tags_count($self->{IMG});
1146 return -1 unless $self->{IMG};
1148 if (defined $opts{value}) {
1149 if ($opts{value} =~ /^\d+$/) {
1151 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1154 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1157 elsif (defined $opts{data}) {
1158 # force addition as a string
1159 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1162 $self->{ERRSTR} = "No value supplied";
1166 elsif ($opts{code}) {
1167 if (defined $opts{value}) {
1168 if ($opts{value} =~ /^\d+$/) {
1170 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1173 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1176 elsif (defined $opts{data}) {
1177 # force addition as a string
1178 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1181 $self->{ERRSTR} = "No value supplied";
1194 return 0 unless $self->{IMG};
1196 if (defined $opts{'index'}) {
1197 return i_tags_delete($self->{IMG}, $opts{'index'});
1199 elsif (defined $opts{name}) {
1200 return i_tags_delbyname($self->{IMG}, $opts{name});
1202 elsif (defined $opts{code}) {
1203 return i_tags_delbycode($self->{IMG}, $opts{code});
1206 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1212 my ($self, %opts) = @_;
1215 $self->deltag(name=>$opts{name});
1216 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1218 elsif (defined $opts{code}) {
1219 $self->deltag(code=>$opts{code});
1220 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1228 sub _get_reader_io {
1229 my ($self, $input) = @_;
1232 return $input->{io}, undef;
1234 elsif ($input->{fd}) {
1235 return io_new_fd($input->{fd});
1237 elsif ($input->{fh}) {
1238 my $fd = fileno($input->{fh});
1239 unless (defined $fd) {
1240 $self->_set_error("Handle in fh option not opened");
1243 return io_new_fd($fd);
1245 elsif ($input->{file}) {
1246 my $file = IO::File->new($input->{file}, "r");
1248 $self->_set_error("Could not open $input->{file}: $!");
1252 return (io_new_fd(fileno($file)), $file);
1254 elsif ($input->{data}) {
1255 return io_new_buffer($input->{data});
1257 elsif ($input->{callback} || $input->{readcb}) {
1258 if (!$input->{seekcb}) {
1259 $self->_set_error("Need a seekcb parameter");
1261 if ($input->{maxbuffer}) {
1262 return io_new_cb($input->{writecb},
1263 $input->{callback} || $input->{readcb},
1264 $input->{seekcb}, $input->{closecb},
1265 $input->{maxbuffer});
1268 return io_new_cb($input->{writecb},
1269 $input->{callback} || $input->{readcb},
1270 $input->{seekcb}, $input->{closecb});
1274 $self->_set_error("file/fd/fh/data/callback parameter missing");
1279 sub _get_writer_io {
1280 my ($self, $input, $type) = @_;
1283 return $input->{io};
1285 elsif ($input->{fd}) {
1286 return io_new_fd($input->{fd});
1288 elsif ($input->{fh}) {
1289 my $fd = fileno($input->{fh});
1290 unless (defined $fd) {
1291 $self->_set_error("Handle in fh option not opened");
1295 my $oldfh = select($input->{fh});
1296 # flush anything that's buffered, and make sure anything else is flushed
1299 return io_new_fd($fd);
1301 elsif ($input->{file}) {
1302 my $fh = new IO::File($input->{file},"w+");
1304 $self->_set_error("Could not open file $input->{file}: $!");
1307 binmode($fh) or die;
1308 return (io_new_fd(fileno($fh)), $fh);
1310 elsif ($input->{data}) {
1311 return io_new_bufchain();
1313 elsif ($input->{callback} || $input->{writecb}) {
1314 if ($input->{maxbuffer}) {
1315 return io_new_cb($input->{callback} || $input->{writecb},
1317 $input->{seekcb}, $input->{closecb},
1318 $input->{maxbuffer});
1321 return io_new_cb($input->{callback} || $input->{writecb},
1323 $input->{seekcb}, $input->{closecb});
1327 $self->_set_error("file/fd/fh/data/callback parameter missing");
1332 # Read an image from file
1338 if (defined($self->{IMG})) {
1339 # let IIM_DESTROY do the destruction, since the image may be
1340 # referenced from elsewhere
1341 #i_img_destroy($self->{IMG});
1342 undef($self->{IMG});
1345 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1347 unless ($input{'type'}) {
1348 $input{'type'} = i_test_format_probe($IO, -1);
1351 unless ($input{'type'}) {
1352 $self->_set_error('type parameter missing and not possible to guess from extension');
1356 _reader_autoload($input{type});
1358 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1359 return $readers{$input{type}}{single}->($self, $IO, %input);
1362 unless ($formats_low{$input{'type'}}) {
1363 my $read_types = join ', ', sort Imager->read_types();
1364 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1368 my $allow_incomplete = $input{allow_incomplete};
1369 defined $allow_incomplete or $allow_incomplete = 0;
1371 if ( $input{'type'} eq 'pnm' ) {
1372 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1373 if ( !defined($self->{IMG}) ) {
1374 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1377 $self->{DEBUG} && print "loading a pnm file\n";
1381 if ( $input{'type'} eq 'bmp' ) {
1382 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1383 if ( !defined($self->{IMG}) ) {
1384 $self->{ERRSTR}=$self->_error_as_msg();
1387 $self->{DEBUG} && print "loading a bmp file\n";
1390 if ( $input{'type'} eq 'gif' ) {
1391 if ($input{colors} && !ref($input{colors})) {
1392 # must be a reference to a scalar that accepts the colour map
1393 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1396 if ($input{'gif_consolidate'}) {
1397 if ($input{colors}) {
1399 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1401 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1405 $self->{IMG} =i_readgif_wiol( $IO );
1409 my $page = $input{'page'};
1410 defined $page or $page = 0;
1411 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1412 if ($self->{IMG} && $input{colors}) {
1413 ${ $input{colors} } =
1414 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1418 if ( !defined($self->{IMG}) ) {
1419 $self->{ERRSTR}=$self->_error_as_msg();
1422 $self->{DEBUG} && print "loading a gif file\n";
1425 if ( $input{'type'} eq 'tga' ) {
1426 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1427 if ( !defined($self->{IMG}) ) {
1428 $self->{ERRSTR}=$self->_error_as_msg();
1431 $self->{DEBUG} && print "loading a tga file\n";
1434 if ( $input{'type'} eq 'raw' ) {
1435 unless ( $input{xsize} && $input{ysize} ) {
1436 $self->_set_error('missing xsize or ysize parameter for raw');
1440 my $interleave = _first($input{raw_interleave}, $input{interleave});
1441 unless (defined $interleave) {
1442 my @caller = caller;
1443 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1446 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1447 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1449 $self->{IMG} = i_readraw_wiol( $IO,
1455 if ( !defined($self->{IMG}) ) {
1456 $self->{ERRSTR}=$self->_error_as_msg();
1459 $self->{DEBUG} && print "loading a raw file\n";
1465 sub register_reader {
1466 my ($class, %opts) = @_;
1469 or die "register_reader called with no type parameter\n";
1471 my $type = $opts{type};
1473 defined $opts{single} || defined $opts{multiple}
1474 or die "register_reader called with no single or multiple parameter\n";
1476 $readers{$type} = { };
1477 if ($opts{single}) {
1478 $readers{$type}{single} = $opts{single};
1480 if ($opts{multiple}) {
1481 $readers{$type}{multiple} = $opts{multiple};
1487 sub register_writer {
1488 my ($class, %opts) = @_;
1491 or die "register_writer called with no type parameter\n";
1493 my $type = $opts{type};
1495 defined $opts{single} || defined $opts{multiple}
1496 or die "register_writer called with no single or multiple parameter\n";
1498 $writers{$type} = { };
1499 if ($opts{single}) {
1500 $writers{$type}{single} = $opts{single};
1502 if ($opts{multiple}) {
1503 $writers{$type}{multiple} = $opts{multiple};
1514 grep($file_formats{$_}, keys %formats),
1515 qw(ico sgi), # formats not handled directly, but supplied with Imager
1526 grep($file_formats{$_}, keys %formats),
1527 qw(ico sgi), # formats not handled directly, but supplied with Imager
1533 # probes for an Imager::File::whatever module
1534 sub _reader_autoload {
1537 return if $formats_low{$type} || $readers{$type};
1539 return unless $type =~ /^\w+$/;
1541 my $file = "Imager/File/\U$type\E.pm";
1543 unless ($attempted_to_load{$file}) {
1545 ++$attempted_to_load{$file};
1549 # try to get a reader specific module
1550 my $file = "Imager/File/\U$type\EReader.pm";
1551 unless ($attempted_to_load{$file}) {
1553 ++$attempted_to_load{$file};
1561 # probes for an Imager::File::whatever module
1562 sub _writer_autoload {
1565 return if $formats_low{$type} || $readers{$type};
1567 return unless $type =~ /^\w+$/;
1569 my $file = "Imager/File/\U$type\E.pm";
1571 unless ($attempted_to_load{$file}) {
1573 ++$attempted_to_load{$file};
1577 # try to get a writer specific module
1578 my $file = "Imager/File/\U$type\EWriter.pm";
1579 unless ($attempted_to_load{$file}) {
1581 ++$attempted_to_load{$file};
1589 sub _fix_gif_positions {
1590 my ($opts, $opt, $msg, @imgs) = @_;
1592 my $positions = $opts->{'gif_positions'};
1594 for my $pos (@$positions) {
1595 my ($x, $y) = @$pos;
1596 my $img = $imgs[$index++];
1597 $img->settag(name=>'gif_left', value=>$x);
1598 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1600 $$msg .= "replaced with the gif_left and gif_top tags";
1605 gif_each_palette=>'gif_local_map',
1606 interlace => 'gif_interlace',
1607 gif_delays => 'gif_delay',
1608 gif_positions => \&_fix_gif_positions,
1609 gif_loop_count => 'gif_loop',
1612 # options that should be converted to colors
1613 my %color_opts = map { $_ => 1 } qw/i_background/;
1616 my ($self, $opts, $prefix, @imgs) = @_;
1618 for my $opt (keys %$opts) {
1620 if ($obsolete_opts{$opt}) {
1621 my $new = $obsolete_opts{$opt};
1622 my $msg = "Obsolete option $opt ";
1624 $new->($opts, $opt, \$msg, @imgs);
1627 $msg .= "replaced with the $new tag ";
1630 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1631 warn $msg if $warn_obsolete && $^W;
1633 next unless $tagname =~ /^\Q$prefix/;
1634 my $value = $opts->{$opt};
1635 if ($color_opts{$opt}) {
1636 $value = _color($value);
1638 $self->_set_error($Imager::ERRSTR);
1643 if (UNIVERSAL::isa($value, "Imager::Color")) {
1644 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1645 for my $img (@imgs) {
1646 $img->settag(name=>$tagname, value=>$tag);
1649 elsif (ref($value) eq 'ARRAY') {
1650 for my $i (0..$#$value) {
1651 my $val = $value->[$i];
1653 if (UNIVERSAL::isa($val, "Imager::Color")) {
1654 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1656 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1659 $self->_set_error("Unknown reference type " . ref($value) .
1660 " supplied in array for $opt");
1666 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1671 $self->_set_error("Unknown reference type " . ref($value) .
1672 " supplied for $opt");
1677 # set it as a tag for every image
1678 for my $img (@imgs) {
1679 $img->settag(name=>$tagname, value=>$value);
1687 # Write an image to file
1690 my %input=(jpegquality=>75,
1700 $self->_set_opts(\%input, "i_", $self)
1703 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1705 if (!$input{'type'} and $input{file}) {
1706 $input{'type'}=$FORMATGUESS->($input{file});
1708 if (!$input{'type'}) {
1709 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1713 _writer_autoload($input{type});
1716 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1717 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1720 $writers{$input{type}}{single}->($self, $IO, %input)
1724 if (!$formats_low{$input{'type'}}) {
1725 my $write_types = join ', ', sort Imager->write_types();
1726 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1730 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1733 if ( $input{'type'} eq 'pnm' ) {
1734 $self->_set_opts(\%input, "pnm_", $self)
1736 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1737 $self->{ERRSTR} = $self->_error_as_msg();
1740 $self->{DEBUG} && print "writing a pnm file\n";
1741 } elsif ( $input{'type'} eq 'raw' ) {
1742 $self->_set_opts(\%input, "raw_", $self)
1744 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1745 $self->{ERRSTR} = $self->_error_as_msg();
1748 $self->{DEBUG} && print "writing a raw file\n";
1749 } elsif ( $input{'type'} eq 'jpeg' ) {
1750 $self->_set_opts(\%input, "jpeg_", $self)
1752 $self->_set_opts(\%input, "exif_", $self)
1754 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1755 $self->{ERRSTR} = $self->_error_as_msg();
1758 $self->{DEBUG} && print "writing a jpeg file\n";
1759 } elsif ( $input{'type'} eq 'bmp' ) {
1760 $self->_set_opts(\%input, "bmp_", $self)
1762 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1763 $self->{ERRSTR} = $self->_error_as_msg;
1766 $self->{DEBUG} && print "writing a bmp file\n";
1767 } elsif ( $input{'type'} eq 'tga' ) {
1768 $self->_set_opts(\%input, "tga_", $self)
1771 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1772 $self->{ERRSTR}=$self->_error_as_msg();
1775 $self->{DEBUG} && print "writing a tga file\n";
1776 } elsif ( $input{'type'} eq 'gif' ) {
1777 $self->_set_opts(\%input, "gif_", $self)
1779 # compatibility with the old interfaces
1780 if ($input{gifquant} eq 'lm') {
1781 $input{make_colors} = 'addi';
1782 $input{translate} = 'perturb';
1783 $input{perturb} = $input{lmdither};
1784 } elsif ($input{gifquant} eq 'gen') {
1785 # just pass options through
1787 $input{make_colors} = 'webmap'; # ignored
1788 $input{translate} = 'giflib';
1790 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1791 $self->{ERRSTR} = $self->_error_as_msg;
1797 if (exists $input{'data'}) {
1798 my $data = io_slurp($IO);
1800 $self->{ERRSTR}='Could not slurp from buffer';
1803 ${$input{data}} = $data;
1809 my ($class, $opts, @images) = @_;
1811 my $type = $opts->{type};
1813 if (!$type && $opts->{'file'}) {
1814 $type = $FORMATGUESS->($opts->{'file'});
1817 $class->_set_error('type parameter missing and not possible to guess from extension');
1820 # translate to ImgRaw
1821 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1822 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1825 $class->_set_opts($opts, "i_", @images)
1827 my @work = map $_->{IMG}, @images;
1829 _writer_autoload($type);
1832 if ($writers{$type} && $writers{$type}{multiple}) {
1833 ($IO, $file) = $class->_get_writer_io($opts, $type)
1836 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1840 if (!$formats{$type}) {
1841 my $write_types = join ', ', sort Imager->write_types();
1842 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1846 ($IO, $file) = $class->_get_writer_io($opts, $type)
1849 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1853 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1858 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1864 if (exists $opts->{'data'}) {
1865 my $data = io_slurp($IO);
1867 Imager->_set_error('Could not slurp from buffer');
1870 ${$opts->{data}} = $data;
1875 # read multiple images from a file
1877 my ($class, %opts) = @_;
1879 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1882 my $type = $opts{'type'};
1884 $type = i_test_format_probe($IO, -1);
1887 if ($opts{file} && !$type) {
1889 $type = $FORMATGUESS->($opts{file});
1893 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1897 _reader_autoload($type);
1899 if ($readers{$type} && $readers{$type}{multiple}) {
1900 return $readers{$type}{multiple}->($IO, %opts);
1903 unless ($formats{$type}) {
1904 my $read_types = join ', ', sort Imager->read_types();
1905 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1910 if ($type eq 'pnm') {
1911 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1914 my $img = Imager->new;
1915 if ($img->read(%opts, io => $IO, type => $type)) {
1918 Imager->_set_error($img->errstr);
1923 $ERRSTR = _error_as_msg();
1927 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1931 # Destroy an Imager object
1935 # delete $instances{$self};
1936 if (defined($self->{IMG})) {
1937 # the following is now handled by the XS DESTROY method for
1938 # Imager::ImgRaw object
1939 # Re-enabling this will break virtual images
1940 # tested for in t/t020masked.t
1941 # i_img_destroy($self->{IMG});
1942 undef($self->{IMG});
1944 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1948 # Perform an inplace filter of an image
1949 # that is the image will be overwritten with the data
1955 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1957 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1959 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1960 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1963 if ($filters{$input{'type'}}{names}) {
1964 my $names = $filters{$input{'type'}}{names};
1965 for my $name (keys %$names) {
1966 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1967 $input{$name} = $names->{$name}{$input{$name}};
1971 if (defined($filters{$input{'type'}}{defaults})) {
1972 %hsh=( image => $self->{IMG},
1974 %{$filters{$input{'type'}}{defaults}},
1977 %hsh=( image => $self->{IMG},
1982 my @cs=@{$filters{$input{'type'}}{callseq}};
1985 if (!defined($hsh{$_})) {
1986 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1991 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1992 &{$filters{$input{'type'}}{callsub}}(%hsh);
1995 chomp($self->{ERRSTR} = $@);
2001 $self->{DEBUG} && print "callseq is: @cs\n";
2002 $self->{DEBUG} && print "matching callseq is: @b\n";
2007 sub register_filter {
2009 my %hsh = ( defaults => {}, @_ );
2012 or die "register_filter() with no type\n";
2013 defined $hsh{callsub}
2014 or die "register_filter() with no callsub\n";
2015 defined $hsh{callseq}
2016 or die "register_filter() with no callseq\n";
2018 exists $filters{$hsh{type}}
2021 $filters{$hsh{type}} = \%hsh;
2026 sub scale_calculate {
2029 my %opts = ('type'=>'max', @_);
2031 # none of these should be references
2032 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2033 if (defined $opts{$name} && ref $opts{$name}) {
2034 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2039 my ($x_scale, $y_scale);
2040 my $width = $opts{width};
2041 my $height = $opts{height};
2043 defined $width or $width = $self->getwidth;
2044 defined $height or $height = $self->getheight;
2047 unless (defined $width && defined $height) {
2048 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2053 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2054 $x_scale = $opts{'xscalefactor'};
2055 $y_scale = $opts{'yscalefactor'};
2057 elsif ($opts{'xscalefactor'}) {
2058 $x_scale = $opts{'xscalefactor'};
2059 $y_scale = $opts{'scalefactor'} || $x_scale;
2061 elsif ($opts{'yscalefactor'}) {
2062 $y_scale = $opts{'yscalefactor'};
2063 $x_scale = $opts{'scalefactor'} || $y_scale;
2066 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2069 # work out the scaling
2070 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2071 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2072 $opts{ypixels} / $height );
2073 if ($opts{'type'} eq 'min') {
2074 $x_scale = $y_scale = _min($xpix,$ypix);
2076 elsif ($opts{'type'} eq 'max') {
2077 $x_scale = $y_scale = _max($xpix,$ypix);
2079 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2084 $self->_set_error('invalid value for type parameter');
2087 } elsif ($opts{xpixels}) {
2088 $x_scale = $y_scale = $opts{xpixels} / $width;
2090 elsif ($opts{ypixels}) {
2091 $x_scale = $y_scale = $opts{ypixels}/$height;
2093 elsif ($opts{constrain} && ref $opts{constrain}
2094 && $opts{constrain}->can('constrain')) {
2095 # we've been passed an Image::Math::Constrain object or something
2096 # that looks like one
2098 (undef, undef, $scalefactor)
2099 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2100 unless ($scalefactor) {
2101 $self->_set_error('constrain method failed on constrain parameter');
2104 $x_scale = $y_scale = $scalefactor;
2107 my $new_width = int($x_scale * $width + 0.5);
2108 $new_width > 0 or $new_width = 1;
2109 my $new_height = int($y_scale * $height + 0.5);
2110 $new_height > 0 or $new_height = 1;
2112 return ($x_scale, $y_scale, $new_width, $new_height);
2116 # Scale an image to requested size and return the scaled version
2120 my %opts = (qtype=>'normal' ,@_);
2121 my $img = Imager->new();
2122 my $tmp = Imager->new();
2124 unless (defined wantarray) {
2125 my @caller = caller;
2126 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2130 unless ($self->{IMG}) {
2131 $self->_set_error('empty input image');
2135 my ($x_scale, $y_scale, $new_width, $new_height) =
2136 $self->scale_calculate(%opts)
2139 if ($opts{qtype} eq 'normal') {
2140 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2141 if ( !defined($tmp->{IMG}) ) {
2142 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2145 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2146 if ( !defined($img->{IMG}) ) {
2147 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2153 elsif ($opts{'qtype'} eq 'preview') {
2154 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2155 if ( !defined($img->{IMG}) ) {
2156 $self->{ERRSTR}='unable to scale image';
2161 elsif ($opts{'qtype'} eq 'mixing') {
2162 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2163 unless ($img->{IMG}) {
2164 $self->_set_error(Imager->_error_as_msg);
2170 $self->_set_error('invalid value for qtype parameter');
2175 # Scales only along the X axis
2179 my %opts = ( scalefactor=>0.5, @_ );
2181 unless (defined wantarray) {
2182 my @caller = caller;
2183 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2187 unless ($self->{IMG}) {
2188 $self->{ERRSTR} = 'empty input image';
2192 my $img = Imager->new();
2194 my $scalefactor = $opts{scalefactor};
2196 if ($opts{pixels}) {
2197 $scalefactor = $opts{pixels} / $self->getwidth();
2200 unless ($self->{IMG}) {
2201 $self->{ERRSTR}='empty input image';
2205 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2207 if ( !defined($img->{IMG}) ) {
2208 $self->{ERRSTR} = 'unable to scale image';
2215 # Scales only along the Y axis
2219 my %opts = ( scalefactor => 0.5, @_ );
2221 unless (defined wantarray) {
2222 my @caller = caller;
2223 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2227 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2229 my $img = Imager->new();
2231 my $scalefactor = $opts{scalefactor};
2233 if ($opts{pixels}) {
2234 $scalefactor = $opts{pixels} / $self->getheight();
2237 unless ($self->{IMG}) {
2238 $self->{ERRSTR} = 'empty input image';
2241 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2243 if ( !defined($img->{IMG}) ) {
2244 $self->{ERRSTR} = 'unable to scale image';
2251 # Transform returns a spatial transformation of the input image
2252 # this moves pixels to a new location in the returned image.
2253 # NOTE - should make a utility function to check transforms for
2258 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2260 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2262 # print Dumper(\%opts);
2265 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2267 eval ("use Affix::Infix2Postfix;");
2270 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2273 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2274 {op=>'-',trans=>'Sub'},
2275 {op=>'*',trans=>'Mult'},
2276 {op=>'/',trans=>'Div'},
2277 {op=>'-','type'=>'unary',trans=>'u-'},
2279 {op=>'func','type'=>'unary'}],
2280 'grouping'=>[qw( \( \) )],
2281 'func'=>[qw( sin cos )],
2286 @xt=$I2P->translate($opts{'xexpr'});
2287 @yt=$I2P->translate($opts{'yexpr'});
2289 $numre=$I2P->{'numre'};
2292 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2293 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2294 @{$opts{'parm'}}=@pt;
2297 # print Dumper(\%opts);
2299 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2300 $self->{ERRSTR}='transform: no xopcodes given.';
2304 @op=@{$opts{'xopcodes'}};
2306 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2307 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2310 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2316 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2317 $self->{ERRSTR}='transform: no yopcodes given.';
2321 @op=@{$opts{'yopcodes'}};
2323 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2324 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2327 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2332 if ( !exists $opts{'parm'}) {
2333 $self->{ERRSTR}='transform: no parameter arg given.';
2337 # print Dumper(\@ropx);
2338 # print Dumper(\@ropy);
2339 # print Dumper(\@ropy);
2341 my $img = Imager->new();
2342 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2343 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2349 my ($opts, @imgs) = @_;
2351 require "Imager/Expr.pm";
2353 $opts->{variables} = [ qw(x y) ];
2354 my ($width, $height) = @{$opts}{qw(width height)};
2356 $width ||= $imgs[0]->getwidth();
2357 $height ||= $imgs[0]->getheight();
2359 for my $img (@imgs) {
2360 $opts->{constants}{"w$img_num"} = $img->getwidth();
2361 $opts->{constants}{"h$img_num"} = $img->getheight();
2362 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2363 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2368 $opts->{constants}{w} = $width;
2369 $opts->{constants}{cx} = $width/2;
2372 $Imager::ERRSTR = "No width supplied";
2376 $opts->{constants}{h} = $height;
2377 $opts->{constants}{cy} = $height/2;
2380 $Imager::ERRSTR = "No height supplied";
2383 my $code = Imager::Expr->new($opts);
2385 $Imager::ERRSTR = Imager::Expr::error();
2388 my $channels = $opts->{channels} || 3;
2389 unless ($channels >= 1 && $channels <= 4) {
2390 return Imager->_set_error("channels must be an integer between 1 and 4");
2393 my $img = Imager->new();
2394 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2395 $channels, $code->code(),
2396 $code->nregs(), $code->cregs(),
2397 [ map { $_->{IMG} } @imgs ]);
2398 if (!defined $img->{IMG}) {
2399 $Imager::ERRSTR = Imager->_error_as_msg();
2410 unless ($self->{IMG}) {
2411 $self->{ERRSTR}='empty input image';
2414 unless ($opts{src} && $opts{src}->{IMG}) {
2415 $self->{ERRSTR}='empty input image for src';
2419 %opts = (src_minx => 0,
2421 src_maxx => $opts{src}->getwidth(),
2422 src_maxy => $opts{src}->getheight(),
2426 defined $tx or $tx = $opts{left};
2427 defined $tx or $tx = 0;
2430 defined $ty or $ty = $opts{top};
2431 defined $ty or $ty = 0;
2433 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2434 $opts{src_minx}, $opts{src_miny},
2435 $opts{src_maxx}, $opts{src_maxy})) {
2436 $self->_set_error($self->_error_as_msg());
2453 unless ($self->{IMG}) {
2454 $self->_set_error("compose: empty input image");
2458 unless ($opts{src}) {
2459 $self->_set_error("compose: src parameter missing");
2463 unless ($opts{src}{IMG}) {
2464 $self->_set_error("compose: src parameter empty image");
2467 my $src = $opts{src};
2469 my $left = $opts{left};
2470 defined $left or $left = $opts{tx};
2471 defined $left or $left = 0;
2473 my $top = $opts{top};
2474 defined $top or $top = $opts{ty};
2475 defined $top or $top = 0;
2477 my $src_left = $opts{src_left};
2478 defined $src_left or $src_left = $opts{src_minx};
2479 defined $src_left or $src_left = 0;
2481 my $src_top = $opts{src_top};
2482 defined $src_top or $src_top = $opts{src_miny};
2483 defined $src_top or $src_top = 0;
2485 my $width = $opts{width};
2486 if (!defined $width && defined $opts{src_maxx}) {
2487 $width = $opts{src_maxx} - $src_left;
2489 defined $width or $width = $src->getwidth() - $src_left;
2491 my $height = $opts{height};
2492 if (!defined $height && defined $opts{src_maxy}) {
2493 $height = $opts{src_maxy} - $src_top;
2495 defined $height or $height = $src->getheight() - $src_top;
2497 my $combine = $self->_combine($opts{combine}, 'normal');
2500 unless ($opts{mask}{IMG}) {
2501 $self->_set_error("compose: mask parameter empty image");
2505 my $mask_left = $opts{mask_left};
2506 defined $mask_left or $mask_left = $opts{mask_minx};
2507 defined $mask_left or $mask_left = 0;
2509 my $mask_top = $opts{mask_top};
2510 defined $mask_top or $mask_top = $opts{mask_miny};
2511 defined $mask_top or $mask_top = 0;
2513 i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2514 $left, $top, $src_left, $src_top,
2515 $mask_left, $mask_top, $width, $height,
2516 $combine, $opts{opacity})
2520 i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2521 $width, $height, $combine, $opts{opacity})
2531 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2533 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2534 $dir = $xlate{$opts{'dir'}};
2535 return $self if i_flipxy($self->{IMG}, $dir);
2543 unless (defined wantarray) {
2544 my @caller = caller;
2545 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2549 if (defined $opts{right}) {
2550 my $degrees = $opts{right};
2552 $degrees += 360 * int(((-$degrees)+360)/360);
2554 $degrees = $degrees % 360;
2555 if ($degrees == 0) {
2556 return $self->copy();
2558 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2559 my $result = Imager->new();
2560 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2564 $self->{ERRSTR} = $self->_error_as_msg();
2569 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2573 elsif (defined $opts{radians} || defined $opts{degrees}) {
2574 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2576 my $back = $opts{back};
2577 my $result = Imager->new;
2579 $back = _color($back);
2581 $self->_set_error(Imager->errstr);
2585 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2588 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2590 if ($result->{IMG}) {
2594 $self->{ERRSTR} = $self->_error_as_msg();
2599 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2604 sub matrix_transform {
2608 unless (defined wantarray) {
2609 my @caller = caller;
2610 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2614 if ($opts{matrix}) {
2615 my $xsize = $opts{xsize} || $self->getwidth;
2616 my $ysize = $opts{ysize} || $self->getheight;
2618 my $result = Imager->new;
2620 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2621 $opts{matrix}, $opts{back})
2625 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2633 $self->{ERRSTR} = "matrix parameter required";
2639 *yatf = \&matrix_transform;
2641 # These two are supported for legacy code only
2644 return Imager::Color->new(@_);
2648 return Imager::Color::set(@_);
2651 # Draws a box between the specified corner points.
2654 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2655 my %opts=(xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2657 if (exists $opts{'box'}) {
2658 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2659 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2660 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2661 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2664 if ($opts{filled}) {
2665 my $color = $opts{'color'};
2667 if (defined $color) {
2668 unless (ref $color &&
2669 (UNIVERSAL::isa($color, "Imager::Color")
2670 || UNIVERSAL::isa($color, "Imager::Color::Float"))) {
2671 $color = _color($color);
2673 $self->{ERRSTR} = $Imager::ERRSTR;
2679 $color = i_color_new(255,255,255,255);
2682 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2683 $opts{ymax}, $color);
2685 elsif ($opts{fill}) {
2686 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2687 # assume it's a hash ref
2688 require 'Imager/Fill.pm';
2689 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2690 $self->{ERRSTR} = $Imager::ERRSTR;
2694 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2695 $opts{ymax},$opts{fill}{fill});
2698 my $color = $opts{'color'};
2699 if (defined $color) {
2700 unless (ref $color &&
2701 (UNIVERSAL::isa($color, "Imager::Color")
2702 || UNIVERSAL::isa($color, "Imager::Color::Float"))) {
2703 $color = _color($color);
2705 $self->{ERRSTR} = $Imager::ERRSTR;
2711 $color = i_color_new(255, 255, 255, 255);
2714 $self->{ERRSTR} = $Imager::ERRSTR;
2717 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2725 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2726 my $dflcl= [ 255, 255, 255, 255];
2731 'r'=>_min($self->getwidth(),$self->getheight())/3,
2732 'x'=>$self->getwidth()/2,
2733 'y'=>$self->getheight()/2,
2740 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2741 # assume it's a hash ref
2742 require 'Imager/Fill.pm';
2743 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2744 $self->{ERRSTR} = $Imager::ERRSTR;
2748 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2749 $opts{'d2'}, $opts{fill}{fill});
2751 elsif ($opts{filled}) {
2752 my $color = _color($opts{'color'});
2754 $self->{ERRSTR} = $Imager::ERRSTR;
2757 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2758 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2762 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2763 $opts{'d1'}, $opts{'d2'}, $color);
2767 my $color = _color($opts{'color'});
2768 if ($opts{d2} - $opts{d1} >= 360) {
2769 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2772 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2778 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2779 # assume it's a hash ref
2780 require 'Imager/Fill.pm';
2781 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2782 $self->{ERRSTR} = $Imager::ERRSTR;
2786 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2787 $opts{'d2'}, $opts{fill}{fill});
2790 my $color = _color($opts{'color'});
2792 $self->{ERRSTR} = $Imager::ERRSTR;
2795 if ($opts{filled}) {
2796 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2797 $opts{'d1'}, $opts{'d2'}, $color);
2800 if ($opts{d1} == 0 && $opts{d2} == 361) {
2801 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2804 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2810 $self->_set_error($self->_error_as_msg);
2817 # Draws a line from one point to the other
2818 # the endpoint is set if the endp parameter is set which it is by default.
2819 # to turn of the endpoint being set use endp=>0 when calling line.
2823 my $dflcl=i_color_new(0,0,0,0);
2824 my %opts=(color=>$dflcl,
2827 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2829 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2830 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2832 my $color = _color($opts{'color'});
2834 $self->{ERRSTR} = $Imager::ERRSTR;
2838 $opts{antialias} = $opts{aa} if defined $opts{aa};
2839 if ($opts{antialias}) {
2840 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2841 $color, $opts{endp});
2843 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2844 $color, $opts{endp});
2849 # Draws a line between an ordered set of points - It more or less just transforms this
2850 # into a list of lines.
2854 my ($pt,$ls,@points);
2855 my $dflcl=i_color_new(0,0,0,0);
2856 my %opts=(color=>$dflcl,@_);
2858 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2860 if (exists($opts{points})) { @points=@{$opts{points}}; }
2861 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2862 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2865 # print Dumper(\@points);
2867 my $color = _color($opts{'color'});
2869 $self->{ERRSTR} = $Imager::ERRSTR;
2872 $opts{antialias} = $opts{aa} if defined $opts{aa};
2873 if ($opts{antialias}) {
2876 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2883 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2893 my ($pt,$ls,@points);
2894 my $dflcl = i_color_new(0,0,0,0);
2895 my %opts = (color=>$dflcl, @_);
2897 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2899 if (exists($opts{points})) {
2900 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2901 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2904 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2905 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2908 if ($opts{'fill'}) {
2909 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2910 # assume it's a hash ref
2911 require 'Imager/Fill.pm';
2912 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2913 $self->{ERRSTR} = $Imager::ERRSTR;
2917 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2918 $opts{'fill'}{'fill'});
2921 my $color = _color($opts{'color'});
2923 $self->{ERRSTR} = $Imager::ERRSTR;
2926 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2933 # this the multipoint bezier curve
2934 # this is here more for testing that actual usage since
2935 # this is not a good algorithm. Usually the curve would be
2936 # broken into smaller segments and each done individually.
2940 my ($pt,$ls,@points);
2941 my $dflcl=i_color_new(0,0,0,0);
2942 my %opts=(color=>$dflcl,@_);
2944 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2946 if (exists $opts{points}) {
2947 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2948 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2951 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2952 $self->{ERRSTR}='Missing or invalid points.';
2956 my $color = _color($opts{'color'});
2958 $self->{ERRSTR} = $Imager::ERRSTR;
2961 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2967 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2970 unless (exists $opts{'x'} && exists $opts{'y'}) {
2971 $self->{ERRSTR} = "missing seed x and y parameters";
2975 if ($opts{border}) {
2976 my $border = _color($opts{border});
2978 $self->_set_error($Imager::ERRSTR);
2982 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2983 # assume it's a hash ref
2984 require Imager::Fill;
2985 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2986 $self->{ERRSTR} = $Imager::ERRSTR;
2990 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2991 $opts{fill}{fill}, $border);
2994 my $color = _color($opts{'color'});
2996 $self->{ERRSTR} = $Imager::ERRSTR;
2999 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3006 $self->{ERRSTR} = $self->_error_as_msg();
3012 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3013 # assume it's a hash ref
3014 require 'Imager/Fill.pm';
3015 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3016 $self->{ERRSTR} = $Imager::ERRSTR;
3020 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3023 my $color = _color($opts{'color'});
3025 $self->{ERRSTR} = $Imager::ERRSTR;
3028 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3034 $self->{ERRSTR} = $self->_error_as_msg();
3041 my ($self, %opts) = @_;
3043 my $color = $opts{color};
3044 unless (defined $color) {
3045 $color = $self->{fg};
3046 defined $color or $color = NC(255, 255, 255);
3049 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3050 $color = _color($color)
3054 unless (exists $opts{'x'} && exists $opts{'y'}) {
3055 $self->{ERRSTR} = 'missing x and y parameters';
3061 if (ref $x && ref $y) {
3062 unless (@$x == @$y) {
3063 $self->{ERRSTR} = 'length of x and y mismatch';
3067 if ($color->isa('Imager::Color')) {
3068 for my $i (0..$#{$opts{'x'}}) {
3069 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3074 for my $i (0..$#{$opts{'x'}}) {
3075 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3083 if ($color->isa('Imager::Color')) {
3084 i_ppix($self->{IMG}, $x, $y, $color)
3088 i_ppixf($self->{IMG}, $x, $y, $color)
3099 my %opts = ( "type"=>'8bit', @_);
3101 unless (exists $opts{'x'} && exists $opts{'y'}) {
3102 $self->{ERRSTR} = 'missing x and y parameters';
3108 if (ref $x && ref $y) {
3109 unless (@$x == @$y) {
3110 $self->{ERRSTR} = 'length of x and y mismatch';
3114 if ($opts{"type"} eq '8bit') {
3115 for my $i (0..$#{$opts{'x'}}) {
3116 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3120 for my $i (0..$#{$opts{'x'}}) {
3121 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3124 return wantarray ? @result : \@result;
3127 if ($opts{"type"} eq '8bit') {
3128 return i_get_pixel($self->{IMG}, $x, $y);
3131 return i_gpixf($self->{IMG}, $x, $y);
3140 my %opts = ( type => '8bit', x=>0, @_);
3142 $self->_valid_image or return;
3144 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3146 unless (defined $opts{'y'}) {
3147 $self->_set_error("missing y parameter");
3151 if ($opts{type} eq '8bit') {
3152 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3155 elsif ($opts{type} eq 'float') {
3156 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3159 elsif ($opts{type} eq 'index') {
3160 unless (i_img_type($self->{IMG})) {
3161 $self->_set_error("type => index only valid on paletted images");
3164 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3168 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3175 my %opts = ( x=>0, @_);
3177 $self->_valid_image or return;
3179 unless (defined $opts{'y'}) {
3180 $self->_set_error("missing y parameter");
3185 if (ref $opts{pixels} && @{$opts{pixels}}) {
3186 # try to guess the type
3187 if ($opts{pixels}[0]->isa('Imager::Color')) {
3188 $opts{type} = '8bit';
3190 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3191 $opts{type} = 'float';
3194 $self->_set_error("missing type parameter and could not guess from pixels");
3200 $opts{type} = '8bit';
3204 if ($opts{type} eq '8bit') {
3205 if (ref $opts{pixels}) {
3206 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3209 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3212 elsif ($opts{type} eq 'float') {
3213 if (ref $opts{pixels}) {
3214 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3217 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3220 elsif ($opts{type} eq 'index') {
3221 if (ref $opts{pixels}) {
3222 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3225 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3229 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3236 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3238 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3240 unless (defined $opts{'y'}) {
3241 $self->_set_error("missing y parameter");
3245 unless ($opts{channels}) {
3246 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3249 if ($opts{target}) {
3250 my $target = $opts{target};
3251 my $offset = $opts{offset};
3252 if ($opts{type} eq '8bit') {
3253 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3254 $opts{y}, @{$opts{channels}})
3256 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3257 return scalar(@samples);
3259 elsif ($opts{type} eq 'float') {
3260 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3261 $opts{y}, @{$opts{channels}});
3262 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3263 return scalar(@samples);
3265 elsif ($opts{type} =~ /^(\d+)bit$/) {
3269 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3270 $opts{y}, $bits, $target,
3271 $offset, @{$opts{channels}});
3272 unless (defined $count) {
3273 $self->_set_error(Imager->_error_as_msg);
3280 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3285 if ($opts{type} eq '8bit') {
3286 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3287 $opts{y}, @{$opts{channels}});
3289 elsif ($opts{type} eq 'float') {
3290 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3291 $opts{y}, @{$opts{channels}});
3293 elsif ($opts{type} =~ /^(\d+)bit$/) {
3297 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3298 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3303 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3311 my %opts = ( x => 0, offset => 0, @_ );
3313 unless ($self->{IMG}) {
3314 $self->_set_error('setsamples: empty input image');
3318 unless(defined $opts{data} && ref $opts{data}) {
3319 $self->_set_error('setsamples: data parameter missing or invalid');
3323 unless ($opts{channels}) {
3324 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3327 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3328 $self->_set_error('setsamples: type parameter missing or invalid');
3333 unless (defined $opts{width}) {
3334 $opts{width} = $self->getwidth() - $opts{x};
3337 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3338 $opts{channels}, $opts{data}, $opts{offset},
3340 unless (defined $count) {
3341 $self->_set_error(Imager->_error_as_msg);
3348 # make an identity matrix of the given size
3352 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3353 for my $c (0 .. ($size-1)) {
3354 $matrix->[$c][$c] = 1;
3359 # general function to convert an image
3361 my ($self, %opts) = @_;
3364 unless (defined wantarray) {
3365 my @caller = caller;
3366 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3370 # the user can either specify a matrix or preset
3371 # the matrix overrides the preset
3372 if (!exists($opts{matrix})) {
3373 unless (exists($opts{preset})) {
3374 $self->{ERRSTR} = "convert() needs a matrix or preset";
3378 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3379 # convert to greyscale, keeping the alpha channel if any
3380 if ($self->getchannels == 3) {
3381 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3383 elsif ($self->getchannels == 4) {
3384 # preserve the alpha channel
3385 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3390 $matrix = _identity($self->getchannels);
3393 elsif ($opts{preset} eq 'noalpha') {
3394 # strip the alpha channel
3395 if ($self->getchannels == 2 or $self->getchannels == 4) {
3396 $matrix = _identity($self->getchannels);
3397 pop(@$matrix); # lose the alpha entry
3400 $matrix = _identity($self->getchannels);
3403 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3405 $matrix = [ [ 1 ] ];
3407 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3408 $matrix = [ [ 0, 1 ] ];
3410 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3411 $matrix = [ [ 0, 0, 1 ] ];
3413 elsif ($opts{preset} eq 'alpha') {
3414 if ($self->getchannels == 2 or $self->getchannels == 4) {
3415 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3418 # the alpha is just 1 <shrug>
3419 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3422 elsif ($opts{preset} eq 'rgb') {
3423 if ($self->getchannels == 1) {
3424 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3426 elsif ($self->getchannels == 2) {
3427 # preserve the alpha channel
3428 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3431 $matrix = _identity($self->getchannels);
3434 elsif ($opts{preset} eq 'addalpha') {
3435 if ($self->getchannels == 1) {
3436 $matrix = _identity(2);
3438 elsif ($self->getchannels == 3) {
3439 $matrix = _identity(4);
3442 $matrix = _identity($self->getchannels);
3446 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3452 $matrix = $opts{matrix};
3455 my $new = Imager->new;
3456 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3457 unless ($new->{IMG}) {
3458 # most likely a bad matrix
3459 $self->{ERRSTR} = _error_as_msg();
3466 # general function to map an image through lookup tables
3469 my ($self, %opts) = @_;
3470 my @chlist = qw( red green blue alpha );
3472 if (!exists($opts{'maps'})) {
3473 # make maps from channel maps
3475 for $chnum (0..$#chlist) {
3476 if (exists $opts{$chlist[$chnum]}) {
3477 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3478 } elsif (exists $opts{'all'}) {
3479 $opts{'maps'}[$chnum] = $opts{'all'};
3483 if ($opts{'maps'} and $self->{IMG}) {
3484 i_map($self->{IMG}, $opts{'maps'} );
3490 my ($self, %opts) = @_;
3492 defined $opts{mindist} or $opts{mindist} = 0;
3494 defined $opts{other}
3495 or return $self->_set_error("No 'other' parameter supplied");
3496 defined $opts{other}{IMG}
3497 or return $self->_set_error("No image data in 'other' image");
3500 or return $self->_set_error("No image data");
3502 my $result = Imager->new;
3503 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3505 or return $self->_set_error($self->_error_as_msg());
3510 # destructive border - image is shrunk by one pixel all around
3513 my ($self,%opts)=@_;
3514 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3515 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3519 # Get the width of an image
3523 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3524 return (i_img_info($self->{IMG}))[0];
3527 # Get the height of an image
3531 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3532 return (i_img_info($self->{IMG}))[1];
3535 # Get number of channels in an image
3539 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3540 return i_img_getchannels($self->{IMG});
3547 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3548 return i_img_getmask($self->{IMG});
3556 if (!defined($self->{IMG})) {
3557 $self->{ERRSTR} = 'image is empty';
3560 unless (defined $opts{mask}) {
3561 $self->_set_error("mask parameter required");
3564 i_img_setmask( $self->{IMG} , $opts{mask} );
3569 # Get number of colors in an image
3573 my %opts=('maxcolors'=>2**30,@_);
3574 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3575 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3576 return ($rc==-1? undef : $rc);
3579 # Returns a reference to a hash. The keys are colour named (packed) and the
3580 # values are the number of pixels in this colour.
3581 sub getcolorusagehash {
3584 my %opts = ( maxcolors => 2**30, @_ );
3585 my $max_colors = $opts{maxcolors};
3586 unless (defined $max_colors && $max_colors > 0) {
3587 $self->_set_error('maxcolors must be a positive integer');
3591 unless (defined $self->{IMG}) {
3592 $self->_set_error('empty input image');
3596 my $channels= $self->getchannels;
3597 # We don't want to look at the alpha channel, because some gifs using it
3598 # doesn't define it for every colour (but only for some)
3599 $channels -= 1 if $channels == 2 or $channels == 4;
3601 my $height = $self->getheight;
3602 for my $y (0 .. $height - 1) {
3603 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3604 while (length $colors) {
3605 $color_use{ substr($colors, 0, $channels, '') }++;
3607 keys %color_use > $max_colors
3613 # This will return a ordered array of the colour usage. Kind of the sorted
3614 # version of the values of the hash returned by getcolorusagehash.
3615 # You might want to add safety checks and change the names, etc...
3619 my %opts = ( maxcolors => 2**30, @_ );
3620 my $max_colors = $opts{maxcolors};
3621 unless (defined $max_colors && $max_colors > 0) {
3622 $self->_set_error('maxcolors must be a positive integer');
3626 unless (defined $self->{IMG}) {
3627 $self->_set_error('empty input image');
3631 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3634 # draw string to an image
3638 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3640 my %input=('x'=>0, 'y'=>0, @_);
3641 defined($input{string}) or $input{string} = $input{text};
3643 unless(defined $input{string}) {
3644 $self->{ERRSTR}="missing required parameter 'string'";
3648 unless($input{font}) {
3649 $self->{ERRSTR}="missing required parameter 'font'";
3653 unless ($input{font}->draw(image=>$self, %input)) {
3665 unless ($self->{IMG}) {
3666 $self->{ERRSTR}='empty input image';
3675 my %input=('x'=>0, 'y'=>0, @_);
3676 defined $input{string}
3677 or $input{string} = $input{text};
3679 unless(exists $input{string}) {
3680 $self->_set_error("missing required parameter 'string'");
3684 unless($input{font}) {
3685 $self->_set_error("missing required parameter 'font'");
3690 unless (@result = $input{font}->align(image=>$img, %input)) {
3694 return wantarray ? @result : $result[0];
3697 my @file_limit_names = qw/width height bytes/;
3699 sub set_file_limits {
3706 @values{@file_limit_names} = (0) x @file_limit_names;
3709 @values{@file_limit_names} = i_get_image_file_limits();
3712 for my $key (keys %values) {
3713 defined $opts{$key} and $values{$key} = $opts{$key};
3716 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3719 sub get_file_limits {
3720 i_get_image_file_limits();
3723 # Shortcuts that can be exported
3725 sub newcolor { Imager::Color->new(@_); }
3726 sub newfont { Imager::Font->new(@_); }
3727 sub NCF { Imager::Color::Float->new(@_) }
3729 *NC=*newcolour=*newcolor;
3736 #### Utility routines
3739 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3743 my ($self, $msg) = @_;
3746 $self->{ERRSTR} = $msg;
3754 # Default guess for the type of an image from extension
3756 sub def_guess_type {
3759 $ext=($name =~ m/\.([^\.]+)$/)[0];
3760 return 'tiff' if ($ext =~ m/^tiff?$/);
3761 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3762 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3763 return 'png' if ($ext eq "png");
3764 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3765 return 'tga' if ($ext eq "tga");
3766 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3767 return 'gif' if ($ext eq "gif");
3768 return 'raw' if ($ext eq "raw");
3769 return lc $ext; # best guess
3774 return @combine_types;
3777 # get the minimum of a list
3781 for(@_) { if ($_<$mx) { $mx=$_; }}
3785 # get the maximum of a list
3789 for(@_) { if ($_>$mx) { $mx=$_; }}
3793 # string stuff for iptc headers
3797 $str = substr($str,3);
3798 $str =~ s/[\n\r]//g;
3805 # A little hack to parse iptc headers.
3810 my($caption,$photogr,$headln,$credit);
3812 my $str=$self->{IPTCRAW};
3817 @ar=split(/8BIM/,$str);
3822 @sar=split(/\034\002/);
3823 foreach $item (@sar) {
3824 if ($item =~ m/^x/) {
3825 $caption = _clean($item);
3828 if ($item =~ m/^P/) {
3829 $photogr = _clean($item);
3832 if ($item =~ m/^i/) {
3833 $headln = _clean($item);
3836 if ($item =~ m/^n/) {
3837 $credit = _clean($item);
3843 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3850 or die "Only C language supported";
3852 require Imager::ExtUtils;
3853 return Imager::ExtUtils->inline_config;
3856 # threads shouldn't try to close raw Imager objects
3857 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3859 # backward compatibility for %formats
3860 package Imager::FORMATS;
3862 use constant IX_FORMATS => 0;
3863 use constant IX_LIST => 1;
3864 use constant IX_INDEX => 2;
3865 use constant IX_CLASSES => 3;
3868 my ($class, $formats, $classes) = @_;
3870 return bless [ $formats, [ ], 0, $classes ], $class;
3874 my ($self, $key) = @_;
3876 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
3878 if (eval { require $file; 1 }) {
3884 $self->[IX_FORMATS]{$key} = $value;
3890 my ($self, $key) = @_;
3892 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
3894 $self->[IX_CLASSES]{$key} or return undef;
3896 return $self->_check($key);
3900 die "%Imager::formats is not user monifiable";
3904 die "%Imager::formats is not user monifiable";
3908 die "%Imager::formats is not user monifiable";
3912 my ($self, $key) = @_;
3914 if (exists $self->[IX_FORMATS]{$key}) {
3915 my $value = $self->[IX_FORMATS]{$key}
3920 $self->_check($key) or return 1==0;
3928 unless (@{$self->[IX_LIST]}) {
3930 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
3931 keys %{$self->[IX_FORMATS]};
3933 for my $key (keys %{$self->[IX_CLASSES]}) {
3934 $self->[IX_FORMATS]{$key} and next;
3936 and push @{$self->[IX_LIST]}, $key;
3940 @{$self->[IX_LIST]} or return;
3941 $self->[IX_INDEX] = 1;
3942 return $self->[IX_LIST][0];
3948 $self->[IX_INDEX] < @{$self->[IX_LIST]}
3951 return $self->[IX_LIST][$self->[IX_INDEX]++];
3957 return scalar @{$self->[IX_LIST]};
3962 # Below is the stub of documentation for your module. You better edit it!
3966 Imager - Perl extension for Generating 24 bit Images
3976 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3981 # see Imager::Files for information on the read() method
3982 my $im = Imager->new(file=>$file)
3983 or die Imager->errstr();
3985 $file =~ s/\.[^.]*$//;
3987 # Create smaller version
3988 # documented in Imager::Transformations
3989 my $thumb = $img->scale(scalefactor=>.3);
3991 # Autostretch individual channels
3992 $thumb->filter(type=>'autolevels');
3994 # try to save in one of these formats
3997 for $format ( qw( png gif jpeg tiff ppm ) ) {
3998 # Check if given format is supported
3999 if ($Imager::formats{$format}) {
4000 $file.="_low.$format";
4001 print "Storing image as: $file\n";
4002 # documented in Imager::Files
4003 $thumb->write(file=>$file) or
4011 Imager is a module for creating and altering images. It can read and
4012 write various image formats, draw primitive shapes like lines,and
4013 polygons, blend multiple images together in various ways, scale, crop,
4014 render text and more.
4016 =head2 Overview of documentation
4022 Imager - This document - Synopsis, Example, Table of Contents and
4027 L<Imager::Tutorial> - a brief introduction to Imager.
4031 L<Imager::Cookbook> - how to do various things with Imager.
4035 L<Imager::ImageTypes> - Basics of constructing image objects with
4036 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4037 8/16/double bits/channel, color maps, channel masks, image tags, color
4038 quantization. Also discusses basic image information methods.
4042 L<Imager::Files> - IO interaction, reading/writing images, format
4047 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4052 L<Imager::Color> - Color specification.
4056 L<Imager::Fill> - Fill pattern specification.
4060 L<Imager::Font> - General font rendering, bounding boxes and font
4065 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4066 blending, pasting, convert and map.
4070 L<Imager::Engines> - Programmable transformations through
4071 C<transform()>, C<transform2()> and C<matrix_transform()>.
4075 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4080 L<Imager::Expr> - Expressions for evaluation engine used by
4085 L<Imager::Matrix2d> - Helper class for affine transformations.
4089 L<Imager::Fountain> - Helper for making gradient profiles.
4093 L<Imager::API> - using Imager's C API
4097 L<Imager::APIRef> - API function reference
4101 L<Imager::Inline> - using Imager's C API from Inline::C
4105 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4109 =head2 Basic Overview
4111 An Image object is created with C<$img = Imager-E<gt>new()>.
4114 $img=Imager->new(); # create empty image
4115 $img->read(file=>'lena.png',type=>'png') or # read image from file
4116 die $img->errstr(); # give an explanation
4117 # if something failed
4119 or if you want to create an empty image:
4121 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4123 This example creates a completely black image of width 400 and height
4126 =head1 ERROR HANDLING
4128 In general a method will return false when it fails, if it does use
4129 the C<errstr()> method to find out why:
4135 Returns the last error message in that context.
4137 If the last error you received was from calling an object method, such
4138 as read, call errstr() as an object method to find out why:
4140 my $image = Imager->new;
4141 $image->read(file => 'somefile.gif')
4142 or die $image->errstr;
4144 If it was a class method then call errstr() as a class method:
4146 my @imgs = Imager->read_multi(file => 'somefile.gif')
4147 or die Imager->errstr;
4149 Note that in some cases object methods are implemented in terms of
4150 class methods so a failing object method may set both.
4154 The C<Imager-E<gt>new> method is described in detail in
4155 L<Imager::ImageTypes>.
4159 Where to find information on methods for Imager class objects.
4161 addcolors() - L<Imager::ImageTypes/addcolors> - add colors to a
4164 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4166 align_string() - L<Imager::Draw/align_string> - draw text aligned on a
4169 arc() - L<Imager::Draw/arc> - draw a filled arc
4171 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4174 box() - L<Imager::Draw/box> - draw a filled or outline box.
4176 circle() - L<Imager::Draw/circle> - draw a filled circle
4178 colorcount() - L<Imager::Draw/colorcount> - the number of colors in an
4179 image's palette (paletted images only)
4181 combines() - L<Imager::Draw/combines> - return a list of the different
4182 combine type keywords
4184 compose() - L<Imager::Transformations/compose> - compose one image
4187 convert() - L<Imager::Transformations/"Color transformations"> -
4188 transform the color space
4190 copy() - L<Imager::Transformations/copy> - make a duplicate of an
4193 crop() - L<Imager::Transformations/crop> - extract part of an image
4195 def_guess_type() - L<Imager::Files/def_guess_type> - default function
4196 used to guess the output file format based on the output file name
4198 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4200 difference() - L<Imager::Filters/"Image Difference"> - produce a
4201 difference images from two input images.
4203 errstr() - L<"Basic Overview"> - the error from the last failed
4206 filter() - L<Imager::Filters> - image filtering
4208 findcolor() - L<Imager::ImageTypes/findcolor> - search the image
4209 palette, if it has one
4211 flip() - L<Imager::Transformations/flip> - flip an image, vertically,
4214 flood_fill() - L<Imager::Draw/flood_fill> - fill an enclosed or same
4217 getchannels() - L<Imager::ImageTypes/getchannels> - the number of
4218 samples per pixel for an image
4220 getcolorcount() - L<Imager::ImageTypes/getcolorcount> - the number of
4221 different colors used by an image (works for direct color images)
4223 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4224 palette, if it has one
4226 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4228 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4230 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4232 getheight() - L<Imager::ImageTypes/getwidth> - height of the image in
4235 getmask() - L<Imager::ImageTypes/getmask> - write mask for the image
4237 getpixel() - L<Imager::Draw/getpixel> - retrieve one or more pixel
4240 getsamples() - L<Imager::Draw/getsamples> - retrieve samples from a
4241 row or partial row of pixels.
4243 getscanline() - L<Imager::Draw/getscanline> - retrieve colors for a
4244 row or partial row of pixels.
4246 getwidth() - L<Imager::ImageTypes/getwidth> - width of the image in
4249 img_set() - L<Imager::ImageTypes/img_set> - re-use an Imager object
4252 init() - L<Imager::ImageTypes/init>
4254 is_bilevel() - L<Imager::ImageTypes/is_bilevel> - returns whether
4255 image write functions should write the image in their bilevel (blank
4256 and white, no gray levels) format
4258 line() - L<Imager::Draw/line> - draw an interval
4260 load_plugin() - L<Imager::Filters/load_plugin>
4262 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4265 masked() - L<Imager::ImageTypes/masked> - make a masked image
4267 matrix_transform() - L<Imager::Engines/matrix_transform>
4269 maxcolors() - L<Imager::ImageTypes/maxcolors>
4271 NC() - L<Imager::Handy/NC>
4273 NCF() - L<Imager::Handy/NCF>
4275 new() - L<Imager::ImageTypes/new>
4277 newcolor() - L<Imager::Handy/newcolor>
4279 newcolour() - L<Imager::Handy/newcolour>
4281 newfont() - L<Imager::Handy/newfont>
4283 NF() - L<Imager::Handy/NF>
4285 open() - L<Imager::Files> - an alias for read()
4289 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4292 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4294 polygon() - L<Imager::Draw/polygon>
4296 polyline() - L<Imager::Draw/polyline>
4298 read() - L<Imager::Files> - read a single image from an image file
4300 read_multi() - L<Imager::Files> - read multiple images from an image
4303 read_types() - L<Imager::Files/read_types> - list image types Imager
4306 register_filter() - L<Imager::Filters/register_filter>
4308 register_reader() - L<Imager::Files/register_reader>
4310 register_writer() - L<Imager::Files/register_writer>
4312 rotate() - L<Imager::Transformations/rotate>
4314 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4315 image and use the alpha channel
4317 scale() - L<Imager::Transformations/scale>
4319 scale_calculate() - L<Imager::Transformations/scale_calculate>
4321 scaleX() - L<Imager::Transformations/scaleX>
4323 scaleY() - L<Imager::Transformations/scaleY>
4325 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4328 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4330 setmask() - L<Imager::ImageTypes/setmask>
4332 setpixel() - L<Imager::Draw/setpixel>
4334 setsamples() - L<Imager::Draw/setsamples>
4336 setscanline() - L<Imager::Draw/setscanline>
4338 settag() - L<Imager::ImageTypes/settag>
4340 string() - L<Imager::Draw/string> - draw text on an image
4342 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4344 to_paletted() - L<Imager::ImageTypes/to_paletted>
4346 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4348 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4350 transform() - L<Imager::Engines/"transform">
4352 transform2() - L<Imager::Engines/"transform2">
4354 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4356 unload_plugin() - L<Imager::Filters/unload_plugin>
4358 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4361 write() - L<Imager::Files> - write an image to a file
4363 write_multi() - L<Imager::Files> - write multiple image to an image
4366 write_types() - L<Imager::Files/read_types> - list image types Imager
4369 =head1 CONCEPT INDEX
4371 animated GIF - L<Imager::Files/"Writing an animated GIF">
4373 aspect ratio - L<Imager::ImageTypes/i_xres>,
4374 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4376 blend - alpha blending one image onto another
4377 L<Imager::Transformations/rubthrough>
4379 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4381 boxes, drawing - L<Imager::Draw/box>
4383 changes between image - L<Imager::Filters/"Image Difference">
4385 color - L<Imager::Color>
4387 color names - L<Imager::Color>, L<Imager::Color::Table>
4389 combine modes - L<Imager::Draw/"Combine Types">
4391 compare images - L<Imager::Filters/"Image Difference">
4393 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4395 convolution - L<Imager::Filters/conv>
4397 cropping - L<Imager::Transformations/crop>
4399 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4401 C<diff> images - L<Imager::Filters/"Image Difference">
4403 dpi - L<Imager::ImageTypes/i_xres>,
4404 L<Imager::Cookbook/"Image spatial resolution">
4406 drawing boxes - L<Imager::Draw/box>
4408 drawing lines - L<Imager::Draw/line>
4410 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4412 error message - L<"ERROR HANDLING">
4414 files, font - L<Imager::Font>
4416 files, image - L<Imager::Files>
4418 filling, types of fill - L<Imager::Fill>
4420 filling, boxes - L<Imager::Draw/box>
4422 filling, flood fill - L<Imager::Draw/flood_fill>
4424 flood fill - L<Imager::Draw/flood_fill>
4426 fonts - L<Imager::Font>
4428 fonts, drawing with - L<Imager::Draw/string>,
4429 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4431 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4433 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4435 fountain fill - L<Imager::Fill/"Fountain fills">,
4436 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4437 L<Imager::Filters/gradgen>
4439 GIF files - L<Imager::Files/"GIF">
4441 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4443 gradient fill - L<Imager::Fill/"Fountain fills">,
4444 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4445 L<Imager::Filters/gradgen>
4447 gray scale, convert image to - L<Imager::Transformations/convert>
4449 guassian blur - L<Imager::Filters/guassian>
4451 hatch fills - L<Imager::Fill/"Hatched fills">
4453 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4455 invert image - L<Imager::Filters/hardinvert>,
4456 L<Imager::Filters/hardinvertall>
4458 JPEG - L<Imager::Files/"JPEG">
4460 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4462 lines, drawing - L<Imager::Draw/line>
4464 matrix - L<Imager::Matrix2d>,
4465 L<Imager::Transformations/"Matrix Transformations">,
4466 L<Imager::Font/transform>
4468 metadata, image - L<Imager::ImageTypes/"Tags">
4470 mosaic - L<Imager::Filters/mosaic>
4472 noise, filter - L<Imager::Filters/noise>
4474 noise, rendered - L<Imager::Filters/turbnoise>,
4475 L<Imager::Filters/radnoise>
4477 paste - L<Imager::Transformations/paste>,
4478 L<Imager::Transformations/rubthrough>
4480 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4481 L<Imager::ImageTypes/new>
4483 =for stopwords posterize
4485 posterize - L<Imager::Filters/postlevels>
4487 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4489 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4491 rectangles, drawing - L<Imager::Draw/box>
4493 resizing an image - L<Imager::Transformations/scale>,
4494 L<Imager::Transformations/crop>
4496 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4498 saving an image - L<Imager::Files>
4500 scaling - L<Imager::Transformations/scale>
4502 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4504 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4506 size, image - L<Imager::ImageTypes/getwidth>,
4507 L<Imager::ImageTypes/getheight>
4509 size, text - L<Imager::Font/bounding_box>
4511 tags, image metadata - L<Imager::ImageTypes/"Tags">
4513 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4514 L<Imager::Font::Wrap>
4516 text, wrapping text in an area - L<Imager::Font::Wrap>
4518 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4520 tiles, color - L<Imager::Filters/mosaic>
4522 =for stopwords unsharp
4524 unsharp mask - L<Imager::Filters/unsharpmask>
4526 watermark - L<Imager::Filters/watermark>
4528 writing an image to a file - L<Imager::Files>
4532 Imager doesn't support perl threads.
4534 Imager has limited code to prevent double frees if you create images,
4535 colors etc, and then create a thread, but has no code to prevent two
4536 threads entering Imager's error handling code, and none is likely to
4541 The best place to get help with Imager is the mailing list.
4543 To subscribe send a message with C<subscribe> in the body to:
4545 imager-devel+request@molar.is
4551 L<http://www.molar.is/en/lists/imager-devel/>
4555 where you can also find the mailing list archive.
4557 You can report bugs by pointing your browser at:
4561 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4565 or by sending an email to:
4569 bug-Imager@rt.cpan.org
4573 Please remember to include the versions of Imager, perl, supporting
4574 libraries, and any relevant code. If you have specific images that
4575 cause the problems, please include those too.
4577 If you don't want to publish your email address on a mailing list you
4578 can use CPAN::Forum:
4580 http://www.cpanforum.com/dist/Imager
4582 You will need to register to post.
4584 =head1 CONTRIBUTING TO IMAGER
4590 If you like or dislike Imager, you can add a public review of Imager
4593 http://cpanratings.perl.org/dist/Imager
4595 =for stopwords Bitcard
4597 This requires a Bitcard account (http://www.bitcard.org).
4599 You can also send email to the maintainer below.
4601 If you send me a bug report via email, it will be copied to Request
4606 I accept patches, preferably against the main branch in subversion.
4607 You should include an explanation of the reason for why the patch is
4610 Your patch should include regression tests where possible, otherwise
4611 it will be delayed until I get a chance to write them.
4615 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4617 Arnar M. Hrafnkelsson is the original author of Imager.
4619 Many others have contributed to Imager, please see the C<README> for a
4624 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4625 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4626 L<Imager::Font>(3), L<Imager::Transformations>(3),
4627 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4628 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4630 L<http://imager.perl.org/>
4632 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4634 Other perl imaging modules include:
4636 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).