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 $dflcl=i_color_new(255,255,255,255);
2656 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2658 if (exists $opts{'box'}) {
2659 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2660 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2661 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2662 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2665 if ($opts{filled}) {
2666 my $color = _color($opts{'color'});
2668 $self->{ERRSTR} = $Imager::ERRSTR;
2671 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2672 $opts{ymax}, $color);
2674 elsif ($opts{fill}) {
2675 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2676 # assume it's a hash ref
2677 require 'Imager/Fill.pm';
2678 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2679 $self->{ERRSTR} = $Imager::ERRSTR;
2683 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2684 $opts{ymax},$opts{fill}{fill});
2687 my $color = _color($opts{'color'});
2689 $self->{ERRSTR} = $Imager::ERRSTR;
2692 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2700 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2701 my $dflcl= [ 255, 255, 255, 255];
2706 'r'=>_min($self->getwidth(),$self->getheight())/3,
2707 'x'=>$self->getwidth()/2,
2708 'y'=>$self->getheight()/2,
2715 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2716 # assume it's a hash ref
2717 require 'Imager/Fill.pm';
2718 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2719 $self->{ERRSTR} = $Imager::ERRSTR;
2723 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2724 $opts{'d2'}, $opts{fill}{fill});
2726 elsif ($opts{filled}) {
2727 my $color = _color($opts{'color'});
2729 $self->{ERRSTR} = $Imager::ERRSTR;
2732 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2733 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2737 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2738 $opts{'d1'}, $opts{'d2'}, $color);
2742 my $color = _color($opts{'color'});
2743 if ($opts{d2} - $opts{d1} >= 360) {
2744 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2747 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2753 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2754 # assume it's a hash ref
2755 require 'Imager/Fill.pm';
2756 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2757 $self->{ERRSTR} = $Imager::ERRSTR;
2761 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2762 $opts{'d2'}, $opts{fill}{fill});
2765 my $color = _color($opts{'color'});
2767 $self->{ERRSTR} = $Imager::ERRSTR;
2770 if ($opts{filled}) {
2771 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2772 $opts{'d1'}, $opts{'d2'}, $color);
2775 if ($opts{d1} == 0 && $opts{d2} == 361) {
2776 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2779 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2785 $self->_set_error($self->_error_as_msg);
2792 # Draws a line from one point to the other
2793 # the endpoint is set if the endp parameter is set which it is by default.
2794 # to turn of the endpoint being set use endp=>0 when calling line.
2798 my $dflcl=i_color_new(0,0,0,0);
2799 my %opts=(color=>$dflcl,
2802 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2804 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2805 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2807 my $color = _color($opts{'color'});
2809 $self->{ERRSTR} = $Imager::ERRSTR;
2813 $opts{antialias} = $opts{aa} if defined $opts{aa};
2814 if ($opts{antialias}) {
2815 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2816 $color, $opts{endp});
2818 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2819 $color, $opts{endp});
2824 # Draws a line between an ordered set of points - It more or less just transforms this
2825 # into a list of lines.
2829 my ($pt,$ls,@points);
2830 my $dflcl=i_color_new(0,0,0,0);
2831 my %opts=(color=>$dflcl,@_);
2833 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2835 if (exists($opts{points})) { @points=@{$opts{points}}; }
2836 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2837 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2840 # print Dumper(\@points);
2842 my $color = _color($opts{'color'});
2844 $self->{ERRSTR} = $Imager::ERRSTR;
2847 $opts{antialias} = $opts{aa} if defined $opts{aa};
2848 if ($opts{antialias}) {
2851 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2858 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2868 my ($pt,$ls,@points);
2869 my $dflcl = i_color_new(0,0,0,0);
2870 my %opts = (color=>$dflcl, @_);
2872 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2874 if (exists($opts{points})) {
2875 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2876 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2879 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2880 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2883 if ($opts{'fill'}) {
2884 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2885 # assume it's a hash ref
2886 require 'Imager/Fill.pm';
2887 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2888 $self->{ERRSTR} = $Imager::ERRSTR;
2892 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2893 $opts{'fill'}{'fill'});
2896 my $color = _color($opts{'color'});
2898 $self->{ERRSTR} = $Imager::ERRSTR;
2901 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2908 # this the multipoint bezier curve
2909 # this is here more for testing that actual usage since
2910 # this is not a good algorithm. Usually the curve would be
2911 # broken into smaller segments and each done individually.
2915 my ($pt,$ls,@points);
2916 my $dflcl=i_color_new(0,0,0,0);
2917 my %opts=(color=>$dflcl,@_);
2919 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2921 if (exists $opts{points}) {
2922 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2923 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2926 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2927 $self->{ERRSTR}='Missing or invalid points.';
2931 my $color = _color($opts{'color'});
2933 $self->{ERRSTR} = $Imager::ERRSTR;
2936 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2942 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2945 unless (exists $opts{'x'} && exists $opts{'y'}) {
2946 $self->{ERRSTR} = "missing seed x and y parameters";
2950 if ($opts{border}) {
2951 my $border = _color($opts{border});
2953 $self->_set_error($Imager::ERRSTR);
2957 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2958 # assume it's a hash ref
2959 require Imager::Fill;
2960 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2961 $self->{ERRSTR} = $Imager::ERRSTR;
2965 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2966 $opts{fill}{fill}, $border);
2969 my $color = _color($opts{'color'});
2971 $self->{ERRSTR} = $Imager::ERRSTR;
2974 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2981 $self->{ERRSTR} = $self->_error_as_msg();
2987 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2988 # assume it's a hash ref
2989 require 'Imager/Fill.pm';
2990 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2991 $self->{ERRSTR} = $Imager::ERRSTR;
2995 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2998 my $color = _color($opts{'color'});
3000 $self->{ERRSTR} = $Imager::ERRSTR;
3003 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3009 $self->{ERRSTR} = $self->_error_as_msg();
3016 my ($self, %opts) = @_;
3018 my $color = $opts{color};
3019 unless (defined $color) {
3020 $color = $self->{fg};
3021 defined $color or $color = NC(255, 255, 255);
3024 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3025 $color = _color($color)
3029 unless (exists $opts{'x'} && exists $opts{'y'}) {
3030 $self->{ERRSTR} = 'missing x and y parameters';
3036 if (ref $x && ref $y) {
3037 unless (@$x == @$y) {
3038 $self->{ERRSTR} = 'length of x and y mismatch';
3042 if ($color->isa('Imager::Color')) {
3043 for my $i (0..$#{$opts{'x'}}) {
3044 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3049 for my $i (0..$#{$opts{'x'}}) {
3050 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3058 if ($color->isa('Imager::Color')) {
3059 i_ppix($self->{IMG}, $x, $y, $color)
3063 i_ppixf($self->{IMG}, $x, $y, $color)
3074 my %opts = ( "type"=>'8bit', @_);
3076 unless (exists $opts{'x'} && exists $opts{'y'}) {
3077 $self->{ERRSTR} = 'missing x and y parameters';
3083 if (ref $x && ref $y) {
3084 unless (@$x == @$y) {
3085 $self->{ERRSTR} = 'length of x and y mismatch';
3089 if ($opts{"type"} eq '8bit') {
3090 for my $i (0..$#{$opts{'x'}}) {
3091 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3095 for my $i (0..$#{$opts{'x'}}) {
3096 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3099 return wantarray ? @result : \@result;
3102 if ($opts{"type"} eq '8bit') {
3103 return i_get_pixel($self->{IMG}, $x, $y);
3106 return i_gpixf($self->{IMG}, $x, $y);
3115 my %opts = ( type => '8bit', x=>0, @_);
3117 $self->_valid_image or return;
3119 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3121 unless (defined $opts{'y'}) {
3122 $self->_set_error("missing y parameter");
3126 if ($opts{type} eq '8bit') {
3127 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3130 elsif ($opts{type} eq 'float') {
3131 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3134 elsif ($opts{type} eq 'index') {
3135 unless (i_img_type($self->{IMG})) {
3136 $self->_set_error("type => index only valid on paletted images");
3139 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3143 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3150 my %opts = ( x=>0, @_);
3152 $self->_valid_image or return;
3154 unless (defined $opts{'y'}) {
3155 $self->_set_error("missing y parameter");
3160 if (ref $opts{pixels} && @{$opts{pixels}}) {
3161 # try to guess the type
3162 if ($opts{pixels}[0]->isa('Imager::Color')) {
3163 $opts{type} = '8bit';
3165 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3166 $opts{type} = 'float';
3169 $self->_set_error("missing type parameter and could not guess from pixels");
3175 $opts{type} = '8bit';
3179 if ($opts{type} eq '8bit') {
3180 if (ref $opts{pixels}) {
3181 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3184 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3187 elsif ($opts{type} eq 'float') {
3188 if (ref $opts{pixels}) {
3189 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3192 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3195 elsif ($opts{type} eq 'index') {
3196 if (ref $opts{pixels}) {
3197 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3200 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3204 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3211 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3213 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3215 unless (defined $opts{'y'}) {
3216 $self->_set_error("missing y parameter");
3220 unless ($opts{channels}) {
3221 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3224 if ($opts{target}) {
3225 my $target = $opts{target};
3226 my $offset = $opts{offset};
3227 if ($opts{type} eq '8bit') {
3228 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3229 $opts{y}, @{$opts{channels}})
3231 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3232 return scalar(@samples);
3234 elsif ($opts{type} eq 'float') {
3235 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3236 $opts{y}, @{$opts{channels}});
3237 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3238 return scalar(@samples);
3240 elsif ($opts{type} =~ /^(\d+)bit$/) {
3244 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3245 $opts{y}, $bits, $target,
3246 $offset, @{$opts{channels}});
3247 unless (defined $count) {
3248 $self->_set_error(Imager->_error_as_msg);
3255 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3260 if ($opts{type} eq '8bit') {
3261 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3262 $opts{y}, @{$opts{channels}});
3264 elsif ($opts{type} eq 'float') {
3265 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3266 $opts{y}, @{$opts{channels}});
3268 elsif ($opts{type} =~ /^(\d+)bit$/) {
3272 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3273 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3278 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3286 my %opts = ( x => 0, offset => 0, @_ );
3288 unless ($self->{IMG}) {
3289 $self->_set_error('setsamples: empty input image');
3293 unless(defined $opts{data} && ref $opts{data}) {
3294 $self->_set_error('setsamples: data parameter missing or invalid');
3298 unless ($opts{channels}) {
3299 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3302 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3303 $self->_set_error('setsamples: type parameter missing or invalid');
3308 unless (defined $opts{width}) {
3309 $opts{width} = $self->getwidth() - $opts{x};
3312 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3313 $opts{channels}, $opts{data}, $opts{offset},
3315 unless (defined $count) {
3316 $self->_set_error(Imager->_error_as_msg);
3323 # make an identity matrix of the given size
3327 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3328 for my $c (0 .. ($size-1)) {
3329 $matrix->[$c][$c] = 1;
3334 # general function to convert an image
3336 my ($self, %opts) = @_;
3339 unless (defined wantarray) {
3340 my @caller = caller;
3341 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3345 # the user can either specify a matrix or preset
3346 # the matrix overrides the preset
3347 if (!exists($opts{matrix})) {
3348 unless (exists($opts{preset})) {
3349 $self->{ERRSTR} = "convert() needs a matrix or preset";
3353 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3354 # convert to greyscale, keeping the alpha channel if any
3355 if ($self->getchannels == 3) {
3356 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3358 elsif ($self->getchannels == 4) {
3359 # preserve the alpha channel
3360 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3365 $matrix = _identity($self->getchannels);
3368 elsif ($opts{preset} eq 'noalpha') {
3369 # strip the alpha channel
3370 if ($self->getchannels == 2 or $self->getchannels == 4) {
3371 $matrix = _identity($self->getchannels);
3372 pop(@$matrix); # lose the alpha entry
3375 $matrix = _identity($self->getchannels);
3378 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3380 $matrix = [ [ 1 ] ];
3382 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3383 $matrix = [ [ 0, 1 ] ];
3385 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3386 $matrix = [ [ 0, 0, 1 ] ];
3388 elsif ($opts{preset} eq 'alpha') {
3389 if ($self->getchannels == 2 or $self->getchannels == 4) {
3390 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3393 # the alpha is just 1 <shrug>
3394 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3397 elsif ($opts{preset} eq 'rgb') {
3398 if ($self->getchannels == 1) {
3399 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3401 elsif ($self->getchannels == 2) {
3402 # preserve the alpha channel
3403 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3406 $matrix = _identity($self->getchannels);
3409 elsif ($opts{preset} eq 'addalpha') {
3410 if ($self->getchannels == 1) {
3411 $matrix = _identity(2);
3413 elsif ($self->getchannels == 3) {
3414 $matrix = _identity(4);
3417 $matrix = _identity($self->getchannels);
3421 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3427 $matrix = $opts{matrix};
3430 my $new = Imager->new;
3431 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3432 unless ($new->{IMG}) {
3433 # most likely a bad matrix
3434 $self->{ERRSTR} = _error_as_msg();
3441 # general function to map an image through lookup tables
3444 my ($self, %opts) = @_;
3445 my @chlist = qw( red green blue alpha );
3447 if (!exists($opts{'maps'})) {
3448 # make maps from channel maps
3450 for $chnum (0..$#chlist) {
3451 if (exists $opts{$chlist[$chnum]}) {
3452 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3453 } elsif (exists $opts{'all'}) {
3454 $opts{'maps'}[$chnum] = $opts{'all'};
3458 if ($opts{'maps'} and $self->{IMG}) {
3459 i_map($self->{IMG}, $opts{'maps'} );
3465 my ($self, %opts) = @_;
3467 defined $opts{mindist} or $opts{mindist} = 0;
3469 defined $opts{other}
3470 or return $self->_set_error("No 'other' parameter supplied");
3471 defined $opts{other}{IMG}
3472 or return $self->_set_error("No image data in 'other' image");
3475 or return $self->_set_error("No image data");
3477 my $result = Imager->new;
3478 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3480 or return $self->_set_error($self->_error_as_msg());
3485 # destructive border - image is shrunk by one pixel all around
3488 my ($self,%opts)=@_;
3489 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3490 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3494 # Get the width of an image
3498 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3499 return (i_img_info($self->{IMG}))[0];
3502 # Get the height of an image
3506 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3507 return (i_img_info($self->{IMG}))[1];
3510 # Get number of channels in an image
3514 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3515 return i_img_getchannels($self->{IMG});
3522 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3523 return i_img_getmask($self->{IMG});
3531 if (!defined($self->{IMG})) {
3532 $self->{ERRSTR} = 'image is empty';
3535 unless (defined $opts{mask}) {
3536 $self->_set_error("mask parameter required");
3539 i_img_setmask( $self->{IMG} , $opts{mask} );
3544 # Get number of colors in an image
3548 my %opts=('maxcolors'=>2**30,@_);
3549 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3550 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3551 return ($rc==-1? undef : $rc);
3554 # Returns a reference to a hash. The keys are colour named (packed) and the
3555 # values are the number of pixels in this colour.
3556 sub getcolorusagehash {
3559 my %opts = ( maxcolors => 2**30, @_ );
3560 my $max_colors = $opts{maxcolors};
3561 unless (defined $max_colors && $max_colors > 0) {
3562 $self->_set_error('maxcolors must be a positive integer');
3566 unless (defined $self->{IMG}) {
3567 $self->_set_error('empty input image');
3571 my $channels= $self->getchannels;
3572 # We don't want to look at the alpha channel, because some gifs using it
3573 # doesn't define it for every colour (but only for some)
3574 $channels -= 1 if $channels == 2 or $channels == 4;
3576 my $height = $self->getheight;
3577 for my $y (0 .. $height - 1) {
3578 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3579 while (length $colors) {
3580 $color_use{ substr($colors, 0, $channels, '') }++;
3582 keys %color_use > $max_colors
3588 # This will return a ordered array of the colour usage. Kind of the sorted
3589 # version of the values of the hash returned by getcolorusagehash.
3590 # You might want to add safety checks and change the names, etc...
3594 my %opts = ( maxcolors => 2**30, @_ );
3595 my $max_colors = $opts{maxcolors};
3596 unless (defined $max_colors && $max_colors > 0) {
3597 $self->_set_error('maxcolors must be a positive integer');
3601 unless (defined $self->{IMG}) {
3602 $self->_set_error('empty input image');
3606 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3609 # draw string to an image
3613 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3615 my %input=('x'=>0, 'y'=>0, @_);
3616 defined($input{string}) or $input{string} = $input{text};
3618 unless(defined $input{string}) {
3619 $self->{ERRSTR}="missing required parameter 'string'";
3623 unless($input{font}) {
3624 $self->{ERRSTR}="missing required parameter 'font'";
3628 unless ($input{font}->draw(image=>$self, %input)) {
3640 unless ($self->{IMG}) {
3641 $self->{ERRSTR}='empty input image';
3650 my %input=('x'=>0, 'y'=>0, @_);
3651 defined $input{string}
3652 or $input{string} = $input{text};
3654 unless(exists $input{string}) {
3655 $self->_set_error("missing required parameter 'string'");
3659 unless($input{font}) {
3660 $self->_set_error("missing required parameter 'font'");
3665 unless (@result = $input{font}->align(image=>$img, %input)) {
3669 return wantarray ? @result : $result[0];
3672 my @file_limit_names = qw/width height bytes/;
3674 sub set_file_limits {
3681 @values{@file_limit_names} = (0) x @file_limit_names;
3684 @values{@file_limit_names} = i_get_image_file_limits();
3687 for my $key (keys %values) {
3688 defined $opts{$key} and $values{$key} = $opts{$key};
3691 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3694 sub get_file_limits {
3695 i_get_image_file_limits();
3698 # Shortcuts that can be exported
3700 sub newcolor { Imager::Color->new(@_); }
3701 sub newfont { Imager::Font->new(@_); }
3702 sub NCF { Imager::Color::Float->new(@_) }
3704 *NC=*newcolour=*newcolor;
3711 #### Utility routines
3714 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3718 my ($self, $msg) = @_;
3721 $self->{ERRSTR} = $msg;
3729 # Default guess for the type of an image from extension
3731 sub def_guess_type {
3734 $ext=($name =~ m/\.([^\.]+)$/)[0];
3735 return 'tiff' if ($ext =~ m/^tiff?$/);
3736 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3737 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3738 return 'png' if ($ext eq "png");
3739 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3740 return 'tga' if ($ext eq "tga");
3741 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3742 return 'gif' if ($ext eq "gif");
3743 return 'raw' if ($ext eq "raw");
3744 return lc $ext; # best guess
3749 return @combine_types;
3752 # get the minimum of a list
3756 for(@_) { if ($_<$mx) { $mx=$_; }}
3760 # get the maximum of a list
3764 for(@_) { if ($_>$mx) { $mx=$_; }}
3768 # string stuff for iptc headers
3772 $str = substr($str,3);
3773 $str =~ s/[\n\r]//g;
3780 # A little hack to parse iptc headers.
3785 my($caption,$photogr,$headln,$credit);
3787 my $str=$self->{IPTCRAW};
3792 @ar=split(/8BIM/,$str);
3797 @sar=split(/\034\002/);
3798 foreach $item (@sar) {
3799 if ($item =~ m/^x/) {
3800 $caption = _clean($item);
3803 if ($item =~ m/^P/) {
3804 $photogr = _clean($item);
3807 if ($item =~ m/^i/) {
3808 $headln = _clean($item);
3811 if ($item =~ m/^n/) {
3812 $credit = _clean($item);
3818 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3825 or die "Only C language supported";
3827 require Imager::ExtUtils;
3828 return Imager::ExtUtils->inline_config;
3831 # threads shouldn't try to close raw Imager objects
3832 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3834 # backward compatibility for %formats
3835 package Imager::FORMATS;
3837 use constant IX_FORMATS => 0;
3838 use constant IX_LIST => 1;
3839 use constant IX_INDEX => 2;
3840 use constant IX_CLASSES => 3;
3843 my ($class, $formats, $classes) = @_;
3845 return bless [ $formats, [ ], 0, $classes ], $class;
3849 my ($self, $key) = @_;
3851 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
3853 if (eval { require $file; 1 }) {
3859 $self->[IX_FORMATS]{$key} = $value;
3865 my ($self, $key) = @_;
3867 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
3869 $self->[IX_CLASSES]{$key} or return undef;
3871 return $self->_check($key);
3875 die "%Imager::formats is not user monifiable";
3879 die "%Imager::formats is not user monifiable";
3883 die "%Imager::formats is not user monifiable";
3887 my ($self, $key) = @_;
3889 if (exists $self->[IX_FORMATS]{$key}) {
3890 my $value = $self->[IX_FORMATS]{$key}
3895 $self->_check($key) or return 1==0;
3903 unless (@{$self->[IX_LIST]}) {
3905 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
3906 keys %{$self->[IX_FORMATS]};
3908 for my $key (keys %{$self->[IX_CLASSES]}) {
3909 $self->[IX_FORMATS]{$key} and next;
3911 and push @{$self->[IX_LIST]}, $key;
3915 @{$self->[IX_LIST]} or return;
3916 $self->[IX_INDEX] = 1;
3917 return $self->[IX_LIST][0];
3923 $self->[IX_INDEX] < @{$self->[IX_LIST]}
3926 return $self->[IX_LIST][$self->[IX_INDEX]++];
3932 return scalar @{$self->[IX_LIST]};
3937 # Below is the stub of documentation for your module. You better edit it!
3941 Imager - Perl extension for Generating 24 bit Images
3951 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3956 # see Imager::Files for information on the read() method
3957 my $im = Imager->new(file=>$file)
3958 or die Imager->errstr();
3960 $file =~ s/\.[^.]*$//;
3962 # Create smaller version
3963 # documented in Imager::Transformations
3964 my $thumb = $img->scale(scalefactor=>.3);
3966 # Autostretch individual channels
3967 $thumb->filter(type=>'autolevels');
3969 # try to save in one of these formats
3972 for $format ( qw( png gif jpeg tiff ppm ) ) {
3973 # Check if given format is supported
3974 if ($Imager::formats{$format}) {
3975 $file.="_low.$format";
3976 print "Storing image as: $file\n";
3977 # documented in Imager::Files
3978 $thumb->write(file=>$file) or
3986 Imager is a module for creating and altering images. It can read and
3987 write various image formats, draw primitive shapes like lines,and
3988 polygons, blend multiple images together in various ways, scale, crop,
3989 render text and more.
3991 =head2 Overview of documentation
3997 Imager - This document - Synopsis, Example, Table of Contents and
4002 L<Imager::Tutorial> - a brief introduction to Imager.
4006 L<Imager::Cookbook> - how to do various things with Imager.
4010 L<Imager::ImageTypes> - Basics of constructing image objects with
4011 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4012 8/16/double bits/channel, color maps, channel masks, image tags, color
4013 quantization. Also discusses basic image information methods.
4017 L<Imager::Files> - IO interaction, reading/writing images, format
4022 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4027 L<Imager::Color> - Color specification.
4031 L<Imager::Fill> - Fill pattern specification.
4035 L<Imager::Font> - General font rendering, bounding boxes and font
4040 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4041 blending, pasting, convert and map.
4045 L<Imager::Engines> - Programmable transformations through
4046 C<transform()>, C<transform2()> and C<matrix_transform()>.
4050 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4055 L<Imager::Expr> - Expressions for evaluation engine used by
4060 L<Imager::Matrix2d> - Helper class for affine transformations.
4064 L<Imager::Fountain> - Helper for making gradient profiles.
4068 L<Imager::API> - using Imager's C API
4072 L<Imager::APIRef> - API function reference
4076 L<Imager::Inline> - using Imager's C API from Inline::C
4080 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4084 =head2 Basic Overview
4086 An Image object is created with C<$img = Imager-E<gt>new()>.
4089 $img=Imager->new(); # create empty image
4090 $img->read(file=>'lena.png',type=>'png') or # read image from file
4091 die $img->errstr(); # give an explanation
4092 # if something failed
4094 or if you want to create an empty image:
4096 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4098 This example creates a completely black image of width 400 and height
4101 =head1 ERROR HANDLING
4103 In general a method will return false when it fails, if it does use
4104 the C<errstr()> method to find out why:
4110 Returns the last error message in that context.
4112 If the last error you received was from calling an object method, such
4113 as read, call errstr() as an object method to find out why:
4115 my $image = Imager->new;
4116 $image->read(file => 'somefile.gif')
4117 or die $image->errstr;
4119 If it was a class method then call errstr() as a class method:
4121 my @imgs = Imager->read_multi(file => 'somefile.gif')
4122 or die Imager->errstr;
4124 Note that in some cases object methods are implemented in terms of
4125 class methods so a failing object method may set both.
4129 The C<Imager-E<gt>new> method is described in detail in
4130 L<Imager::ImageTypes>.
4134 Where to find information on methods for Imager class objects.
4136 addcolors() - L<Imager::ImageTypes/addcolors> - add colors to a
4139 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4141 align_string() - L<Imager::Draw/align_string> - draw text aligned on a
4144 arc() - L<Imager::Draw/arc> - draw a filled arc
4146 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4149 box() - L<Imager::Draw/box> - draw a filled or outline box.
4151 circle() - L<Imager::Draw/circle> - draw a filled circle
4153 colorcount() - L<Imager::Draw/colorcount> - the number of colors in an
4154 image's palette (paletted images only)
4156 combines() - L<Imager::Draw/combines> - return a list of the different
4157 combine type keywords
4159 compose() - L<Imager::Transformations/compose> - compose one image
4162 convert() - L<Imager::Transformations/"Color transformations"> -
4163 transform the color space
4165 copy() - L<Imager::Transformations/copy> - make a duplicate of an
4168 crop() - L<Imager::Transformations/crop> - extract part of an image
4170 def_guess_type() - L<Imager::Files/def_guess_type> - default function
4171 used to guess the output file format based on the output file name
4173 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4175 difference() - L<Imager::Filters/"Image Difference"> - produce a
4176 difference images from two input images.
4178 errstr() - L<"Basic Overview"> - the error from the last failed
4181 filter() - L<Imager::Filters> - image filtering
4183 findcolor() - L<Imager::ImageTypes/findcolor> - search the image
4184 palette, if it has one
4186 flip() - L<Imager::Transformations/flip> - flip an image, vertically,
4189 flood_fill() - L<Imager::Draw/flood_fill> - fill an enclosed or same
4192 getchannels() - L<Imager::ImageTypes/getchannels> - the number of
4193 samples per pixel for an image
4195 getcolorcount() - L<Imager::ImageTypes/getcolorcount> - the number of
4196 different colors used by an image (works for direct color images)
4198 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4199 palette, if it has one
4201 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4203 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4205 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4207 getheight() - L<Imager::ImageTypes/getwidth> - height of the image in
4210 getmask() - L<Imager::ImageTypes/getmask> - write mask for the image
4212 getpixel() - L<Imager::Draw/getpixel> - retrieve one or more pixel
4215 getsamples() - L<Imager::Draw/getsamples> - retrieve samples from a
4216 row or partial row of pixels.
4218 getscanline() - L<Imager::Draw/getscanline> - retrieve colors for a
4219 row or partial row of pixels.
4221 getwidth() - L<Imager::ImageTypes/getwidth> - width of the image in
4224 img_set() - L<Imager::ImageTypes/img_set> - re-use an Imager object
4227 init() - L<Imager::ImageTypes/init>
4229 is_bilevel() - L<Imager::ImageTypes/is_bilevel> - returns whether
4230 image write functions should write the image in their bilevel (blank
4231 and white, no gray levels) format
4233 line() - L<Imager::Draw/line> - draw an interval
4235 load_plugin() - L<Imager::Filters/load_plugin>
4237 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4240 masked() - L<Imager::ImageTypes/masked> - make a masked image
4242 matrix_transform() - L<Imager::Engines/matrix_transform>
4244 maxcolors() - L<Imager::ImageTypes/maxcolors>
4246 NC() - L<Imager::Handy/NC>
4248 NCF() - L<Imager::Handy/NCF>
4250 new() - L<Imager::ImageTypes/new>
4252 newcolor() - L<Imager::Handy/newcolor>
4254 newcolour() - L<Imager::Handy/newcolour>
4256 newfont() - L<Imager::Handy/newfont>
4258 NF() - L<Imager::Handy/NF>
4260 open() - L<Imager::Files> - an alias for read()
4264 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4267 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4269 polygon() - L<Imager::Draw/polygon>
4271 polyline() - L<Imager::Draw/polyline>
4273 read() - L<Imager::Files> - read a single image from an image file
4275 read_multi() - L<Imager::Files> - read multiple images from an image
4278 read_types() - L<Imager::Files/read_types> - list image types Imager
4281 register_filter() - L<Imager::Filters/register_filter>
4283 register_reader() - L<Imager::Files/register_reader>
4285 register_writer() - L<Imager::Files/register_writer>
4287 rotate() - L<Imager::Transformations/rotate>
4289 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4290 image and use the alpha channel
4292 scale() - L<Imager::Transformations/scale>
4294 scale_calculate() - L<Imager::Transformations/scale_calculate>
4296 scaleX() - L<Imager::Transformations/scaleX>
4298 scaleY() - L<Imager::Transformations/scaleY>
4300 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4303 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4305 setmask() - L<Imager::ImageTypes/setmask>
4307 setpixel() - L<Imager::Draw/setpixel>
4309 setsamples() - L<Imager::Draw/setsamples>
4311 setscanline() - L<Imager::Draw/setscanline>
4313 settag() - L<Imager::ImageTypes/settag>
4315 string() - L<Imager::Draw/string> - draw text on an image
4317 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4319 to_paletted() - L<Imager::ImageTypes/to_paletted>
4321 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4323 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4325 transform() - L<Imager::Engines/"transform">
4327 transform2() - L<Imager::Engines/"transform2">
4329 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4331 unload_plugin() - L<Imager::Filters/unload_plugin>
4333 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4336 write() - L<Imager::Files> - write an image to a file
4338 write_multi() - L<Imager::Files> - write multiple image to an image
4341 write_types() - L<Imager::Files/read_types> - list image types Imager
4344 =head1 CONCEPT INDEX
4346 animated GIF - L<Imager::Files/"Writing an animated GIF">
4348 aspect ratio - L<Imager::ImageTypes/i_xres>,
4349 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4351 blend - alpha blending one image onto another
4352 L<Imager::Transformations/rubthrough>
4354 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4356 boxes, drawing - L<Imager::Draw/box>
4358 changes between image - L<Imager::Filters/"Image Difference">
4360 color - L<Imager::Color>
4362 color names - L<Imager::Color>, L<Imager::Color::Table>
4364 combine modes - L<Imager::Draw/"Combine Types">
4366 compare images - L<Imager::Filters/"Image Difference">
4368 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4370 convolution - L<Imager::Filters/conv>
4372 cropping - L<Imager::Transformations/crop>
4374 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4376 C<diff> images - L<Imager::Filters/"Image Difference">
4378 dpi - L<Imager::ImageTypes/i_xres>,
4379 L<Imager::Cookbook/"Image spatial resolution">
4381 drawing boxes - L<Imager::Draw/box>
4383 drawing lines - L<Imager::Draw/line>
4385 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4387 error message - L<"ERROR HANDLING">
4389 files, font - L<Imager::Font>
4391 files, image - L<Imager::Files>
4393 filling, types of fill - L<Imager::Fill>
4395 filling, boxes - L<Imager::Draw/box>
4397 filling, flood fill - L<Imager::Draw/flood_fill>
4399 flood fill - L<Imager::Draw/flood_fill>
4401 fonts - L<Imager::Font>
4403 fonts, drawing with - L<Imager::Draw/string>,
4404 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4406 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4408 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4410 fountain fill - L<Imager::Fill/"Fountain fills">,
4411 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4412 L<Imager::Filters/gradgen>
4414 GIF files - L<Imager::Files/"GIF">
4416 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4418 gradient fill - L<Imager::Fill/"Fountain fills">,
4419 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4420 L<Imager::Filters/gradgen>
4422 gray scale, convert image to - L<Imager::Transformations/convert>
4424 guassian blur - L<Imager::Filters/guassian>
4426 hatch fills - L<Imager::Fill/"Hatched fills">
4428 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4430 invert image - L<Imager::Filters/hardinvert>,
4431 L<Imager::Filters/hardinvertall>
4433 JPEG - L<Imager::Files/"JPEG">
4435 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4437 lines, drawing - L<Imager::Draw/line>
4439 matrix - L<Imager::Matrix2d>,
4440 L<Imager::Transformations/"Matrix Transformations">,
4441 L<Imager::Font/transform>
4443 metadata, image - L<Imager::ImageTypes/"Tags">
4445 mosaic - L<Imager::Filters/mosaic>
4447 noise, filter - L<Imager::Filters/noise>
4449 noise, rendered - L<Imager::Filters/turbnoise>,
4450 L<Imager::Filters/radnoise>
4452 paste - L<Imager::Transformations/paste>,
4453 L<Imager::Transformations/rubthrough>
4455 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4456 L<Imager::ImageTypes/new>
4458 =for stopwords posterize
4460 posterize - L<Imager::Filters/postlevels>
4462 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4464 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4466 rectangles, drawing - L<Imager::Draw/box>
4468 resizing an image - L<Imager::Transformations/scale>,
4469 L<Imager::Transformations/crop>
4471 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4473 saving an image - L<Imager::Files>
4475 scaling - L<Imager::Transformations/scale>
4477 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4479 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4481 size, image - L<Imager::ImageTypes/getwidth>,
4482 L<Imager::ImageTypes/getheight>
4484 size, text - L<Imager::Font/bounding_box>
4486 tags, image metadata - L<Imager::ImageTypes/"Tags">
4488 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4489 L<Imager::Font::Wrap>
4491 text, wrapping text in an area - L<Imager::Font::Wrap>
4493 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4495 tiles, color - L<Imager::Filters/mosaic>
4497 =for stopwords unsharp
4499 unsharp mask - L<Imager::Filters/unsharpmask>
4501 watermark - L<Imager::Filters/watermark>
4503 writing an image to a file - L<Imager::Files>
4507 Imager doesn't support perl threads.
4509 Imager has limited code to prevent double frees if you create images,
4510 colors etc, and then create a thread, but has no code to prevent two
4511 threads entering Imager's error handling code, and none is likely to
4516 The best place to get help with Imager is the mailing list.
4518 To subscribe send a message with C<subscribe> in the body to:
4520 imager-devel+request@molar.is
4526 L<http://www.molar.is/en/lists/imager-devel/>
4530 where you can also find the mailing list archive.
4532 You can report bugs by pointing your browser at:
4536 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4540 or by sending an email to:
4544 bug-Imager@rt.cpan.org
4548 Please remember to include the versions of Imager, perl, supporting
4549 libraries, and any relevant code. If you have specific images that
4550 cause the problems, please include those too.
4552 If you don't want to publish your email address on a mailing list you
4553 can use CPAN::Forum:
4555 http://www.cpanforum.com/dist/Imager
4557 You will need to register to post.
4559 =head1 CONTRIBUTING TO IMAGER
4565 If you like or dislike Imager, you can add a public review of Imager
4568 http://cpanratings.perl.org/dist/Imager
4570 =for stopwords Bitcard
4572 This requires a Bitcard account (http://www.bitcard.org).
4574 You can also send email to the maintainer below.
4576 If you send me a bug report via email, it will be copied to Request
4581 I accept patches, preferably against the main branch in subversion.
4582 You should include an explanation of the reason for why the patch is
4585 Your patch should include regression tests where possible, otherwise
4586 it will be delayed until I get a chance to write them.
4590 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4592 Arnar M. Hrafnkelsson is the original author of Imager.
4594 Many others have contributed to Imager, please see the C<README> for a
4599 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4600 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4601 L<Imager::Font>(3), L<Imager::Transformations>(3),
4602 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4603 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4605 L<http://imager.perl.org/>
4607 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4609 Other perl imaging modules include:
4611 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).