4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR $fontstate %OPCODES $I2P $FORMATGUESS $warn_obsolete);
82 i_writetiff_wiol_faxable
148 # registered file readers
151 # registered file writers
154 # modules we attempted to autoload
155 my %attempted_to_load;
157 # library keys that are image file formats
158 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
160 # image pixel combine types
162 qw/none normal multiply dissolve add subtract diff lighten darken
163 hue saturation value color/;
165 @combine_types{@combine_types} = 0 .. $#combine_types;
166 $combine_types{mult} = $combine_types{multiply};
167 $combine_types{'sub'} = $combine_types{subtract};
168 $combine_types{sat} = $combine_types{saturation};
170 # this will be used to store global defaults at some point
179 XSLoader::load(Imager => $VERSION);
183 push @ISA, 'DynaLoader';
184 bootstrap Imager $VERSION;
189 Imager::Font::__init();
190 for(i_list_formats()) { $formats{$_}++; }
192 if (!$formats{'t1'} and !$formats{'tt'}
193 && !$formats{'ft2'} && !$formats{'w32'}) {
194 $fontstate='no font support';
197 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
201 # the members of the subhashes under %filters are:
202 # callseq - a list of the parameters to the underlying filter in the
203 # order they are passed
204 # callsub - a code ref that takes a named parameter list and calls the
206 # defaults - a hash of default values
207 # names - defines names for value of given parameters so if the names
208 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
209 # foo parameter, the filter will receive 1 for the foo
212 callseq => ['image','intensity'],
213 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
217 callseq => ['image', 'amount', 'subtype'],
218 defaults => { amount=>3,subtype=>0 },
219 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
222 $filters{hardinvert} ={
223 callseq => ['image'],
225 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
228 $filters{autolevels} ={
229 callseq => ['image','lsat','usat','skew'],
230 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
231 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
234 $filters{turbnoise} ={
235 callseq => ['image'],
236 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
237 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
240 $filters{radnoise} ={
241 callseq => ['image'],
242 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
243 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
248 callseq => ['image', 'coef'],
253 i_conv($hsh{image},$hsh{coef})
254 or die Imager->_error_as_msg() . "\n";
260 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
261 defaults => { dist => 0 },
265 my @colors = @{$hsh{colors}};
268 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
272 $filters{nearest_color} =
274 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
279 # make sure the segments are specified with colors
281 for my $color (@{$hsh{colors}}) {
282 my $new_color = _color($color)
283 or die $Imager::ERRSTR."\n";
284 push @colors, $new_color;
287 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
289 or die Imager->_error_as_msg() . "\n";
292 $filters{gaussian} = {
293 callseq => [ 'image', 'stddev' ],
295 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
299 callseq => [ qw(image size) ],
300 defaults => { size => 20 },
301 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
305 callseq => [ qw(image bump elevation lightx lighty st) ],
306 defaults => { elevation=>0, st=> 2 },
309 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
310 $hsh{lightx}, $hsh{lighty}, $hsh{st});
313 $filters{bumpmap_complex} =
315 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
326 Ia => Imager::Color->new(rgb=>[0,0,0]),
327 Il => Imager::Color->new(rgb=>[255,255,255]),
328 Is => Imager::Color->new(rgb=>[255,255,255]),
332 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
333 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
334 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
338 $filters{postlevels} =
340 callseq => [ qw(image levels) ],
341 defaults => { levels => 10 },
342 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
344 $filters{watermark} =
346 callseq => [ qw(image wmark tx ty pixdiff) ],
347 defaults => { pixdiff=>10, tx=>0, ty=>0 },
351 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
357 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
359 ftype => { linear => 0,
365 repeat => { none => 0,
380 multiply => 2, mult => 2,
383 subtract => 5, 'sub' => 5,
393 defaults => { ftype => 0, repeat => 0, combine => 0,
394 super_sample => 0, ssample_param => 4,
397 Imager::Color->new(0,0,0),
398 Imager::Color->new(255, 255, 255),
407 # make sure the segments are specified with colors
409 for my $segment (@{$hsh{segments}}) {
410 my @new_segment = @$segment;
412 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
413 push @segments, \@new_segment;
416 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
417 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
418 $hsh{ssample_param}, \@segments)
419 or die Imager->_error_as_msg() . "\n";
422 $filters{unsharpmask} =
424 callseq => [ qw(image stddev scale) ],
425 defaults => { stddev=>2.0, scale=>1.0 },
429 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
433 $FORMATGUESS=\&def_guess_type;
443 # NOTE: this might be moved to an import override later on
448 if ($_[$i] eq '-log-stderr') {
456 goto &Exporter::import;
460 i_init_log($_[0],$_[1]);
461 i_log_entry("Imager $VERSION starting\n", 1);
466 my %parms=(loglevel=>1,@_);
468 init_log($parms{'log'},$parms{'loglevel'});
471 if (exists $parms{'warn_obsolete'}) {
472 $warn_obsolete = $parms{'warn_obsolete'};
475 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
476 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
480 if (exists $parms{'t1log'}) {
481 i_init_fonts($parms{'t1log'});
487 print "shutdown code\n";
488 # for(keys %instances) { $instances{$_}->DESTROY(); }
489 malloc_state(); # how do decide if this should be used? -- store something from the import
490 print "Imager exiting\n";
494 # Load a filter plugin
499 my ($DSO_handle,$str)=DSO_open($filename);
500 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
501 my %funcs=DSO_funclist($DSO_handle);
502 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
504 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
506 $DSOs{$filename}=[$DSO_handle,\%funcs];
509 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
510 $DEBUG && print "eval string:\n",$evstr,"\n";
522 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
523 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
524 for(keys %{$funcref}) {
526 $DEBUG && print "unloading: $_\n";
528 my $rc=DSO_close($DSO_handle);
529 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
533 # take the results of i_error() and make a message out of it
535 return join(": ", map $_->[0], i_errors());
538 # this function tries to DWIM for color parameters
539 # color objects are used as is
540 # simple scalars are simply treated as single parameters to Imager::Color->new
541 # hashrefs are treated as named argument lists to Imager::Color->new
542 # arrayrefs are treated as list arguments to Imager::Color->new iff any
544 # other arrayrefs are treated as list arguments to Imager::Color::Float
548 # perl 5.6.0 seems to do weird things to $arg if we don't make an
549 # explicitly stringified copy
550 # I vaguely remember a bug on this on p5p, but couldn't find it
551 # through bugs.perl.org (I had trouble getting it to find any bugs)
552 my $copy = $arg . "";
556 if (UNIVERSAL::isa($arg, "Imager::Color")
557 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
561 if ($copy =~ /^HASH\(/) {
562 $result = Imager::Color->new(%$arg);
564 elsif ($copy =~ /^ARRAY\(/) {
565 $result = Imager::Color->new(@$arg);
568 $Imager::ERRSTR = "Not a color";
573 # assume Imager::Color::new knows how to handle it
574 $result = Imager::Color->new($arg);
581 my ($self, $combine, $default) = @_;
583 if (!defined $combine && ref $self) {
584 $combine = $self->{combine};
586 defined $combine or $combine = $defaults{combine};
587 defined $combine or $combine = $default;
589 if (exists $combine_types{$combine}) {
590 $combine = $combine_types{$combine};
599 $self->{IMG} and return 1;
601 $self->_set_error('empty input image');
606 # returns first defined parameter
609 return $_ if defined $_;
615 # Methods to be called on objects.
618 # Create a new Imager object takes very few parameters.
619 # usually you call this method and then call open from
620 # the resulting object
627 $self->{IMG}=undef; # Just to indicate what exists
628 $self->{ERRSTR}=undef; #
629 $self->{DEBUG}=$DEBUG;
630 $self->{DEBUG} and print "Initialized Imager\n";
631 if (defined $hsh{xsize} || defined $hsh{ysize}) {
632 unless ($self->img_set(%hsh)) {
633 $Imager::ERRSTR = $self->{ERRSTR};
637 elsif (defined $hsh{file} ||
640 defined $hsh{callback} ||
641 defined $hsh{readcb}) {
642 # allow $img = Imager->new(file => $filename)
645 # type is already used as a parameter to new(), rename it for the
647 if ($hsh{filetype}) {
648 $extras{type} = $hsh{filetype};
650 unless ($self->read(%hsh, %extras)) {
651 $Imager::ERRSTR = $self->{ERRSTR};
659 # Copy an entire image with no changes
660 # - if an image has magic the copy of it will not be magical
664 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
666 unless (defined wantarray) {
668 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
672 my $newcopy=Imager->new();
673 $newcopy->{IMG} = i_copy($self->{IMG});
682 unless ($self->{IMG}) {
683 $self->_set_error('empty input image');
686 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
687 my $src = $input{img} || $input{src};
689 $self->_set_error("no source image");
692 $input{left}=0 if $input{left} <= 0;
693 $input{top}=0 if $input{top} <= 0;
695 my($r,$b)=i_img_info($src->{IMG});
696 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
697 my ($src_right, $src_bottom);
698 if ($input{src_coords}) {
699 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
702 if (defined $input{src_maxx}) {
703 $src_right = $input{src_maxx};
705 elsif (defined $input{width}) {
706 if ($input{width} <= 0) {
707 $self->_set_error("paste: width must me positive");
710 $src_right = $src_left + $input{width};
715 if (defined $input{src_maxy}) {
716 $src_bottom = $input{src_maxy};
718 elsif (defined $input{height}) {
719 if ($input{height} < 0) {
720 $self->_set_error("paste: height must be positive");
723 $src_bottom = $src_top + $input{height};
730 $src_right > $r and $src_right = $r;
731 $src_bottom > $b and $src_bottom = $b;
733 if ($src_right <= $src_left
734 || $src_bottom < $src_top) {
735 $self->_set_error("nothing to paste");
739 i_copyto($self->{IMG}, $src->{IMG},
740 $src_left, $src_top, $src_right, $src_bottom,
741 $input{left}, $input{top});
743 return $self; # What should go here??
746 # Crop an image - i.e. return a new image that is smaller
750 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
752 unless (defined wantarray) {
754 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
760 my ($w, $h, $l, $r, $b, $t) =
761 @hsh{qw(width height left right bottom top)};
763 # work through the various possibilities
768 elsif (!defined $r) {
769 $r = $self->getwidth;
781 $l = int(0.5+($self->getwidth()-$w)/2);
786 $r = $self->getwidth;
792 elsif (!defined $b) {
793 $b = $self->getheight;
805 $t=int(0.5+($self->getheight()-$h)/2);
810 $b = $self->getheight;
813 ($l,$r)=($r,$l) if $l>$r;
814 ($t,$b)=($b,$t) if $t>$b;
817 $r > $self->getwidth and $r = $self->getwidth;
819 $b > $self->getheight and $b = $self->getheight;
821 if ($l == $r || $t == $b) {
822 $self->_set_error("resulting image would have no content");
825 if( $r < $l or $b < $t ) {
826 $self->_set_error("attempting to crop outside of the image");
829 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
831 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
836 my ($self, %opts) = @_;
838 $self->{IMG} or return $self->_set_error("Not a valid image");
840 my $x = $opts{xsize} || $self->getwidth;
841 my $y = $opts{ysize} || $self->getheight;
842 my $channels = $opts{channels} || $self->getchannels;
844 my $out = Imager->new;
845 if ($channels == $self->getchannels) {
846 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
849 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
851 unless ($out->{IMG}) {
852 $self->{ERRSTR} = $self->_error_as_msg;
859 # Sets an image to a certain size and channel number
860 # if there was previously data in the image it is discarded
865 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
867 if (defined($self->{IMG})) {
868 # let IIM_DESTROY destroy it, it's possible this image is
869 # referenced from a virtual image (like masked)
870 #i_img_destroy($self->{IMG});
874 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
875 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
876 $hsh{maxcolors} || 256);
878 elsif ($hsh{bits} eq 'double') {
879 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
881 elsif ($hsh{bits} == 16) {
882 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
885 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
889 unless ($self->{IMG}) {
890 $self->{ERRSTR} = Imager->_error_as_msg();
897 # created a masked version of the current image
901 $self or return undef;
902 my %opts = (left => 0,
904 right => $self->getwidth,
905 bottom => $self->getheight,
907 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
909 my $result = Imager->new;
910 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
911 $opts{top}, $opts{right} - $opts{left},
912 $opts{bottom} - $opts{top});
913 # keep references to the mask and base images so they don't
915 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
920 # convert an RGB image into a paletted image
924 if (@_ != 1 && !ref $_[0]) {
931 unless (defined wantarray) {
933 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
937 my $result = Imager->new;
938 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
940 #print "Type ", i_img_type($result->{IMG}), "\n";
942 if ($result->{IMG}) {
946 $self->{ERRSTR} = $self->_error_as_msg;
951 # convert a paletted (or any image) to an 8-bit/channel RGB images
956 unless (defined wantarray) {
958 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
963 $result = Imager->new;
964 $result->{IMG} = i_img_to_rgb($self->{IMG})
971 # convert a paletted (or any image) to an 8-bit/channel RGB images
976 unless (defined wantarray) {
978 warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
983 $result = Imager->new;
984 $result->{IMG} = i_img_to_rgb16($self->{IMG})
993 my %opts = (colors=>[], @_);
995 unless ($self->{IMG}) {
996 $self->_set_error("empty input image");
1000 my @colors = @{$opts{colors}}
1003 for my $color (@colors) {
1004 $color = _color($color);
1006 $self->_set_error($Imager::ERRSTR);
1011 return i_addcolors($self->{IMG}, @colors);
1016 my %opts = (start=>0, colors=>[], @_);
1018 unless ($self->{IMG}) {
1019 $self->_set_error("empty input image");
1023 my @colors = @{$opts{colors}}
1026 for my $color (@colors) {
1027 $color = _color($color);
1029 $self->_set_error($Imager::ERRSTR);
1034 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1040 if (!exists $opts{start} && !exists $opts{count}) {
1043 $opts{count} = $self->colorcount;
1045 elsif (!exists $opts{count}) {
1048 elsif (!exists $opts{start}) {
1053 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1057 i_colorcount($_[0]{IMG});
1061 i_maxcolors($_[0]{IMG});
1067 $opts{color} or return undef;
1069 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1074 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1075 if ($bits && $bits == length(pack("d", 1)) * 8) {
1084 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1090 $self->{IMG} and i_img_virtual($self->{IMG});
1096 $self->{IMG} or return;
1098 return i_img_is_monochrome($self->{IMG});
1102 my ($self, %opts) = @_;
1104 $self->{IMG} or return;
1106 if (defined $opts{name}) {
1110 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1111 push @result, (i_tags_get($self->{IMG}, $found))[1];
1114 return wantarray ? @result : $result[0];
1116 elsif (defined $opts{code}) {
1120 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1121 push @result, (i_tags_get($self->{IMG}, $found))[1];
1128 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1131 return i_tags_count($self->{IMG});
1140 return -1 unless $self->{IMG};
1142 if (defined $opts{value}) {
1143 if ($opts{value} =~ /^\d+$/) {
1145 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1148 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1151 elsif (defined $opts{data}) {
1152 # force addition as a string
1153 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1156 $self->{ERRSTR} = "No value supplied";
1160 elsif ($opts{code}) {
1161 if (defined $opts{value}) {
1162 if ($opts{value} =~ /^\d+$/) {
1164 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1167 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1170 elsif (defined $opts{data}) {
1171 # force addition as a string
1172 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1175 $self->{ERRSTR} = "No value supplied";
1188 return 0 unless $self->{IMG};
1190 if (defined $opts{'index'}) {
1191 return i_tags_delete($self->{IMG}, $opts{'index'});
1193 elsif (defined $opts{name}) {
1194 return i_tags_delbyname($self->{IMG}, $opts{name});
1196 elsif (defined $opts{code}) {
1197 return i_tags_delbycode($self->{IMG}, $opts{code});
1200 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1206 my ($self, %opts) = @_;
1209 $self->deltag(name=>$opts{name});
1210 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1212 elsif (defined $opts{code}) {
1213 $self->deltag(code=>$opts{code});
1214 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1222 sub _get_reader_io {
1223 my ($self, $input) = @_;
1226 return $input->{io}, undef;
1228 elsif ($input->{fd}) {
1229 return io_new_fd($input->{fd});
1231 elsif ($input->{fh}) {
1232 my $fd = fileno($input->{fh});
1233 unless (defined $fd) {
1234 $self->_set_error("Handle in fh option not opened");
1237 return io_new_fd($fd);
1239 elsif ($input->{file}) {
1240 my $file = IO::File->new($input->{file}, "r");
1242 $self->_set_error("Could not open $input->{file}: $!");
1246 return (io_new_fd(fileno($file)), $file);
1248 elsif ($input->{data}) {
1249 return io_new_buffer($input->{data});
1251 elsif ($input->{callback} || $input->{readcb}) {
1252 if (!$input->{seekcb}) {
1253 $self->_set_error("Need a seekcb parameter");
1255 if ($input->{maxbuffer}) {
1256 return io_new_cb($input->{writecb},
1257 $input->{callback} || $input->{readcb},
1258 $input->{seekcb}, $input->{closecb},
1259 $input->{maxbuffer});
1262 return io_new_cb($input->{writecb},
1263 $input->{callback} || $input->{readcb},
1264 $input->{seekcb}, $input->{closecb});
1268 $self->_set_error("file/fd/fh/data/callback parameter missing");
1273 sub _get_writer_io {
1274 my ($self, $input, $type) = @_;
1277 return $input->{io};
1279 elsif ($input->{fd}) {
1280 return io_new_fd($input->{fd});
1282 elsif ($input->{fh}) {
1283 my $fd = fileno($input->{fh});
1284 unless (defined $fd) {
1285 $self->_set_error("Handle in fh option not opened");
1289 my $oldfh = select($input->{fh});
1290 # flush anything that's buffered, and make sure anything else is flushed
1293 return io_new_fd($fd);
1295 elsif ($input->{file}) {
1296 my $fh = new IO::File($input->{file},"w+");
1298 $self->_set_error("Could not open file $input->{file}: $!");
1301 binmode($fh) or die;
1302 return (io_new_fd(fileno($fh)), $fh);
1304 elsif ($input->{data}) {
1305 return io_new_bufchain();
1307 elsif ($input->{callback} || $input->{writecb}) {
1308 if ($input->{maxbuffer}) {
1309 return io_new_cb($input->{callback} || $input->{writecb},
1311 $input->{seekcb}, $input->{closecb},
1312 $input->{maxbuffer});
1315 return io_new_cb($input->{callback} || $input->{writecb},
1317 $input->{seekcb}, $input->{closecb});
1321 $self->_set_error("file/fd/fh/data/callback parameter missing");
1326 # Read an image from file
1332 if (defined($self->{IMG})) {
1333 # let IIM_DESTROY do the destruction, since the image may be
1334 # referenced from elsewhere
1335 #i_img_destroy($self->{IMG});
1336 undef($self->{IMG});
1339 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1341 unless ($input{'type'}) {
1342 $input{'type'} = i_test_format_probe($IO, -1);
1345 unless ($input{'type'}) {
1346 $self->_set_error('type parameter missing and not possible to guess from extension');
1350 _reader_autoload($input{type});
1352 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1353 return $readers{$input{type}}{single}->($self, $IO, %input);
1356 unless ($formats{$input{'type'}}) {
1357 my $read_types = join ', ', sort Imager->read_types();
1358 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1363 if ( $input{'type'} eq 'jpeg' ) {
1364 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1365 if ( !defined($self->{IMG}) ) {
1366 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1368 $self->{DEBUG} && print "loading a jpeg file\n";
1372 my $allow_incomplete = $input{allow_incomplete};
1373 defined $allow_incomplete or $allow_incomplete = 0;
1375 if ( $input{'type'} eq 'tiff' ) {
1376 my $page = $input{'page'};
1377 defined $page or $page = 0;
1378 $self->{IMG}=i_readtiff_wiol( $IO, $allow_incomplete, $page );
1379 if ( !defined($self->{IMG}) ) {
1380 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1382 $self->{DEBUG} && print "loading a tiff file\n";
1386 if ( $input{'type'} eq 'pnm' ) {
1387 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1388 if ( !defined($self->{IMG}) ) {
1389 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1392 $self->{DEBUG} && print "loading a pnm file\n";
1396 if ( $input{'type'} eq 'png' ) {
1397 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1398 if ( !defined($self->{IMG}) ) {
1399 $self->{ERRSTR} = $self->_error_as_msg();
1402 $self->{DEBUG} && print "loading a png file\n";
1405 if ( $input{'type'} eq 'bmp' ) {
1406 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1407 if ( !defined($self->{IMG}) ) {
1408 $self->{ERRSTR}=$self->_error_as_msg();
1411 $self->{DEBUG} && print "loading a bmp file\n";
1414 if ( $input{'type'} eq 'gif' ) {
1415 if ($input{colors} && !ref($input{colors})) {
1416 # must be a reference to a scalar that accepts the colour map
1417 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1420 if ($input{'gif_consolidate'}) {
1421 if ($input{colors}) {
1423 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1425 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1429 $self->{IMG} =i_readgif_wiol( $IO );
1433 my $page = $input{'page'};
1434 defined $page or $page = 0;
1435 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1436 if ($self->{IMG} && $input{colors}) {
1437 ${ $input{colors} } =
1438 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1442 if ( !defined($self->{IMG}) ) {
1443 $self->{ERRSTR}=$self->_error_as_msg();
1446 $self->{DEBUG} && print "loading a gif file\n";
1449 if ( $input{'type'} eq 'tga' ) {
1450 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1451 if ( !defined($self->{IMG}) ) {
1452 $self->{ERRSTR}=$self->_error_as_msg();
1455 $self->{DEBUG} && print "loading a tga file\n";
1458 if ( $input{'type'} eq 'raw' ) {
1459 unless ( $input{xsize} && $input{ysize} ) {
1460 $self->_set_error('missing xsize or ysize parameter for raw');
1464 my $interleave = _first($input{raw_interleave}, $input{interleave});
1465 unless (defined $interleave) {
1466 my @caller = caller;
1467 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1470 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1471 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1473 $self->{IMG} = i_readraw_wiol( $IO,
1479 if ( !defined($self->{IMG}) ) {
1480 $self->{ERRSTR}=$self->_error_as_msg();
1483 $self->{DEBUG} && print "loading a raw file\n";
1489 sub register_reader {
1490 my ($class, %opts) = @_;
1493 or die "register_reader called with no type parameter\n";
1495 my $type = $opts{type};
1497 defined $opts{single} || defined $opts{multiple}
1498 or die "register_reader called with no single or multiple parameter\n";
1500 $readers{$type} = { };
1501 if ($opts{single}) {
1502 $readers{$type}{single} = $opts{single};
1504 if ($opts{multiple}) {
1505 $readers{$type}{multiple} = $opts{multiple};
1511 sub register_writer {
1512 my ($class, %opts) = @_;
1515 or die "register_writer called with no type parameter\n";
1517 my $type = $opts{type};
1519 defined $opts{single} || defined $opts{multiple}
1520 or die "register_writer called with no single or multiple parameter\n";
1522 $writers{$type} = { };
1523 if ($opts{single}) {
1524 $writers{$type}{single} = $opts{single};
1526 if ($opts{multiple}) {
1527 $writers{$type}{multiple} = $opts{multiple};
1538 grep($file_formats{$_}, keys %formats),
1539 qw(ico sgi), # formats not handled directly, but supplied with Imager
1550 grep($file_formats{$_}, keys %formats),
1551 qw(ico sgi), # formats not handled directly, but supplied with Imager
1557 # probes for an Imager::File::whatever module
1558 sub _reader_autoload {
1561 return if $formats{$type} || $readers{$type};
1563 return unless $type =~ /^\w+$/;
1565 my $file = "Imager/File/\U$type\E.pm";
1567 unless ($attempted_to_load{$file}) {
1569 ++$attempted_to_load{$file};
1573 # try to get a reader specific module
1574 my $file = "Imager/File/\U$type\EReader.pm";
1575 unless ($attempted_to_load{$file}) {
1577 ++$attempted_to_load{$file};
1585 # probes for an Imager::File::whatever module
1586 sub _writer_autoload {
1589 return if $formats{$type} || $readers{$type};
1591 return unless $type =~ /^\w+$/;
1593 my $file = "Imager/File/\U$type\E.pm";
1595 unless ($attempted_to_load{$file}) {
1597 ++$attempted_to_load{$file};
1601 # try to get a writer specific module
1602 my $file = "Imager/File/\U$type\EWriter.pm";
1603 unless ($attempted_to_load{$file}) {
1605 ++$attempted_to_load{$file};
1613 sub _fix_gif_positions {
1614 my ($opts, $opt, $msg, @imgs) = @_;
1616 my $positions = $opts->{'gif_positions'};
1618 for my $pos (@$positions) {
1619 my ($x, $y) = @$pos;
1620 my $img = $imgs[$index++];
1621 $img->settag(name=>'gif_left', value=>$x);
1622 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1624 $$msg .= "replaced with the gif_left and gif_top tags";
1629 gif_each_palette=>'gif_local_map',
1630 interlace => 'gif_interlace',
1631 gif_delays => 'gif_delay',
1632 gif_positions => \&_fix_gif_positions,
1633 gif_loop_count => 'gif_loop',
1636 # options that should be converted to colors
1637 my %color_opts = map { $_ => 1 } qw/i_background/;
1640 my ($self, $opts, $prefix, @imgs) = @_;
1642 for my $opt (keys %$opts) {
1644 if ($obsolete_opts{$opt}) {
1645 my $new = $obsolete_opts{$opt};
1646 my $msg = "Obsolete option $opt ";
1648 $new->($opts, $opt, \$msg, @imgs);
1651 $msg .= "replaced with the $new tag ";
1654 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1655 warn $msg if $warn_obsolete && $^W;
1657 next unless $tagname =~ /^\Q$prefix/;
1658 my $value = $opts->{$opt};
1659 if ($color_opts{$opt}) {
1660 $value = _color($value);
1662 $self->_set_error($Imager::ERRSTR);
1667 if (UNIVERSAL::isa($value, "Imager::Color")) {
1668 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1669 for my $img (@imgs) {
1670 $img->settag(name=>$tagname, value=>$tag);
1673 elsif (ref($value) eq 'ARRAY') {
1674 for my $i (0..$#$value) {
1675 my $val = $value->[$i];
1677 if (UNIVERSAL::isa($val, "Imager::Color")) {
1678 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1680 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1683 $self->_set_error("Unknown reference type " . ref($value) .
1684 " supplied in array for $opt");
1690 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1695 $self->_set_error("Unknown reference type " . ref($value) .
1696 " supplied for $opt");
1701 # set it as a tag for every image
1702 for my $img (@imgs) {
1703 $img->settag(name=>$tagname, value=>$value);
1711 # Write an image to file
1714 my %input=(jpegquality=>75,
1724 $self->_set_opts(\%input, "i_", $self)
1727 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1729 if (!$input{'type'} and $input{file}) {
1730 $input{'type'}=$FORMATGUESS->($input{file});
1732 if (!$input{'type'}) {
1733 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1737 _writer_autoload($input{type});
1740 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1741 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1744 $writers{$input{type}}{single}->($self, $IO, %input)
1748 if (!$formats{$input{'type'}}) {
1749 my $write_types = join ', ', sort Imager->write_types();
1750 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1754 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1757 if ($input{'type'} eq 'tiff') {
1758 $self->_set_opts(\%input, "tiff_", $self)
1760 $self->_set_opts(\%input, "exif_", $self)
1763 if (defined $input{class} && $input{class} eq 'fax') {
1764 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1765 $self->{ERRSTR} = $self->_error_as_msg();
1769 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1770 $self->{ERRSTR} = $self->_error_as_msg();
1774 } elsif ( $input{'type'} eq 'pnm' ) {
1775 $self->_set_opts(\%input, "pnm_", $self)
1777 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1778 $self->{ERRSTR} = $self->_error_as_msg();
1781 $self->{DEBUG} && print "writing a pnm file\n";
1782 } elsif ( $input{'type'} eq 'raw' ) {
1783 $self->_set_opts(\%input, "raw_", $self)
1785 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1786 $self->{ERRSTR} = $self->_error_as_msg();
1789 $self->{DEBUG} && print "writing a raw file\n";
1790 } elsif ( $input{'type'} eq 'png' ) {
1791 $self->_set_opts(\%input, "png_", $self)
1793 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1794 $self->{ERRSTR}='unable to write png image';
1797 $self->{DEBUG} && print "writing a png file\n";
1798 } elsif ( $input{'type'} eq 'jpeg' ) {
1799 $self->_set_opts(\%input, "jpeg_", $self)
1801 $self->_set_opts(\%input, "exif_", $self)
1803 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1804 $self->{ERRSTR} = $self->_error_as_msg();
1807 $self->{DEBUG} && print "writing a jpeg file\n";
1808 } elsif ( $input{'type'} eq 'bmp' ) {
1809 $self->_set_opts(\%input, "bmp_", $self)
1811 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1812 $self->{ERRSTR} = $self->_error_as_msg;
1815 $self->{DEBUG} && print "writing a bmp file\n";
1816 } elsif ( $input{'type'} eq 'tga' ) {
1817 $self->_set_opts(\%input, "tga_", $self)
1820 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1821 $self->{ERRSTR}=$self->_error_as_msg();
1824 $self->{DEBUG} && print "writing a tga file\n";
1825 } elsif ( $input{'type'} eq 'gif' ) {
1826 $self->_set_opts(\%input, "gif_", $self)
1828 # compatibility with the old interfaces
1829 if ($input{gifquant} eq 'lm') {
1830 $input{make_colors} = 'addi';
1831 $input{translate} = 'perturb';
1832 $input{perturb} = $input{lmdither};
1833 } elsif ($input{gifquant} eq 'gen') {
1834 # just pass options through
1836 $input{make_colors} = 'webmap'; # ignored
1837 $input{translate} = 'giflib';
1839 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1840 $self->{ERRSTR} = $self->_error_as_msg;
1846 if (exists $input{'data'}) {
1847 my $data = io_slurp($IO);
1849 $self->{ERRSTR}='Could not slurp from buffer';
1852 ${$input{data}} = $data;
1858 my ($class, $opts, @images) = @_;
1860 my $type = $opts->{type};
1862 if (!$type && $opts->{'file'}) {
1863 $type = $FORMATGUESS->($opts->{'file'});
1866 $class->_set_error('type parameter missing and not possible to guess from extension');
1869 # translate to ImgRaw
1870 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1871 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1874 $class->_set_opts($opts, "i_", @images)
1876 my @work = map $_->{IMG}, @images;
1878 _writer_autoload($type);
1881 if ($writers{$type} && $writers{$type}{multiple}) {
1882 ($IO, $file) = $class->_get_writer_io($opts, $type)
1885 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1889 if (!$formats{$type}) {
1890 my $write_types = join ', ', sort Imager->write_types();
1891 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1895 ($IO, $file) = $class->_get_writer_io($opts, $type)
1898 if ($type eq 'gif') {
1899 $class->_set_opts($opts, "gif_", @images)
1901 my $gif_delays = $opts->{gif_delays};
1902 local $opts->{gif_delays} = $gif_delays;
1903 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1904 # assume the caller wants the same delay for each frame
1905 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1907 unless (i_writegif_wiol($IO, $opts, @work)) {
1908 $class->_set_error($class->_error_as_msg());
1912 elsif ($type eq 'tiff') {
1913 $class->_set_opts($opts, "tiff_", @images)
1915 $class->_set_opts($opts, "exif_", @images)
1918 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1919 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1920 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1923 $res = i_writetiff_multi_wiol($IO, @work);
1926 $class->_set_error($class->_error_as_msg());
1932 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1937 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1943 if (exists $opts->{'data'}) {
1944 my $data = io_slurp($IO);
1946 Imager->_set_error('Could not slurp from buffer');
1949 ${$opts->{data}} = $data;
1954 # read multiple images from a file
1956 my ($class, %opts) = @_;
1958 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1961 my $type = $opts{'type'};
1963 $type = i_test_format_probe($IO, -1);
1966 if ($opts{file} && !$type) {
1968 $type = $FORMATGUESS->($opts{file});
1972 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1976 _reader_autoload($type);
1978 if ($readers{$type} && $readers{$type}{multiple}) {
1979 return $readers{$type}{multiple}->($IO, %opts);
1982 if ($type eq 'gif') {
1984 @imgs = i_readgif_multi_wiol($IO);
1987 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1991 $ERRSTR = _error_as_msg();
1995 elsif ($type eq 'tiff') {
1996 my @imgs = i_readtiff_multi_wiol($IO, -1);
1999 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2003 $ERRSTR = _error_as_msg();
2008 my $img = Imager->new;
2009 if ($img->read(%opts, io => $IO, type => $type)) {
2012 Imager->_set_error($img->errstr);
2018 # Destroy an Imager object
2022 # delete $instances{$self};
2023 if (defined($self->{IMG})) {
2024 # the following is now handled by the XS DESTROY method for
2025 # Imager::ImgRaw object
2026 # Re-enabling this will break virtual images
2027 # tested for in t/t020masked.t
2028 # i_img_destroy($self->{IMG});
2029 undef($self->{IMG});
2031 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2035 # Perform an inplace filter of an image
2036 # that is the image will be overwritten with the data
2042 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2044 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2046 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2047 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2050 if ($filters{$input{'type'}}{names}) {
2051 my $names = $filters{$input{'type'}}{names};
2052 for my $name (keys %$names) {
2053 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2054 $input{$name} = $names->{$name}{$input{$name}};
2058 if (defined($filters{$input{'type'}}{defaults})) {
2059 %hsh=( image => $self->{IMG},
2061 %{$filters{$input{'type'}}{defaults}},
2064 %hsh=( image => $self->{IMG},
2069 my @cs=@{$filters{$input{'type'}}{callseq}};
2072 if (!defined($hsh{$_})) {
2073 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2078 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2079 &{$filters{$input{'type'}}{callsub}}(%hsh);
2082 chomp($self->{ERRSTR} = $@);
2088 $self->{DEBUG} && print "callseq is: @cs\n";
2089 $self->{DEBUG} && print "matching callseq is: @b\n";
2094 sub register_filter {
2096 my %hsh = ( defaults => {}, @_ );
2099 or die "register_filter() with no type\n";
2100 defined $hsh{callsub}
2101 or die "register_filter() with no callsub\n";
2102 defined $hsh{callseq}
2103 or die "register_filter() with no callseq\n";
2105 exists $filters{$hsh{type}}
2108 $filters{$hsh{type}} = \%hsh;
2113 sub scale_calculate {
2116 my %opts = ('type'=>'max', @_);
2118 # none of these should be references
2119 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2120 if (defined $opts{$name} && ref $opts{$name}) {
2121 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2126 my ($x_scale, $y_scale);
2127 my $width = $opts{width};
2128 my $height = $opts{height};
2130 defined $width or $width = $self->getwidth;
2131 defined $height or $height = $self->getheight;
2134 unless (defined $width && defined $height) {
2135 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2140 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2141 $x_scale = $opts{'xscalefactor'};
2142 $y_scale = $opts{'yscalefactor'};
2144 elsif ($opts{'xscalefactor'}) {
2145 $x_scale = $opts{'xscalefactor'};
2146 $y_scale = $opts{'scalefactor'} || $x_scale;
2148 elsif ($opts{'yscalefactor'}) {
2149 $y_scale = $opts{'yscalefactor'};
2150 $x_scale = $opts{'scalefactor'} || $y_scale;
2153 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2156 # work out the scaling
2157 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2158 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2159 $opts{ypixels} / $height );
2160 if ($opts{'type'} eq 'min') {
2161 $x_scale = $y_scale = _min($xpix,$ypix);
2163 elsif ($opts{'type'} eq 'max') {
2164 $x_scale = $y_scale = _max($xpix,$ypix);
2166 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2171 $self->_set_error('invalid value for type parameter');
2174 } elsif ($opts{xpixels}) {
2175 $x_scale = $y_scale = $opts{xpixels} / $width;
2177 elsif ($opts{ypixels}) {
2178 $x_scale = $y_scale = $opts{ypixels}/$height;
2180 elsif ($opts{constrain} && ref $opts{constrain}
2181 && $opts{constrain}->can('constrain')) {
2182 # we've been passed an Image::Math::Constrain object or something
2183 # that looks like one
2185 (undef, undef, $scalefactor)
2186 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2187 unless ($scalefactor) {
2188 $self->_set_error('constrain method failed on constrain parameter');
2191 $x_scale = $y_scale = $scalefactor;
2194 my $new_width = int($x_scale * $width + 0.5);
2195 $new_width > 0 or $new_width = 1;
2196 my $new_height = int($y_scale * $height + 0.5);
2197 $new_height > 0 or $new_height = 1;
2199 return ($x_scale, $y_scale, $new_width, $new_height);
2203 # Scale an image to requested size and return the scaled version
2207 my %opts = (qtype=>'normal' ,@_);
2208 my $img = Imager->new();
2209 my $tmp = Imager->new();
2211 unless (defined wantarray) {
2212 my @caller = caller;
2213 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2217 unless ($self->{IMG}) {
2218 $self->_set_error('empty input image');
2222 my ($x_scale, $y_scale, $new_width, $new_height) =
2223 $self->scale_calculate(%opts)
2226 if ($opts{qtype} eq 'normal') {
2227 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2228 if ( !defined($tmp->{IMG}) ) {
2229 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2232 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2233 if ( !defined($img->{IMG}) ) {
2234 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2240 elsif ($opts{'qtype'} eq 'preview') {
2241 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2242 if ( !defined($img->{IMG}) ) {
2243 $self->{ERRSTR}='unable to scale image';
2248 elsif ($opts{'qtype'} eq 'mixing') {
2249 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2250 unless ($img->{IMG}) {
2251 $self->_set_error(Imager->_error_as_msg);
2257 $self->_set_error('invalid value for qtype parameter');
2262 # Scales only along the X axis
2266 my %opts = ( scalefactor=>0.5, @_ );
2268 unless (defined wantarray) {
2269 my @caller = caller;
2270 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2274 unless ($self->{IMG}) {
2275 $self->{ERRSTR} = 'empty input image';
2279 my $img = Imager->new();
2281 my $scalefactor = $opts{scalefactor};
2283 if ($opts{pixels}) {
2284 $scalefactor = $opts{pixels} / $self->getwidth();
2287 unless ($self->{IMG}) {
2288 $self->{ERRSTR}='empty input image';
2292 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2294 if ( !defined($img->{IMG}) ) {
2295 $self->{ERRSTR} = 'unable to scale image';
2302 # Scales only along the Y axis
2306 my %opts = ( scalefactor => 0.5, @_ );
2308 unless (defined wantarray) {
2309 my @caller = caller;
2310 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2314 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2316 my $img = Imager->new();
2318 my $scalefactor = $opts{scalefactor};
2320 if ($opts{pixels}) {
2321 $scalefactor = $opts{pixels} / $self->getheight();
2324 unless ($self->{IMG}) {
2325 $self->{ERRSTR} = 'empty input image';
2328 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2330 if ( !defined($img->{IMG}) ) {
2331 $self->{ERRSTR} = 'unable to scale image';
2338 # Transform returns a spatial transformation of the input image
2339 # this moves pixels to a new location in the returned image.
2340 # NOTE - should make a utility function to check transforms for
2345 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2347 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2349 # print Dumper(\%opts);
2352 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2354 eval ("use Affix::Infix2Postfix;");
2357 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2360 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2361 {op=>'-',trans=>'Sub'},
2362 {op=>'*',trans=>'Mult'},
2363 {op=>'/',trans=>'Div'},
2364 {op=>'-','type'=>'unary',trans=>'u-'},
2366 {op=>'func','type'=>'unary'}],
2367 'grouping'=>[qw( \( \) )],
2368 'func'=>[qw( sin cos )],
2373 @xt=$I2P->translate($opts{'xexpr'});
2374 @yt=$I2P->translate($opts{'yexpr'});
2376 $numre=$I2P->{'numre'};
2379 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2380 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2381 @{$opts{'parm'}}=@pt;
2384 # print Dumper(\%opts);
2386 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2387 $self->{ERRSTR}='transform: no xopcodes given.';
2391 @op=@{$opts{'xopcodes'}};
2393 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2394 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2397 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2403 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2404 $self->{ERRSTR}='transform: no yopcodes given.';
2408 @op=@{$opts{'yopcodes'}};
2410 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2411 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2414 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2419 if ( !exists $opts{'parm'}) {
2420 $self->{ERRSTR}='transform: no parameter arg given.';
2424 # print Dumper(\@ropx);
2425 # print Dumper(\@ropy);
2426 # print Dumper(\@ropy);
2428 my $img = Imager->new();
2429 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2430 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2436 my ($opts, @imgs) = @_;
2438 require "Imager/Expr.pm";
2440 $opts->{variables} = [ qw(x y) ];
2441 my ($width, $height) = @{$opts}{qw(width height)};
2443 $width ||= $imgs[0]->getwidth();
2444 $height ||= $imgs[0]->getheight();
2446 for my $img (@imgs) {
2447 $opts->{constants}{"w$img_num"} = $img->getwidth();
2448 $opts->{constants}{"h$img_num"} = $img->getheight();
2449 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2450 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2455 $opts->{constants}{w} = $width;
2456 $opts->{constants}{cx} = $width/2;
2459 $Imager::ERRSTR = "No width supplied";
2463 $opts->{constants}{h} = $height;
2464 $opts->{constants}{cy} = $height/2;
2467 $Imager::ERRSTR = "No height supplied";
2470 my $code = Imager::Expr->new($opts);
2472 $Imager::ERRSTR = Imager::Expr::error();
2475 my $channels = $opts->{channels} || 3;
2476 unless ($channels >= 1 && $channels <= 4) {
2477 return Imager->_set_error("channels must be an integer between 1 and 4");
2480 my $img = Imager->new();
2481 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2482 $channels, $code->code(),
2483 $code->nregs(), $code->cregs(),
2484 [ map { $_->{IMG} } @imgs ]);
2485 if (!defined $img->{IMG}) {
2486 $Imager::ERRSTR = Imager->_error_as_msg();
2497 unless ($self->{IMG}) {
2498 $self->{ERRSTR}='empty input image';
2501 unless ($opts{src} && $opts{src}->{IMG}) {
2502 $self->{ERRSTR}='empty input image for src';
2506 %opts = (src_minx => 0,
2508 src_maxx => $opts{src}->getwidth(),
2509 src_maxy => $opts{src}->getheight(),
2513 defined $tx or $tx = $opts{left};
2514 defined $tx or $tx = 0;
2517 defined $ty or $ty = $opts{top};
2518 defined $ty or $ty = 0;
2520 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2521 $opts{src_minx}, $opts{src_miny},
2522 $opts{src_maxx}, $opts{src_maxy})) {
2523 $self->_set_error($self->_error_as_msg());
2540 unless ($self->{IMG}) {
2541 $self->_set_error("compose: empty input image");
2545 unless ($opts{src}) {
2546 $self->_set_error("compose: src parameter missing");
2550 unless ($opts{src}{IMG}) {
2551 $self->_set_error("compose: src parameter empty image");
2554 my $src = $opts{src};
2556 my $left = $opts{left};
2557 defined $left or $left = $opts{tx};
2558 defined $left or $left = 0;
2560 my $top = $opts{top};
2561 defined $top or $top = $opts{ty};
2562 defined $top or $top = 0;
2564 my $src_left = $opts{src_left};
2565 defined $src_left or $src_left = $opts{src_minx};
2566 defined $src_left or $src_left = 0;
2568 my $src_top = $opts{src_top};
2569 defined $src_top or $src_top = $opts{src_miny};
2570 defined $src_top or $src_top = 0;
2572 my $width = $opts{width};
2573 if (!defined $width && defined $opts{src_maxx}) {
2574 $width = $opts{src_maxx} - $src_left;
2576 defined $width or $width = $src->getwidth() - $src_left;
2578 my $height = $opts{height};
2579 if (!defined $height && defined $opts{src_maxy}) {
2580 $height = $opts{src_maxy} - $src_top;
2582 defined $height or $height = $src->getheight() - $src_top;
2584 my $combine = $self->_combine($opts{combine}, 'normal');
2587 unless ($opts{mask}{IMG}) {
2588 $self->_set_error("compose: mask parameter empty image");
2592 my $mask_left = $opts{mask_left};
2593 defined $mask_left or $mask_left = $opts{mask_minx};
2594 defined $mask_left or $mask_left = 0;
2596 my $mask_top = $opts{mask_top};
2597 defined $mask_top or $mask_top = $opts{mask_miny};
2598 defined $mask_top or $mask_top = 0;
2600 i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2601 $left, $top, $src_left, $src_top,
2602 $mask_left, $mask_top, $width, $height,
2603 $combine, $opts{opacity})
2607 i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2608 $width, $height, $combine, $opts{opacity})
2618 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2620 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2621 $dir = $xlate{$opts{'dir'}};
2622 return $self if i_flipxy($self->{IMG}, $dir);
2630 unless (defined wantarray) {
2631 my @caller = caller;
2632 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2636 if (defined $opts{right}) {
2637 my $degrees = $opts{right};
2639 $degrees += 360 * int(((-$degrees)+360)/360);
2641 $degrees = $degrees % 360;
2642 if ($degrees == 0) {
2643 return $self->copy();
2645 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2646 my $result = Imager->new();
2647 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2651 $self->{ERRSTR} = $self->_error_as_msg();
2656 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2660 elsif (defined $opts{radians} || defined $opts{degrees}) {
2661 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2663 my $back = $opts{back};
2664 my $result = Imager->new;
2666 $back = _color($back);
2668 $self->_set_error(Imager->errstr);
2672 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2675 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2677 if ($result->{IMG}) {
2681 $self->{ERRSTR} = $self->_error_as_msg();
2686 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2691 sub matrix_transform {
2695 unless (defined wantarray) {
2696 my @caller = caller;
2697 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2701 if ($opts{matrix}) {
2702 my $xsize = $opts{xsize} || $self->getwidth;
2703 my $ysize = $opts{ysize} || $self->getheight;
2705 my $result = Imager->new;
2707 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2708 $opts{matrix}, $opts{back})
2712 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2720 $self->{ERRSTR} = "matrix parameter required";
2726 *yatf = \&matrix_transform;
2728 # These two are supported for legacy code only
2731 return Imager::Color->new(@_);
2735 return Imager::Color::set(@_);
2738 # Draws a box between the specified corner points.
2741 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2742 my $dflcl=i_color_new(255,255,255,255);
2743 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2745 if (exists $opts{'box'}) {
2746 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2747 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2748 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2749 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2752 if ($opts{filled}) {
2753 my $color = _color($opts{'color'});
2755 $self->{ERRSTR} = $Imager::ERRSTR;
2758 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2759 $opts{ymax}, $color);
2761 elsif ($opts{fill}) {
2762 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2763 # assume it's a hash ref
2764 require 'Imager/Fill.pm';
2765 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2766 $self->{ERRSTR} = $Imager::ERRSTR;
2770 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2771 $opts{ymax},$opts{fill}{fill});
2774 my $color = _color($opts{'color'});
2776 $self->{ERRSTR} = $Imager::ERRSTR;
2779 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2787 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2788 my $dflcl=i_color_new(255,255,255,255);
2789 my %opts=(color=>$dflcl,
2790 'r'=>_min($self->getwidth(),$self->getheight())/3,
2791 'x'=>$self->getwidth()/2,
2792 'y'=>$self->getheight()/2,
2793 'd1'=>0, 'd2'=>361, @_);
2796 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2797 # assume it's a hash ref
2798 require 'Imager/Fill.pm';
2799 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2800 $self->{ERRSTR} = $Imager::ERRSTR;
2804 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2805 $opts{'d2'}, $opts{fill}{fill});
2808 my $color = _color($opts{'color'});
2810 $self->{ERRSTR} = $Imager::ERRSTR;
2813 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2814 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2818 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2819 $opts{'d1'}, $opts{'d2'}, $color);
2825 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2826 # assume it's a hash ref
2827 require 'Imager/Fill.pm';
2828 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2829 $self->{ERRSTR} = $Imager::ERRSTR;
2833 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2834 $opts{'d2'}, $opts{fill}{fill});
2837 my $color = _color($opts{'color'});
2839 $self->{ERRSTR} = $Imager::ERRSTR;
2842 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2843 $opts{'d1'}, $opts{'d2'}, $color);
2850 # Draws a line from one point to the other
2851 # the endpoint is set if the endp parameter is set which it is by default.
2852 # to turn of the endpoint being set use endp=>0 when calling line.
2856 my $dflcl=i_color_new(0,0,0,0);
2857 my %opts=(color=>$dflcl,
2860 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2862 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2863 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2865 my $color = _color($opts{'color'});
2867 $self->{ERRSTR} = $Imager::ERRSTR;
2871 $opts{antialias} = $opts{aa} if defined $opts{aa};
2872 if ($opts{antialias}) {
2873 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2874 $color, $opts{endp});
2876 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2877 $color, $opts{endp});
2882 # Draws a line between an ordered set of points - It more or less just transforms this
2883 # into a list of lines.
2887 my ($pt,$ls,@points);
2888 my $dflcl=i_color_new(0,0,0,0);
2889 my %opts=(color=>$dflcl,@_);
2891 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2893 if (exists($opts{points})) { @points=@{$opts{points}}; }
2894 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2895 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2898 # print Dumper(\@points);
2900 my $color = _color($opts{'color'});
2902 $self->{ERRSTR} = $Imager::ERRSTR;
2905 $opts{antialias} = $opts{aa} if defined $opts{aa};
2906 if ($opts{antialias}) {
2909 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2916 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2926 my ($pt,$ls,@points);
2927 my $dflcl = i_color_new(0,0,0,0);
2928 my %opts = (color=>$dflcl, @_);
2930 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2932 if (exists($opts{points})) {
2933 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2934 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2937 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2938 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2941 if ($opts{'fill'}) {
2942 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2943 # assume it's a hash ref
2944 require 'Imager/Fill.pm';
2945 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2946 $self->{ERRSTR} = $Imager::ERRSTR;
2950 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2951 $opts{'fill'}{'fill'});
2954 my $color = _color($opts{'color'});
2956 $self->{ERRSTR} = $Imager::ERRSTR;
2959 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2966 # this the multipoint bezier curve
2967 # this is here more for testing that actual usage since
2968 # this is not a good algorithm. Usually the curve would be
2969 # broken into smaller segments and each done individually.
2973 my ($pt,$ls,@points);
2974 my $dflcl=i_color_new(0,0,0,0);
2975 my %opts=(color=>$dflcl,@_);
2977 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2979 if (exists $opts{points}) {
2980 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2981 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2984 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2985 $self->{ERRSTR}='Missing or invalid points.';
2989 my $color = _color($opts{'color'});
2991 $self->{ERRSTR} = $Imager::ERRSTR;
2994 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3000 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3003 unless (exists $opts{'x'} && exists $opts{'y'}) {
3004 $self->{ERRSTR} = "missing seed x and y parameters";
3008 if ($opts{border}) {
3009 my $border = _color($opts{border});
3011 $self->_set_error($Imager::ERRSTR);
3015 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3016 # assume it's a hash ref
3017 require Imager::Fill;
3018 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3019 $self->{ERRSTR} = $Imager::ERRSTR;
3023 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3024 $opts{fill}{fill}, $border);
3027 my $color = _color($opts{'color'});
3029 $self->{ERRSTR} = $Imager::ERRSTR;
3032 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3039 $self->{ERRSTR} = $self->_error_as_msg();
3045 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3046 # assume it's a hash ref
3047 require 'Imager/Fill.pm';
3048 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3049 $self->{ERRSTR} = $Imager::ERRSTR;
3053 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3056 my $color = _color($opts{'color'});
3058 $self->{ERRSTR} = $Imager::ERRSTR;
3061 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3067 $self->{ERRSTR} = $self->_error_as_msg();
3076 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
3078 unless (exists $opts{'x'} && exists $opts{'y'}) {
3079 $self->{ERRSTR} = 'missing x and y parameters';
3085 my $color = _color($opts{color})
3087 if (ref $x && ref $y) {
3088 unless (@$x == @$y) {
3089 $self->{ERRSTR} = 'length of x and y mismatch';
3093 if ($color->isa('Imager::Color')) {
3094 for my $i (0..$#{$opts{'x'}}) {
3095 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3100 for my $i (0..$#{$opts{'x'}}) {
3101 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3109 if ($color->isa('Imager::Color')) {
3110 i_ppix($self->{IMG}, $x, $y, $color)
3114 i_ppixf($self->{IMG}, $x, $y, $color)
3125 my %opts = ( "type"=>'8bit', @_);
3127 unless (exists $opts{'x'} && exists $opts{'y'}) {
3128 $self->{ERRSTR} = 'missing x and y parameters';
3134 if (ref $x && ref $y) {
3135 unless (@$x == @$y) {
3136 $self->{ERRSTR} = 'length of x and y mismatch';
3140 if ($opts{"type"} eq '8bit') {
3141 for my $i (0..$#{$opts{'x'}}) {
3142 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3146 for my $i (0..$#{$opts{'x'}}) {
3147 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3150 return wantarray ? @result : \@result;
3153 if ($opts{"type"} eq '8bit') {
3154 return i_get_pixel($self->{IMG}, $x, $y);
3157 return i_gpixf($self->{IMG}, $x, $y);
3166 my %opts = ( type => '8bit', x=>0, @_);
3168 $self->_valid_image or return;
3170 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3172 unless (defined $opts{'y'}) {
3173 $self->_set_error("missing y parameter");
3177 if ($opts{type} eq '8bit') {
3178 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3181 elsif ($opts{type} eq 'float') {
3182 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3185 elsif ($opts{type} eq 'index') {
3186 unless (i_img_type($self->{IMG})) {
3187 $self->_set_error("type => index only valid on paletted images");
3190 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3194 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3201 my %opts = ( x=>0, @_);
3203 $self->_valid_image or return;
3205 unless (defined $opts{'y'}) {
3206 $self->_set_error("missing y parameter");
3211 if (ref $opts{pixels} && @{$opts{pixels}}) {
3212 # try to guess the type
3213 if ($opts{pixels}[0]->isa('Imager::Color')) {
3214 $opts{type} = '8bit';
3216 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3217 $opts{type} = 'float';
3220 $self->_set_error("missing type parameter and could not guess from pixels");
3226 $opts{type} = '8bit';
3230 if ($opts{type} eq '8bit') {
3231 if (ref $opts{pixels}) {
3232 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3235 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3238 elsif ($opts{type} eq 'float') {
3239 if (ref $opts{pixels}) {
3240 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3243 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3246 elsif ($opts{type} eq 'index') {
3247 if (ref $opts{pixels}) {
3248 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3251 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3255 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3262 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3264 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3266 unless (defined $opts{'y'}) {
3267 $self->_set_error("missing y parameter");
3271 unless ($opts{channels}) {
3272 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3275 if ($opts{target}) {
3276 my $target = $opts{target};
3277 my $offset = $opts{offset};
3278 if ($opts{type} eq '8bit') {
3279 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3280 $opts{y}, @{$opts{channels}})
3282 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3283 return scalar(@samples);
3285 elsif ($opts{type} eq 'float') {
3286 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3287 $opts{y}, @{$opts{channels}});
3288 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3289 return scalar(@samples);
3291 elsif ($opts{type} =~ /^(\d+)bit$/) {
3295 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3296 $opts{y}, $bits, $target,
3297 $offset, @{$opts{channels}});
3298 unless (defined $count) {
3299 $self->_set_error(Imager->_error_as_msg);
3306 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3311 if ($opts{type} eq '8bit') {
3312 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3313 $opts{y}, @{$opts{channels}});
3315 elsif ($opts{type} eq 'float') {
3316 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3317 $opts{y}, @{$opts{channels}});
3319 elsif ($opts{type} =~ /^(\d+)bit$/) {
3323 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3324 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3329 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3337 my %opts = ( x => 0, offset => 0, @_ );
3339 unless ($self->{IMG}) {
3340 $self->_set_error('setsamples: empty input image');
3344 unless(defined $opts{data} && ref $opts{data}) {
3345 $self->_set_error('setsamples: data parameter missing or invalid');
3349 unless ($opts{channels}) {
3350 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3353 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3354 $self->_set_error('setsamples: type parameter missing or invalid');
3359 unless (defined $opts{width}) {
3360 $opts{width} = $self->getwidth() - $opts{x};
3363 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3364 $opts{channels}, $opts{data}, $opts{offset},
3366 unless (defined $count) {
3367 $self->_set_error(Imager->_error_as_msg);
3374 # make an identity matrix of the given size
3378 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3379 for my $c (0 .. ($size-1)) {
3380 $matrix->[$c][$c] = 1;
3385 # general function to convert an image
3387 my ($self, %opts) = @_;
3390 unless (defined wantarray) {
3391 my @caller = caller;
3392 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3396 # the user can either specify a matrix or preset
3397 # the matrix overrides the preset
3398 if (!exists($opts{matrix})) {
3399 unless (exists($opts{preset})) {
3400 $self->{ERRSTR} = "convert() needs a matrix or preset";
3404 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3405 # convert to greyscale, keeping the alpha channel if any
3406 if ($self->getchannels == 3) {
3407 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3409 elsif ($self->getchannels == 4) {
3410 # preserve the alpha channel
3411 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3416 $matrix = _identity($self->getchannels);
3419 elsif ($opts{preset} eq 'noalpha') {
3420 # strip the alpha channel
3421 if ($self->getchannels == 2 or $self->getchannels == 4) {
3422 $matrix = _identity($self->getchannels);
3423 pop(@$matrix); # lose the alpha entry
3426 $matrix = _identity($self->getchannels);
3429 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3431 $matrix = [ [ 1 ] ];
3433 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3434 $matrix = [ [ 0, 1 ] ];
3436 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3437 $matrix = [ [ 0, 0, 1 ] ];
3439 elsif ($opts{preset} eq 'alpha') {
3440 if ($self->getchannels == 2 or $self->getchannels == 4) {
3441 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3444 # the alpha is just 1 <shrug>
3445 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3448 elsif ($opts{preset} eq 'rgb') {
3449 if ($self->getchannels == 1) {
3450 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3452 elsif ($self->getchannels == 2) {
3453 # preserve the alpha channel
3454 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3457 $matrix = _identity($self->getchannels);
3460 elsif ($opts{preset} eq 'addalpha') {
3461 if ($self->getchannels == 1) {
3462 $matrix = _identity(2);
3464 elsif ($self->getchannels == 3) {
3465 $matrix = _identity(4);
3468 $matrix = _identity($self->getchannels);
3472 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3478 $matrix = $opts{matrix};
3481 my $new = Imager->new;
3482 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3483 unless ($new->{IMG}) {
3484 # most likely a bad matrix
3485 $self->{ERRSTR} = _error_as_msg();
3492 # general function to map an image through lookup tables
3495 my ($self, %opts) = @_;
3496 my @chlist = qw( red green blue alpha );
3498 if (!exists($opts{'maps'})) {
3499 # make maps from channel maps
3501 for $chnum (0..$#chlist) {
3502 if (exists $opts{$chlist[$chnum]}) {
3503 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3504 } elsif (exists $opts{'all'}) {
3505 $opts{'maps'}[$chnum] = $opts{'all'};
3509 if ($opts{'maps'} and $self->{IMG}) {
3510 i_map($self->{IMG}, $opts{'maps'} );
3516 my ($self, %opts) = @_;
3518 defined $opts{mindist} or $opts{mindist} = 0;
3520 defined $opts{other}
3521 or return $self->_set_error("No 'other' parameter supplied");
3522 defined $opts{other}{IMG}
3523 or return $self->_set_error("No image data in 'other' image");
3526 or return $self->_set_error("No image data");
3528 my $result = Imager->new;
3529 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3531 or return $self->_set_error($self->_error_as_msg());
3536 # destructive border - image is shrunk by one pixel all around
3539 my ($self,%opts)=@_;
3540 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3541 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3545 # Get the width of an image
3549 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3550 return (i_img_info($self->{IMG}))[0];
3553 # Get the height of an image
3557 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3558 return (i_img_info($self->{IMG}))[1];
3561 # Get number of channels in an image
3565 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3566 return i_img_getchannels($self->{IMG});
3573 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3574 return i_img_getmask($self->{IMG});
3582 if (!defined($self->{IMG})) {
3583 $self->{ERRSTR} = 'image is empty';
3586 unless (defined $opts{mask}) {
3587 $self->_set_error("mask parameter required");
3590 i_img_setmask( $self->{IMG} , $opts{mask} );
3595 # Get number of colors in an image
3599 my %opts=('maxcolors'=>2**30,@_);
3600 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3601 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3602 return ($rc==-1? undef : $rc);
3605 # Returns a reference to a hash. The keys are colour named (packed) and the
3606 # values are the number of pixels in this colour.
3607 sub getcolorusagehash {
3610 my %opts = ( maxcolors => 2**30, @_ );
3611 my $max_colors = $opts{maxcolors};
3612 unless (defined $max_colors && $max_colors > 0) {
3613 $self->_set_error('maxcolors must be a positive integer');
3617 unless (defined $self->{IMG}) {
3618 $self->_set_error('empty input image');
3622 my $channels= $self->getchannels;
3623 # We don't want to look at the alpha channel, because some gifs using it
3624 # doesn't define it for every colour (but only for some)
3625 $channels -= 1 if $channels == 2 or $channels == 4;
3627 my $height = $self->getheight;
3628 for my $y (0 .. $height - 1) {
3629 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3630 while (length $colors) {
3631 $color_use{ substr($colors, 0, $channels, '') }++;
3633 keys %color_use > $max_colors
3639 # This will return a ordered array of the colour usage. Kind of the sorted
3640 # version of the values of the hash returned by getcolorusagehash.
3641 # You might want to add safety checks and change the names, etc...
3645 my %opts = ( maxcolors => 2**30, @_ );
3646 my $max_colors = $opts{maxcolors};
3647 unless (defined $max_colors && $max_colors > 0) {
3648 $self->_set_error('maxcolors must be a positive integer');
3652 unless (defined $self->{IMG}) {
3653 $self->_set_error('empty input image');
3657 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3660 # draw string to an image
3664 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3666 my %input=('x'=>0, 'y'=>0, @_);
3667 defined($input{string}) or $input{string} = $input{text};
3669 unless(defined $input{string}) {
3670 $self->{ERRSTR}="missing required parameter 'string'";
3674 unless($input{font}) {
3675 $self->{ERRSTR}="missing required parameter 'font'";
3679 unless ($input{font}->draw(image=>$self, %input)) {
3691 unless ($self->{IMG}) {
3692 $self->{ERRSTR}='empty input image';
3701 my %input=('x'=>0, 'y'=>0, @_);
3702 $input{string}||=$input{text};
3704 unless(exists $input{string}) {
3705 $self->_set_error("missing required parameter 'string'");
3709 unless($input{font}) {
3710 $self->_set_error("missing required parameter 'font'");
3715 unless (@result = $input{font}->align(image=>$img, %input)) {
3719 return wantarray ? @result : $result[0];
3722 my @file_limit_names = qw/width height bytes/;
3724 sub set_file_limits {
3731 @values{@file_limit_names} = (0) x @file_limit_names;
3734 @values{@file_limit_names} = i_get_image_file_limits();
3737 for my $key (keys %values) {
3738 defined $opts{$key} and $values{$key} = $opts{$key};
3741 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3744 sub get_file_limits {
3745 i_get_image_file_limits();
3748 # Shortcuts that can be exported
3750 sub newcolor { Imager::Color->new(@_); }
3751 sub newfont { Imager::Font->new(@_); }
3752 sub NCF { Imager::Color::Float->new(@_) }
3754 *NC=*newcolour=*newcolor;
3761 #### Utility routines
3764 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3768 my ($self, $msg) = @_;
3771 $self->{ERRSTR} = $msg;
3779 # Default guess for the type of an image from extension
3781 sub def_guess_type {
3784 $ext=($name =~ m/\.([^\.]+)$/)[0];
3785 return 'tiff' if ($ext =~ m/^tiff?$/);
3786 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3787 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3788 return 'png' if ($ext eq "png");
3789 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3790 return 'tga' if ($ext eq "tga");
3791 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3792 return 'gif' if ($ext eq "gif");
3793 return 'raw' if ($ext eq "raw");
3794 return lc $ext; # best guess
3799 return @combine_types;
3802 # get the minimum of a list
3806 for(@_) { if ($_<$mx) { $mx=$_; }}
3810 # get the maximum of a list
3814 for(@_) { if ($_>$mx) { $mx=$_; }}
3818 # string stuff for iptc headers
3822 $str = substr($str,3);
3823 $str =~ s/[\n\r]//g;
3830 # A little hack to parse iptc headers.
3835 my($caption,$photogr,$headln,$credit);
3837 my $str=$self->{IPTCRAW};
3842 @ar=split(/8BIM/,$str);
3847 @sar=split(/\034\002/);
3848 foreach $item (@sar) {
3849 if ($item =~ m/^x/) {
3850 $caption = _clean($item);
3853 if ($item =~ m/^P/) {
3854 $photogr = _clean($item);
3857 if ($item =~ m/^i/) {
3858 $headln = _clean($item);
3861 if ($item =~ m/^n/) {
3862 $credit = _clean($item);
3868 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3875 or die "Only C language supported";
3877 require Imager::ExtUtils;
3878 return Imager::ExtUtils->inline_config;
3883 # Below is the stub of documentation for your module. You better edit it!
3887 Imager - Perl extension for Generating 24 bit Images
3897 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3902 # see Imager::Files for information on the read() method
3903 my $im = Imager->new(file=>$file)
3904 or die Imager->errstr();
3906 $file =~ s/\.[^.]*$//;
3908 # Create smaller version
3909 # documented in Imager::Transformations
3910 my $thumb = $img->scale(scalefactor=>.3);
3912 # Autostretch individual channels
3913 $thumb->filter(type=>'autolevels');
3915 # try to save in one of these formats
3918 for $format ( qw( png gif jpeg tiff ppm ) ) {
3919 # Check if given format is supported
3920 if ($Imager::formats{$format}) {
3921 $file.="_low.$format";
3922 print "Storing image as: $file\n";
3923 # documented in Imager::Files
3924 $thumb->write(file=>$file) or
3932 Imager is a module for creating and altering images. It can read and
3933 write various image formats, draw primitive shapes like lines,and
3934 polygons, blend multiple images together in various ways, scale, crop,
3935 render text and more.
3937 =head2 Overview of documentation
3943 Imager - This document - Synopsis, Example, Table of Contents and
3948 L<Imager::Tutorial> - a brief introduction to Imager.
3952 L<Imager::Cookbook> - how to do various things with Imager.
3956 L<Imager::ImageTypes> - Basics of constructing image objects with
3957 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3958 8/16/double bits/channel, color maps, channel masks, image tags, color
3959 quantization. Also discusses basic image information methods.
3963 L<Imager::Files> - IO interaction, reading/writing images, format
3968 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3973 L<Imager::Color> - Color specification.
3977 L<Imager::Fill> - Fill pattern specification.
3981 L<Imager::Font> - General font rendering, bounding boxes and font
3986 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3987 blending, pasting, convert and map.
3991 L<Imager::Engines> - Programmable transformations through
3992 C<transform()>, C<transform2()> and C<matrix_transform()>.
3996 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4001 L<Imager::Expr> - Expressions for evaluation engine used by
4006 L<Imager::Matrix2d> - Helper class for affine transformations.
4010 L<Imager::Fountain> - Helper for making gradient profiles.
4014 L<Imager::API> - using Imager's C API
4018 L<Imager::APIRef> - API function reference
4022 L<Imager::Inline> - using Imager's C API from Inline::C
4026 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4030 =head2 Basic Overview
4032 An Image object is created with C<$img = Imager-E<gt>new()>.
4035 $img=Imager->new(); # create empty image
4036 $img->read(file=>'lena.png',type=>'png') or # read image from file
4037 die $img->errstr(); # give an explanation
4038 # if something failed
4040 or if you want to create an empty image:
4042 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4044 This example creates a completely black image of width 400 and height
4047 =head1 ERROR HANDLING
4049 In general a method will return false when it fails, if it does use
4050 the errstr() method to find out why:
4056 Returns the last error message in that context.
4058 If the last error you received was from calling an object method, such
4059 as read, call errstr() as an object method to find out why:
4061 my $image = Imager->new;
4062 $image->read(file => 'somefile.gif')
4063 or die $image->errstr;
4065 If it was a class method then call errstr() as a class method:
4067 my @imgs = Imager->read_multi(file => 'somefile.gif')
4068 or die Imager->errstr;
4070 Note that in some cases object methods are implemented in terms of
4071 class methods so a failing object method may set both.
4075 The C<Imager-E<gt>new> method is described in detail in
4076 L<Imager::ImageTypes>.
4080 Where to find information on methods for Imager class objects.
4082 addcolors() - L<Imager::ImageTypes/addcolors> - add colors to a
4085 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4087 align_string() - L<Imager::Draw/align_string> - draw text aligned on a
4090 arc() - L<Imager::Draw/arc> - draw a filled arc
4092 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4095 box() - L<Imager::Draw/box> - draw a filled or outline box.
4097 circle() - L<Imager::Draw/circle> - draw a filled circle
4099 colorcount() - L<Imager::Draw/colorcount> - the number of colors in an
4100 image's palette (paletted images only)
4102 combines() - L<Imager::Draw/combines> - return a list of the different
4103 combine type keywords
4105 compose() - L<Imager::Transformations/compose> - compose one image
4108 convert() - L<Imager::Transformations/"Color transformations"> -
4109 transform the color space
4111 copy() - L<Imager::Transformations/copy> - make a duplicate of an
4114 crop() - L<Imager::Transformations/crop> - extract part of an image
4116 def_guess_type() - L<Imager::Files/def_guess_type> - default function
4117 used to guess the output file format based on the output filename
4119 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4121 difference() - L<Imager::Filters/"Image Difference"> - produce a
4122 difference images from two input images.
4124 errstr() - L<"Basic Overview"> - the error from the last failed
4127 filter() - L<Imager::Filters> - image filtering
4129 findcolor() - L<Imager::ImageTypes/findcolor> - search the image
4130 palette, if it has one
4132 flip() - L<Imager::Transformations/flip> - flip an image, vertically,
4135 flood_fill() - L<Imager::Draw/flood_fill> - fill an enclosed or same
4138 getchannels() - L<Imager::ImageTypes/getchannels> - the number of
4139 samples per pixel for an image
4141 getcolorcount() - L<Imager::ImageTypes/getcolorcount> - the number of
4142 different colors used by an image (works for direct color images)
4144 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4145 palette, if it has one
4147 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4149 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4151 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4153 getheight() - L<Imager::ImageTypes/getwidth> - height of the image in
4156 getmask() - L<Imager::ImageTypes/getmask> - write mask for the image
4158 getpixel() - L<Imager::Draw/getpixel> - retrieve one or more pixel
4161 getsamples() - L<Imager::Draw/getsamples> - retrieve samples from a
4162 row or subrow of pixels.
4164 getscanline() - L<Imager::Draw/getscanline> - retrieve colors for a
4165 row or subrow of pixels.
4167 getwidth() - L<Imager::ImageTypes/getwidth> - width of the image in
4170 img_set() - L<Imager::ImageTypes/img_set> - re-use an Imager object
4173 init() - L<Imager::ImageTypes/init>
4175 is_bilevel() - L<Imager::ImageTypes/is_bilevel> - returns whether
4176 image write functions should write the image in their bi-level (blank
4177 and white, no grey levels) format
4179 line() - L<Imager::Draw/line> - draw an interval
4181 load_plugin() - L<Imager::Filters/load_plugin>
4183 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4186 masked() - L<Imager::ImageTypes/masked> - make a masked image
4188 matrix_transform() - L<Imager::Engines/matrix_transform>
4190 maxcolors() - L<Imager::ImageTypes/maxcolors>
4192 NC() - L<Imager::Handy/NC>
4194 NCF() - L<Imager::Handy/NCF>
4196 new() - L<Imager::ImageTypes/new>
4198 newcolor() - L<Imager::Handy/newcolor>
4200 newcolour() - L<Imager::Handy/newcolour>
4202 newfont() - L<Imager::Handy/newfont>
4204 NF() - L<Imager::Handy/NF>
4206 open() - L<Imager::Files> - an alias for read()
4208 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4211 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4213 polygon() - L<Imager::Draw/polygon>
4215 polyline() - L<Imager::Draw/polyline>
4217 read() - L<Imager::Files> - read a single image from an image file
4219 read_multi() - L<Imager::Files> - read multiple images from an image
4222 read_types() - L<Imager::Files/read_types> - list image types Imager
4225 register_filter() - L<Imager::Filters/register_filter>
4227 register_reader() - L<Imager::Files/register_reader>
4229 register_writer() - L<Imager::Files/register_writer>
4231 rotate() - L<Imager::Transformations/rotate>
4233 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4234 image and use the alpha channel
4236 scale() - L<Imager::Transformations/scale>
4238 scale_calculate() - L<Imager::Transformations/scale_calculate>
4240 scaleX() - L<Imager::Transformations/scaleX>
4242 scaleY() - L<Imager::Transformations/scaleY>
4244 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4247 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4249 setmask() - L<Imager::ImageTypes/setmask>
4251 setpixel() - L<Imager::Draw/setpixel>
4253 setsamples() - L<Imager::Draw/setsamples>
4255 setscanline() - L<Imager::Draw/setscanline>
4257 settag() - L<Imager::ImageTypes/settag>
4259 string() - L<Imager::Draw/string> - draw text on an image
4261 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4263 to_paletted() - L<Imager::ImageTypes/to_paletted>
4265 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4267 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4269 transform() - L<Imager::Engines/"transform">
4271 transform2() - L<Imager::Engines/"transform2">
4273 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4275 unload_plugin() - L<Imager::Filters/unload_plugin>
4277 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4280 write() - L<Imager::Files> - write an image to a file
4282 write_multi() - L<Imager::Files> - write multiple image to an image
4285 write_types() - L<Imager::Files/read_types> - list image types Imager
4288 =head1 CONCEPT INDEX
4290 animated GIF - L<Imager::Files/"Writing an animated GIF">
4292 aspect ratio - L<Imager::ImageTypes/i_xres>,
4293 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4295 blend - alpha blending one image onto another
4296 L<Imager::Transformations/rubthrough>
4298 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4300 boxes, drawing - L<Imager::Draw/box>
4302 changes between image - L<Imager::Filters/"Image Difference">
4304 color - L<Imager::Color>
4306 color names - L<Imager::Color>, L<Imager::Color::Table>
4308 combine modes - L<Imager::Draw/"Combine Types">
4310 compare images - L<Imager::Filters/"Image Difference">
4312 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4314 convolution - L<Imager::Filters/conv>
4316 cropping - L<Imager::Transformations/crop>
4318 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4320 C<diff> images - L<Imager::Filters/"Image Difference">
4322 dpi - L<Imager::ImageTypes/i_xres>,
4323 L<Imager::Cookbook/"Image spatial resolution">
4325 drawing boxes - L<Imager::Draw/box>
4327 drawing lines - L<Imager::Draw/line>
4329 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4331 error message - L<"ERROR HANDLING">
4333 files, font - L<Imager::Font>
4335 files, image - L<Imager::Files>
4337 filling, types of fill - L<Imager::Fill>
4339 filling, boxes - L<Imager::Draw/box>
4341 filling, flood fill - L<Imager::Draw/flood_fill>
4343 flood fill - L<Imager::Draw/flood_fill>
4345 fonts - L<Imager::Font>
4347 fonts, drawing with - L<Imager::Draw/string>,
4348 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4350 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4352 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4354 fountain fill - L<Imager::Fill/"Fountain fills">,
4355 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4356 L<Imager::Filters/gradgen>
4358 GIF files - L<Imager::Files/"GIF">
4360 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4362 gradient fill - L<Imager::Fill/"Fountain fills">,
4363 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4364 L<Imager::Filters/gradgen>
4366 grayscale, convert image to - L<Imager::Transformations/convert>
4368 guassian blur - L<Imager::Filters/guassian>
4370 hatch fills - L<Imager::Fill/"Hatched fills">
4372 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4374 invert image - L<Imager::Filters/hardinvert>
4376 JPEG - L<Imager::Files/"JPEG">
4378 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4380 lines, drawing - L<Imager::Draw/line>
4382 matrix - L<Imager::Matrix2d>,
4383 L<Imager::Transformations/"Matrix Transformations">,
4384 L<Imager::Font/transform>
4386 metadata, image - L<Imager::ImageTypes/"Tags">
4388 mosaic - L<Imager::Filters/mosaic>
4390 noise, filter - L<Imager::Filters/noise>
4392 noise, rendered - L<Imager::Filters/turbnoise>,
4393 L<Imager::Filters/radnoise>
4395 paste - L<Imager::Transformations/paste>,
4396 L<Imager::Transformations/rubthrough>
4398 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4399 L<Imager::ImageTypes/new>
4401 posterize - L<Imager::Filters/postlevels>
4403 png files - L<Imager::Files>, L<Imager::Files/"PNG">
4405 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
4407 rectangles, drawing - L<Imager::Draw/box>
4409 resizing an image - L<Imager::Transformations/scale>,
4410 L<Imager::Transformations/crop>
4412 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4414 saving an image - L<Imager::Files>
4416 scaling - L<Imager::Transformations/scale>
4418 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4420 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4422 size, image - L<Imager::ImageTypes/getwidth>,
4423 L<Imager::ImageTypes/getheight>
4425 size, text - L<Imager::Font/bounding_box>
4427 tags, image metadata - L<Imager::ImageTypes/"Tags">
4429 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4430 L<Imager::Font::Wrap>
4432 text, wrapping text in an area - L<Imager::Font::Wrap>
4434 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4436 tiles, color - L<Imager::Filters/mosaic>
4438 unsharp mask - L<Imager::Filters/unsharpmask>
4440 watermark - L<Imager::Filters/watermark>
4442 writing an image to a file - L<Imager::Files>
4446 The best place to get help with Imager is the mailing list.
4448 To subscribe send a message with C<subscribe> in the body to:
4450 imager-devel+request@molar.is
4456 L<http://www.molar.is/en/lists/imager-devel/>
4460 where you can also find the mailing list archive.
4462 You can report bugs by pointing your browser at:
4466 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4470 or by sending an email to:
4474 bug-Imager@rt.cpan.org
4478 Please remember to include the versions of Imager, perl, supporting
4479 libraries, and any relevant code. If you have specific images that
4480 cause the problems, please include those too.
4482 If you don't want to publish your email address on a mailing list you
4483 can use CPAN::Forum:
4485 http://www.cpanforum.com/dist/Imager
4487 You will need to register to post.
4489 =head1 CONTRIBUTING TO IMAGER
4495 If you like or dislike Imager, you can add a public review of Imager
4498 http://cpanratings.perl.org/dist/Imager
4500 This requires a Bitcard Account (http://www.bitcard.org).
4502 You can also send email to the maintainer below.
4504 If you send me a bug report via email, it will be copied to RT.
4508 I accept patches, preferably against the main branch in subversion.
4509 You should include an explanation of the reason for why the patch is
4512 Your patch should include regression tests where possible, otherwise
4513 it will be delayed until I get a chance to write them.
4517 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4519 Arnar M. Hrafnkelsson is the original author of Imager.
4521 Many others have contributed to Imager, please see the README for a
4526 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4527 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4528 L<Imager::Font>(3), L<Imager::Transformations>(3),
4529 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4530 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4532 L<http://imager.perl.org/>
4534 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4536 Other perl imaging modules include:
4538 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).