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) ],
332 for my $cname (qw/Ia Il Is/) {
333 my $old = $hsh{$cname};
334 my $new_color = _color($old)
335 or die $Imager::ERRSTR, "\n";
336 $hsh{$cname} = $new_color;
338 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
339 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
340 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
344 $filters{postlevels} =
346 callseq => [ qw(image levels) ],
347 defaults => { levels => 10 },
348 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
350 $filters{watermark} =
352 callseq => [ qw(image wmark tx ty pixdiff) ],
353 defaults => { pixdiff=>10, tx=>0, ty=>0 },
357 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
363 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
365 ftype => { linear => 0,
371 repeat => { none => 0,
386 multiply => 2, mult => 2,
389 subtract => 5, 'sub' => 5,
399 defaults => { ftype => 0, repeat => 0, combine => 0,
400 super_sample => 0, ssample_param => 4,
413 # make sure the segments are specified with colors
415 for my $segment (@{$hsh{segments}}) {
416 my @new_segment = @$segment;
418 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
419 push @segments, \@new_segment;
422 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
423 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
424 $hsh{ssample_param}, \@segments)
425 or die Imager->_error_as_msg() . "\n";
428 $filters{unsharpmask} =
430 callseq => [ qw(image stddev scale) ],
431 defaults => { stddev=>2.0, scale=>1.0 },
435 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
439 $FORMATGUESS=\&def_guess_type;
449 # NOTE: this might be moved to an import override later on
454 if ($_[$i] eq '-log-stderr') {
462 goto &Exporter::import;
466 i_init_log($_[0],$_[1]);
467 i_log_entry("Imager $VERSION starting\n", 1);
472 my %parms=(loglevel=>1,@_);
474 init_log($parms{'log'},$parms{'loglevel'});
477 if (exists $parms{'warn_obsolete'}) {
478 $warn_obsolete = $parms{'warn_obsolete'};
481 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
482 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
486 if (exists $parms{'t1log'}) {
487 i_init_fonts($parms{'t1log'});
493 print "shutdown code\n";
494 # for(keys %instances) { $instances{$_}->DESTROY(); }
495 malloc_state(); # how do decide if this should be used? -- store something from the import
496 print "Imager exiting\n";
500 # Load a filter plugin
505 my ($DSO_handle,$str)=DSO_open($filename);
506 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
507 my %funcs=DSO_funclist($DSO_handle);
508 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
510 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
512 $DSOs{$filename}=[$DSO_handle,\%funcs];
515 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
516 $DEBUG && print "eval string:\n",$evstr,"\n";
528 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
529 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
530 for(keys %{$funcref}) {
532 $DEBUG && print "unloading: $_\n";
534 my $rc=DSO_close($DSO_handle);
535 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
539 # take the results of i_error() and make a message out of it
541 return join(": ", map $_->[0], i_errors());
544 # this function tries to DWIM for color parameters
545 # color objects are used as is
546 # simple scalars are simply treated as single parameters to Imager::Color->new
547 # hashrefs are treated as named argument lists to Imager::Color->new
548 # arrayrefs are treated as list arguments to Imager::Color->new iff any
550 # other arrayrefs are treated as list arguments to Imager::Color::Float
554 # perl 5.6.0 seems to do weird things to $arg if we don't make an
555 # explicitly stringified copy
556 # I vaguely remember a bug on this on p5p, but couldn't find it
557 # through bugs.perl.org (I had trouble getting it to find any bugs)
558 my $copy = $arg . "";
562 if (UNIVERSAL::isa($arg, "Imager::Color")
563 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
567 if ($copy =~ /^HASH\(/) {
568 $result = Imager::Color->new(%$arg);
570 elsif ($copy =~ /^ARRAY\(/) {
571 $result = Imager::Color->new(@$arg);
574 $Imager::ERRSTR = "Not a color";
579 # assume Imager::Color::new knows how to handle it
580 $result = Imager::Color->new($arg);
587 my ($self, $combine, $default) = @_;
589 if (!defined $combine && ref $self) {
590 $combine = $self->{combine};
592 defined $combine or $combine = $defaults{combine};
593 defined $combine or $combine = $default;
595 if (exists $combine_types{$combine}) {
596 $combine = $combine_types{$combine};
605 $self->{IMG} and return 1;
607 $self->_set_error('empty input image');
612 # returns first defined parameter
615 return $_ if defined $_;
621 # Methods to be called on objects.
624 # Create a new Imager object takes very few parameters.
625 # usually you call this method and then call open from
626 # the resulting object
633 $self->{IMG}=undef; # Just to indicate what exists
634 $self->{ERRSTR}=undef; #
635 $self->{DEBUG}=$DEBUG;
636 $self->{DEBUG} and print "Initialized Imager\n";
637 if (defined $hsh{xsize} || defined $hsh{ysize}) {
638 unless ($self->img_set(%hsh)) {
639 $Imager::ERRSTR = $self->{ERRSTR};
643 elsif (defined $hsh{file} ||
646 defined $hsh{callback} ||
647 defined $hsh{readcb}) {
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{$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");
1369 if ( $input{'type'} eq 'jpeg' ) {
1370 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1371 if ( !defined($self->{IMG}) ) {
1372 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1374 $self->{DEBUG} && print "loading a jpeg file\n";
1378 my $allow_incomplete = $input{allow_incomplete};
1379 defined $allow_incomplete or $allow_incomplete = 0;
1381 if ( $input{'type'} eq 'tiff' ) {
1382 my $page = $input{'page'};
1383 defined $page or $page = 0;
1384 $self->{IMG}=i_readtiff_wiol( $IO, $allow_incomplete, $page );
1385 if ( !defined($self->{IMG}) ) {
1386 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1388 $self->{DEBUG} && print "loading a tiff file\n";
1392 if ( $input{'type'} eq 'pnm' ) {
1393 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1394 if ( !defined($self->{IMG}) ) {
1395 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1398 $self->{DEBUG} && print "loading a pnm file\n";
1402 if ( $input{'type'} eq 'png' ) {
1403 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1404 if ( !defined($self->{IMG}) ) {
1405 $self->{ERRSTR} = $self->_error_as_msg();
1408 $self->{DEBUG} && print "loading a png file\n";
1411 if ( $input{'type'} eq 'bmp' ) {
1412 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1413 if ( !defined($self->{IMG}) ) {
1414 $self->{ERRSTR}=$self->_error_as_msg();
1417 $self->{DEBUG} && print "loading a bmp file\n";
1420 if ( $input{'type'} eq 'gif' ) {
1421 if ($input{colors} && !ref($input{colors})) {
1422 # must be a reference to a scalar that accepts the colour map
1423 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1426 if ($input{'gif_consolidate'}) {
1427 if ($input{colors}) {
1429 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1431 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1435 $self->{IMG} =i_readgif_wiol( $IO );
1439 my $page = $input{'page'};
1440 defined $page or $page = 0;
1441 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1442 if ($self->{IMG} && $input{colors}) {
1443 ${ $input{colors} } =
1444 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1448 if ( !defined($self->{IMG}) ) {
1449 $self->{ERRSTR}=$self->_error_as_msg();
1452 $self->{DEBUG} && print "loading a gif file\n";
1455 if ( $input{'type'} eq 'tga' ) {
1456 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1457 if ( !defined($self->{IMG}) ) {
1458 $self->{ERRSTR}=$self->_error_as_msg();
1461 $self->{DEBUG} && print "loading a tga file\n";
1464 if ( $input{'type'} eq 'raw' ) {
1465 unless ( $input{xsize} && $input{ysize} ) {
1466 $self->_set_error('missing xsize or ysize parameter for raw');
1470 my $interleave = _first($input{raw_interleave}, $input{interleave});
1471 unless (defined $interleave) {
1472 my @caller = caller;
1473 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1476 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1477 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1479 $self->{IMG} = i_readraw_wiol( $IO,
1485 if ( !defined($self->{IMG}) ) {
1486 $self->{ERRSTR}=$self->_error_as_msg();
1489 $self->{DEBUG} && print "loading a raw file\n";
1495 sub register_reader {
1496 my ($class, %opts) = @_;
1499 or die "register_reader called with no type parameter\n";
1501 my $type = $opts{type};
1503 defined $opts{single} || defined $opts{multiple}
1504 or die "register_reader called with no single or multiple parameter\n";
1506 $readers{$type} = { };
1507 if ($opts{single}) {
1508 $readers{$type}{single} = $opts{single};
1510 if ($opts{multiple}) {
1511 $readers{$type}{multiple} = $opts{multiple};
1517 sub register_writer {
1518 my ($class, %opts) = @_;
1521 or die "register_writer called with no type parameter\n";
1523 my $type = $opts{type};
1525 defined $opts{single} || defined $opts{multiple}
1526 or die "register_writer called with no single or multiple parameter\n";
1528 $writers{$type} = { };
1529 if ($opts{single}) {
1530 $writers{$type}{single} = $opts{single};
1532 if ($opts{multiple}) {
1533 $writers{$type}{multiple} = $opts{multiple};
1544 grep($file_formats{$_}, keys %formats),
1545 qw(ico sgi), # formats not handled directly, but supplied with Imager
1556 grep($file_formats{$_}, keys %formats),
1557 qw(ico sgi), # formats not handled directly, but supplied with Imager
1563 # probes for an Imager::File::whatever module
1564 sub _reader_autoload {
1567 return if $formats{$type} || $readers{$type};
1569 return unless $type =~ /^\w+$/;
1571 my $file = "Imager/File/\U$type\E.pm";
1573 unless ($attempted_to_load{$file}) {
1575 ++$attempted_to_load{$file};
1579 # try to get a reader specific module
1580 my $file = "Imager/File/\U$type\EReader.pm";
1581 unless ($attempted_to_load{$file}) {
1583 ++$attempted_to_load{$file};
1591 # probes for an Imager::File::whatever module
1592 sub _writer_autoload {
1595 return if $formats{$type} || $readers{$type};
1597 return unless $type =~ /^\w+$/;
1599 my $file = "Imager/File/\U$type\E.pm";
1601 unless ($attempted_to_load{$file}) {
1603 ++$attempted_to_load{$file};
1607 # try to get a writer specific module
1608 my $file = "Imager/File/\U$type\EWriter.pm";
1609 unless ($attempted_to_load{$file}) {
1611 ++$attempted_to_load{$file};
1619 sub _fix_gif_positions {
1620 my ($opts, $opt, $msg, @imgs) = @_;
1622 my $positions = $opts->{'gif_positions'};
1624 for my $pos (@$positions) {
1625 my ($x, $y) = @$pos;
1626 my $img = $imgs[$index++];
1627 $img->settag(name=>'gif_left', value=>$x);
1628 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1630 $$msg .= "replaced with the gif_left and gif_top tags";
1635 gif_each_palette=>'gif_local_map',
1636 interlace => 'gif_interlace',
1637 gif_delays => 'gif_delay',
1638 gif_positions => \&_fix_gif_positions,
1639 gif_loop_count => 'gif_loop',
1642 # options that should be converted to colors
1643 my %color_opts = map { $_ => 1 } qw/i_background/;
1646 my ($self, $opts, $prefix, @imgs) = @_;
1648 for my $opt (keys %$opts) {
1650 if ($obsolete_opts{$opt}) {
1651 my $new = $obsolete_opts{$opt};
1652 my $msg = "Obsolete option $opt ";
1654 $new->($opts, $opt, \$msg, @imgs);
1657 $msg .= "replaced with the $new tag ";
1660 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1661 warn $msg if $warn_obsolete && $^W;
1663 next unless $tagname =~ /^\Q$prefix/;
1664 my $value = $opts->{$opt};
1665 if ($color_opts{$opt}) {
1666 $value = _color($value);
1668 $self->_set_error($Imager::ERRSTR);
1673 if (UNIVERSAL::isa($value, "Imager::Color")) {
1674 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1675 for my $img (@imgs) {
1676 $img->settag(name=>$tagname, value=>$tag);
1679 elsif (ref($value) eq 'ARRAY') {
1680 for my $i (0..$#$value) {
1681 my $val = $value->[$i];
1683 if (UNIVERSAL::isa($val, "Imager::Color")) {
1684 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1686 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1689 $self->_set_error("Unknown reference type " . ref($value) .
1690 " supplied in array for $opt");
1696 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1701 $self->_set_error("Unknown reference type " . ref($value) .
1702 " supplied for $opt");
1707 # set it as a tag for every image
1708 for my $img (@imgs) {
1709 $img->settag(name=>$tagname, value=>$value);
1717 # Write an image to file
1720 my %input=(jpegquality=>75,
1730 $self->_set_opts(\%input, "i_", $self)
1733 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1735 if (!$input{'type'} and $input{file}) {
1736 $input{'type'}=$FORMATGUESS->($input{file});
1738 if (!$input{'type'}) {
1739 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1743 _writer_autoload($input{type});
1746 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1747 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1750 $writers{$input{type}}{single}->($self, $IO, %input)
1754 if (!$formats{$input{'type'}}) {
1755 my $write_types = join ', ', sort Imager->write_types();
1756 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1760 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1763 if ($input{'type'} eq 'tiff') {
1764 $self->_set_opts(\%input, "tiff_", $self)
1766 $self->_set_opts(\%input, "exif_", $self)
1769 if (defined $input{class} && $input{class} eq 'fax') {
1770 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1771 $self->{ERRSTR} = $self->_error_as_msg();
1775 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1776 $self->{ERRSTR} = $self->_error_as_msg();
1780 } elsif ( $input{'type'} eq 'pnm' ) {
1781 $self->_set_opts(\%input, "pnm_", $self)
1783 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1784 $self->{ERRSTR} = $self->_error_as_msg();
1787 $self->{DEBUG} && print "writing a pnm file\n";
1788 } elsif ( $input{'type'} eq 'raw' ) {
1789 $self->_set_opts(\%input, "raw_", $self)
1791 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1792 $self->{ERRSTR} = $self->_error_as_msg();
1795 $self->{DEBUG} && print "writing a raw file\n";
1796 } elsif ( $input{'type'} eq 'png' ) {
1797 $self->_set_opts(\%input, "png_", $self)
1799 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1800 $self->{ERRSTR}='unable to write png image';
1803 $self->{DEBUG} && print "writing a png file\n";
1804 } elsif ( $input{'type'} eq 'jpeg' ) {
1805 $self->_set_opts(\%input, "jpeg_", $self)
1807 $self->_set_opts(\%input, "exif_", $self)
1809 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1810 $self->{ERRSTR} = $self->_error_as_msg();
1813 $self->{DEBUG} && print "writing a jpeg file\n";
1814 } elsif ( $input{'type'} eq 'bmp' ) {
1815 $self->_set_opts(\%input, "bmp_", $self)
1817 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1818 $self->{ERRSTR} = $self->_error_as_msg;
1821 $self->{DEBUG} && print "writing a bmp file\n";
1822 } elsif ( $input{'type'} eq 'tga' ) {
1823 $self->_set_opts(\%input, "tga_", $self)
1826 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1827 $self->{ERRSTR}=$self->_error_as_msg();
1830 $self->{DEBUG} && print "writing a tga file\n";
1831 } elsif ( $input{'type'} eq 'gif' ) {
1832 $self->_set_opts(\%input, "gif_", $self)
1834 # compatibility with the old interfaces
1835 if ($input{gifquant} eq 'lm') {
1836 $input{make_colors} = 'addi';
1837 $input{translate} = 'perturb';
1838 $input{perturb} = $input{lmdither};
1839 } elsif ($input{gifquant} eq 'gen') {
1840 # just pass options through
1842 $input{make_colors} = 'webmap'; # ignored
1843 $input{translate} = 'giflib';
1845 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1846 $self->{ERRSTR} = $self->_error_as_msg;
1852 if (exists $input{'data'}) {
1853 my $data = io_slurp($IO);
1855 $self->{ERRSTR}='Could not slurp from buffer';
1858 ${$input{data}} = $data;
1864 my ($class, $opts, @images) = @_;
1866 my $type = $opts->{type};
1868 if (!$type && $opts->{'file'}) {
1869 $type = $FORMATGUESS->($opts->{'file'});
1872 $class->_set_error('type parameter missing and not possible to guess from extension');
1875 # translate to ImgRaw
1876 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1877 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1880 $class->_set_opts($opts, "i_", @images)
1882 my @work = map $_->{IMG}, @images;
1884 _writer_autoload($type);
1887 if ($writers{$type} && $writers{$type}{multiple}) {
1888 ($IO, $file) = $class->_get_writer_io($opts, $type)
1891 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1895 if (!$formats{$type}) {
1896 my $write_types = join ', ', sort Imager->write_types();
1897 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1901 ($IO, $file) = $class->_get_writer_io($opts, $type)
1904 if ($type eq 'gif') {
1905 $class->_set_opts($opts, "gif_", @images)
1907 my $gif_delays = $opts->{gif_delays};
1908 local $opts->{gif_delays} = $gif_delays;
1909 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1910 # assume the caller wants the same delay for each frame
1911 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1913 unless (i_writegif_wiol($IO, $opts, @work)) {
1914 $class->_set_error($class->_error_as_msg());
1918 elsif ($type eq 'tiff') {
1919 $class->_set_opts($opts, "tiff_", @images)
1921 $class->_set_opts($opts, "exif_", @images)
1924 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1925 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1926 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1929 $res = i_writetiff_multi_wiol($IO, @work);
1932 $class->_set_error($class->_error_as_msg());
1938 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1943 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1949 if (exists $opts->{'data'}) {
1950 my $data = io_slurp($IO);
1952 Imager->_set_error('Could not slurp from buffer');
1955 ${$opts->{data}} = $data;
1960 # read multiple images from a file
1962 my ($class, %opts) = @_;
1964 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1967 my $type = $opts{'type'};
1969 $type = i_test_format_probe($IO, -1);
1972 if ($opts{file} && !$type) {
1974 $type = $FORMATGUESS->($opts{file});
1978 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1982 _reader_autoload($type);
1984 if ($readers{$type} && $readers{$type}{multiple}) {
1985 return $readers{$type}{multiple}->($IO, %opts);
1988 if ($type eq 'gif') {
1990 @imgs = i_readgif_multi_wiol($IO);
1993 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1997 $ERRSTR = _error_as_msg();
2001 elsif ($type eq 'tiff') {
2002 my @imgs = i_readtiff_multi_wiol($IO, -1);
2005 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2009 $ERRSTR = _error_as_msg();
2014 my $img = Imager->new;
2015 if ($img->read(%opts, io => $IO, type => $type)) {
2018 Imager->_set_error($img->errstr);
2024 # Destroy an Imager object
2028 # delete $instances{$self};
2029 if (defined($self->{IMG})) {
2030 # the following is now handled by the XS DESTROY method for
2031 # Imager::ImgRaw object
2032 # Re-enabling this will break virtual images
2033 # tested for in t/t020masked.t
2034 # i_img_destroy($self->{IMG});
2035 undef($self->{IMG});
2037 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2041 # Perform an inplace filter of an image
2042 # that is the image will be overwritten with the data
2048 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2050 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2052 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2053 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2056 if ($filters{$input{'type'}}{names}) {
2057 my $names = $filters{$input{'type'}}{names};
2058 for my $name (keys %$names) {
2059 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2060 $input{$name} = $names->{$name}{$input{$name}};
2064 if (defined($filters{$input{'type'}}{defaults})) {
2065 %hsh=( image => $self->{IMG},
2067 %{$filters{$input{'type'}}{defaults}},
2070 %hsh=( image => $self->{IMG},
2075 my @cs=@{$filters{$input{'type'}}{callseq}};
2078 if (!defined($hsh{$_})) {
2079 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2084 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2085 &{$filters{$input{'type'}}{callsub}}(%hsh);
2088 chomp($self->{ERRSTR} = $@);
2094 $self->{DEBUG} && print "callseq is: @cs\n";
2095 $self->{DEBUG} && print "matching callseq is: @b\n";
2100 sub register_filter {
2102 my %hsh = ( defaults => {}, @_ );
2105 or die "register_filter() with no type\n";
2106 defined $hsh{callsub}
2107 or die "register_filter() with no callsub\n";
2108 defined $hsh{callseq}
2109 or die "register_filter() with no callseq\n";
2111 exists $filters{$hsh{type}}
2114 $filters{$hsh{type}} = \%hsh;
2119 sub scale_calculate {
2122 my %opts = ('type'=>'max', @_);
2124 # none of these should be references
2125 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2126 if (defined $opts{$name} && ref $opts{$name}) {
2127 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2132 my ($x_scale, $y_scale);
2133 my $width = $opts{width};
2134 my $height = $opts{height};
2136 defined $width or $width = $self->getwidth;
2137 defined $height or $height = $self->getheight;
2140 unless (defined $width && defined $height) {
2141 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2146 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2147 $x_scale = $opts{'xscalefactor'};
2148 $y_scale = $opts{'yscalefactor'};
2150 elsif ($opts{'xscalefactor'}) {
2151 $x_scale = $opts{'xscalefactor'};
2152 $y_scale = $opts{'scalefactor'} || $x_scale;
2154 elsif ($opts{'yscalefactor'}) {
2155 $y_scale = $opts{'yscalefactor'};
2156 $x_scale = $opts{'scalefactor'} || $y_scale;
2159 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2162 # work out the scaling
2163 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2164 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2165 $opts{ypixels} / $height );
2166 if ($opts{'type'} eq 'min') {
2167 $x_scale = $y_scale = _min($xpix,$ypix);
2169 elsif ($opts{'type'} eq 'max') {
2170 $x_scale = $y_scale = _max($xpix,$ypix);
2172 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2177 $self->_set_error('invalid value for type parameter');
2180 } elsif ($opts{xpixels}) {
2181 $x_scale = $y_scale = $opts{xpixels} / $width;
2183 elsif ($opts{ypixels}) {
2184 $x_scale = $y_scale = $opts{ypixels}/$height;
2186 elsif ($opts{constrain} && ref $opts{constrain}
2187 && $opts{constrain}->can('constrain')) {
2188 # we've been passed an Image::Math::Constrain object or something
2189 # that looks like one
2191 (undef, undef, $scalefactor)
2192 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2193 unless ($scalefactor) {
2194 $self->_set_error('constrain method failed on constrain parameter');
2197 $x_scale = $y_scale = $scalefactor;
2200 my $new_width = int($x_scale * $width + 0.5);
2201 $new_width > 0 or $new_width = 1;
2202 my $new_height = int($y_scale * $height + 0.5);
2203 $new_height > 0 or $new_height = 1;
2205 return ($x_scale, $y_scale, $new_width, $new_height);
2209 # Scale an image to requested size and return the scaled version
2213 my %opts = (qtype=>'normal' ,@_);
2214 my $img = Imager->new();
2215 my $tmp = Imager->new();
2217 unless (defined wantarray) {
2218 my @caller = caller;
2219 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2223 unless ($self->{IMG}) {
2224 $self->_set_error('empty input image');
2228 my ($x_scale, $y_scale, $new_width, $new_height) =
2229 $self->scale_calculate(%opts)
2232 if ($opts{qtype} eq 'normal') {
2233 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2234 if ( !defined($tmp->{IMG}) ) {
2235 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2238 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2239 if ( !defined($img->{IMG}) ) {
2240 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2246 elsif ($opts{'qtype'} eq 'preview') {
2247 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2248 if ( !defined($img->{IMG}) ) {
2249 $self->{ERRSTR}='unable to scale image';
2254 elsif ($opts{'qtype'} eq 'mixing') {
2255 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2256 unless ($img->{IMG}) {
2257 $self->_set_error(Imager->_error_as_msg);
2263 $self->_set_error('invalid value for qtype parameter');
2268 # Scales only along the X axis
2272 my %opts = ( scalefactor=>0.5, @_ );
2274 unless (defined wantarray) {
2275 my @caller = caller;
2276 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2280 unless ($self->{IMG}) {
2281 $self->{ERRSTR} = 'empty input image';
2285 my $img = Imager->new();
2287 my $scalefactor = $opts{scalefactor};
2289 if ($opts{pixels}) {
2290 $scalefactor = $opts{pixels} / $self->getwidth();
2293 unless ($self->{IMG}) {
2294 $self->{ERRSTR}='empty input image';
2298 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2300 if ( !defined($img->{IMG}) ) {
2301 $self->{ERRSTR} = 'unable to scale image';
2308 # Scales only along the Y axis
2312 my %opts = ( scalefactor => 0.5, @_ );
2314 unless (defined wantarray) {
2315 my @caller = caller;
2316 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2320 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2322 my $img = Imager->new();
2324 my $scalefactor = $opts{scalefactor};
2326 if ($opts{pixels}) {
2327 $scalefactor = $opts{pixels} / $self->getheight();
2330 unless ($self->{IMG}) {
2331 $self->{ERRSTR} = 'empty input image';
2334 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2336 if ( !defined($img->{IMG}) ) {
2337 $self->{ERRSTR} = 'unable to scale image';
2344 # Transform returns a spatial transformation of the input image
2345 # this moves pixels to a new location in the returned image.
2346 # NOTE - should make a utility function to check transforms for
2351 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2353 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2355 # print Dumper(\%opts);
2358 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2360 eval ("use Affix::Infix2Postfix;");
2363 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2366 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2367 {op=>'-',trans=>'Sub'},
2368 {op=>'*',trans=>'Mult'},
2369 {op=>'/',trans=>'Div'},
2370 {op=>'-','type'=>'unary',trans=>'u-'},
2372 {op=>'func','type'=>'unary'}],
2373 'grouping'=>[qw( \( \) )],
2374 'func'=>[qw( sin cos )],
2379 @xt=$I2P->translate($opts{'xexpr'});
2380 @yt=$I2P->translate($opts{'yexpr'});
2382 $numre=$I2P->{'numre'};
2385 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2386 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2387 @{$opts{'parm'}}=@pt;
2390 # print Dumper(\%opts);
2392 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2393 $self->{ERRSTR}='transform: no xopcodes given.';
2397 @op=@{$opts{'xopcodes'}};
2399 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2400 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2403 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2409 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2410 $self->{ERRSTR}='transform: no yopcodes given.';
2414 @op=@{$opts{'yopcodes'}};
2416 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2417 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2420 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2425 if ( !exists $opts{'parm'}) {
2426 $self->{ERRSTR}='transform: no parameter arg given.';
2430 # print Dumper(\@ropx);
2431 # print Dumper(\@ropy);
2432 # print Dumper(\@ropy);
2434 my $img = Imager->new();
2435 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2436 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2442 my ($opts, @imgs) = @_;
2444 require "Imager/Expr.pm";
2446 $opts->{variables} = [ qw(x y) ];
2447 my ($width, $height) = @{$opts}{qw(width height)};
2449 $width ||= $imgs[0]->getwidth();
2450 $height ||= $imgs[0]->getheight();
2452 for my $img (@imgs) {
2453 $opts->{constants}{"w$img_num"} = $img->getwidth();
2454 $opts->{constants}{"h$img_num"} = $img->getheight();
2455 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2456 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2461 $opts->{constants}{w} = $width;
2462 $opts->{constants}{cx} = $width/2;
2465 $Imager::ERRSTR = "No width supplied";
2469 $opts->{constants}{h} = $height;
2470 $opts->{constants}{cy} = $height/2;
2473 $Imager::ERRSTR = "No height supplied";
2476 my $code = Imager::Expr->new($opts);
2478 $Imager::ERRSTR = Imager::Expr::error();
2481 my $channels = $opts->{channels} || 3;
2482 unless ($channels >= 1 && $channels <= 4) {
2483 return Imager->_set_error("channels must be an integer between 1 and 4");
2486 my $img = Imager->new();
2487 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2488 $channels, $code->code(),
2489 $code->nregs(), $code->cregs(),
2490 [ map { $_->{IMG} } @imgs ]);
2491 if (!defined $img->{IMG}) {
2492 $Imager::ERRSTR = Imager->_error_as_msg();
2503 unless ($self->{IMG}) {
2504 $self->{ERRSTR}='empty input image';
2507 unless ($opts{src} && $opts{src}->{IMG}) {
2508 $self->{ERRSTR}='empty input image for src';
2512 %opts = (src_minx => 0,
2514 src_maxx => $opts{src}->getwidth(),
2515 src_maxy => $opts{src}->getheight(),
2519 defined $tx or $tx = $opts{left};
2520 defined $tx or $tx = 0;
2523 defined $ty or $ty = $opts{top};
2524 defined $ty or $ty = 0;
2526 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2527 $opts{src_minx}, $opts{src_miny},
2528 $opts{src_maxx}, $opts{src_maxy})) {
2529 $self->_set_error($self->_error_as_msg());
2546 unless ($self->{IMG}) {
2547 $self->_set_error("compose: empty input image");
2551 unless ($opts{src}) {
2552 $self->_set_error("compose: src parameter missing");
2556 unless ($opts{src}{IMG}) {
2557 $self->_set_error("compose: src parameter empty image");
2560 my $src = $opts{src};
2562 my $left = $opts{left};
2563 defined $left or $left = $opts{tx};
2564 defined $left or $left = 0;
2566 my $top = $opts{top};
2567 defined $top or $top = $opts{ty};
2568 defined $top or $top = 0;
2570 my $src_left = $opts{src_left};
2571 defined $src_left or $src_left = $opts{src_minx};
2572 defined $src_left or $src_left = 0;
2574 my $src_top = $opts{src_top};
2575 defined $src_top or $src_top = $opts{src_miny};
2576 defined $src_top or $src_top = 0;
2578 my $width = $opts{width};
2579 if (!defined $width && defined $opts{src_maxx}) {
2580 $width = $opts{src_maxx} - $src_left;
2582 defined $width or $width = $src->getwidth() - $src_left;
2584 my $height = $opts{height};
2585 if (!defined $height && defined $opts{src_maxy}) {
2586 $height = $opts{src_maxy} - $src_top;
2588 defined $height or $height = $src->getheight() - $src_top;
2590 my $combine = $self->_combine($opts{combine}, 'normal');
2593 unless ($opts{mask}{IMG}) {
2594 $self->_set_error("compose: mask parameter empty image");
2598 my $mask_left = $opts{mask_left};
2599 defined $mask_left or $mask_left = $opts{mask_minx};
2600 defined $mask_left or $mask_left = 0;
2602 my $mask_top = $opts{mask_top};
2603 defined $mask_top or $mask_top = $opts{mask_miny};
2604 defined $mask_top or $mask_top = 0;
2606 i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2607 $left, $top, $src_left, $src_top,
2608 $mask_left, $mask_top, $width, $height,
2609 $combine, $opts{opacity})
2613 i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2614 $width, $height, $combine, $opts{opacity})
2624 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2626 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2627 $dir = $xlate{$opts{'dir'}};
2628 return $self if i_flipxy($self->{IMG}, $dir);
2636 unless (defined wantarray) {
2637 my @caller = caller;
2638 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2642 if (defined $opts{right}) {
2643 my $degrees = $opts{right};
2645 $degrees += 360 * int(((-$degrees)+360)/360);
2647 $degrees = $degrees % 360;
2648 if ($degrees == 0) {
2649 return $self->copy();
2651 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2652 my $result = Imager->new();
2653 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2657 $self->{ERRSTR} = $self->_error_as_msg();
2662 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2666 elsif (defined $opts{radians} || defined $opts{degrees}) {
2667 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2669 my $back = $opts{back};
2670 my $result = Imager->new;
2672 $back = _color($back);
2674 $self->_set_error(Imager->errstr);
2678 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2681 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2683 if ($result->{IMG}) {
2687 $self->{ERRSTR} = $self->_error_as_msg();
2692 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2697 sub matrix_transform {
2701 unless (defined wantarray) {
2702 my @caller = caller;
2703 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2707 if ($opts{matrix}) {
2708 my $xsize = $opts{xsize} || $self->getwidth;
2709 my $ysize = $opts{ysize} || $self->getheight;
2711 my $result = Imager->new;
2713 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2714 $opts{matrix}, $opts{back})
2718 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2726 $self->{ERRSTR} = "matrix parameter required";
2732 *yatf = \&matrix_transform;
2734 # These two are supported for legacy code only
2737 return Imager::Color->new(@_);
2741 return Imager::Color::set(@_);
2744 # Draws a box between the specified corner points.
2747 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2748 my $dflcl=i_color_new(255,255,255,255);
2749 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2751 if (exists $opts{'box'}) {
2752 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2753 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2754 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2755 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2758 if ($opts{filled}) {
2759 my $color = _color($opts{'color'});
2761 $self->{ERRSTR} = $Imager::ERRSTR;
2764 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2765 $opts{ymax}, $color);
2767 elsif ($opts{fill}) {
2768 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2769 # assume it's a hash ref
2770 require 'Imager/Fill.pm';
2771 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2772 $self->{ERRSTR} = $Imager::ERRSTR;
2776 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2777 $opts{ymax},$opts{fill}{fill});
2780 my $color = _color($opts{'color'});
2782 $self->{ERRSTR} = $Imager::ERRSTR;
2785 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2793 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2794 my $dflcl=i_color_new(255,255,255,255);
2795 my %opts=(color=>$dflcl,
2796 'r'=>_min($self->getwidth(),$self->getheight())/3,
2797 'x'=>$self->getwidth()/2,
2798 'y'=>$self->getheight()/2,
2799 'd1'=>0, 'd2'=>361, @_);
2802 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2803 # assume it's a hash ref
2804 require 'Imager/Fill.pm';
2805 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2806 $self->{ERRSTR} = $Imager::ERRSTR;
2810 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2811 $opts{'d2'}, $opts{fill}{fill});
2814 my $color = _color($opts{'color'});
2816 $self->{ERRSTR} = $Imager::ERRSTR;
2819 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2820 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2824 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2825 $opts{'d1'}, $opts{'d2'}, $color);
2831 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2832 # assume it's a hash ref
2833 require 'Imager/Fill.pm';
2834 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2835 $self->{ERRSTR} = $Imager::ERRSTR;
2839 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2840 $opts{'d2'}, $opts{fill}{fill});
2843 my $color = _color($opts{'color'});
2845 $self->{ERRSTR} = $Imager::ERRSTR;
2848 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2849 $opts{'d1'}, $opts{'d2'}, $color);
2856 # Draws a line from one point to the other
2857 # the endpoint is set if the endp parameter is set which it is by default.
2858 # to turn of the endpoint being set use endp=>0 when calling line.
2862 my $dflcl=i_color_new(0,0,0,0);
2863 my %opts=(color=>$dflcl,
2866 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2868 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2869 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2871 my $color = _color($opts{'color'});
2873 $self->{ERRSTR} = $Imager::ERRSTR;
2877 $opts{antialias} = $opts{aa} if defined $opts{aa};
2878 if ($opts{antialias}) {
2879 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2880 $color, $opts{endp});
2882 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2883 $color, $opts{endp});
2888 # Draws a line between an ordered set of points - It more or less just transforms this
2889 # into a list of lines.
2893 my ($pt,$ls,@points);
2894 my $dflcl=i_color_new(0,0,0,0);
2895 my %opts=(color=>$dflcl,@_);
2897 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2899 if (exists($opts{points})) { @points=@{$opts{points}}; }
2900 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2901 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2904 # print Dumper(\@points);
2906 my $color = _color($opts{'color'});
2908 $self->{ERRSTR} = $Imager::ERRSTR;
2911 $opts{antialias} = $opts{aa} if defined $opts{aa};
2912 if ($opts{antialias}) {
2915 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2922 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2932 my ($pt,$ls,@points);
2933 my $dflcl = i_color_new(0,0,0,0);
2934 my %opts = (color=>$dflcl, @_);
2936 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2938 if (exists($opts{points})) {
2939 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2940 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2943 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2944 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2947 if ($opts{'fill'}) {
2948 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2949 # assume it's a hash ref
2950 require 'Imager/Fill.pm';
2951 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2952 $self->{ERRSTR} = $Imager::ERRSTR;
2956 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2957 $opts{'fill'}{'fill'});
2960 my $color = _color($opts{'color'});
2962 $self->{ERRSTR} = $Imager::ERRSTR;
2965 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2972 # this the multipoint bezier curve
2973 # this is here more for testing that actual usage since
2974 # this is not a good algorithm. Usually the curve would be
2975 # broken into smaller segments and each done individually.
2979 my ($pt,$ls,@points);
2980 my $dflcl=i_color_new(0,0,0,0);
2981 my %opts=(color=>$dflcl,@_);
2983 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2985 if (exists $opts{points}) {
2986 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2987 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2990 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2991 $self->{ERRSTR}='Missing or invalid points.';
2995 my $color = _color($opts{'color'});
2997 $self->{ERRSTR} = $Imager::ERRSTR;
3000 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3006 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3009 unless (exists $opts{'x'} && exists $opts{'y'}) {
3010 $self->{ERRSTR} = "missing seed x and y parameters";
3014 if ($opts{border}) {
3015 my $border = _color($opts{border});
3017 $self->_set_error($Imager::ERRSTR);
3021 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3022 # assume it's a hash ref
3023 require Imager::Fill;
3024 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3025 $self->{ERRSTR} = $Imager::ERRSTR;
3029 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3030 $opts{fill}{fill}, $border);
3033 my $color = _color($opts{'color'});
3035 $self->{ERRSTR} = $Imager::ERRSTR;
3038 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3045 $self->{ERRSTR} = $self->_error_as_msg();
3051 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3052 # assume it's a hash ref
3053 require 'Imager/Fill.pm';
3054 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3055 $self->{ERRSTR} = $Imager::ERRSTR;
3059 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3062 my $color = _color($opts{'color'});
3064 $self->{ERRSTR} = $Imager::ERRSTR;
3067 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3073 $self->{ERRSTR} = $self->_error_as_msg();
3082 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
3084 unless (exists $opts{'x'} && exists $opts{'y'}) {
3085 $self->{ERRSTR} = 'missing x and y parameters';
3091 my $color = _color($opts{color})
3093 if (ref $x && ref $y) {
3094 unless (@$x == @$y) {
3095 $self->{ERRSTR} = 'length of x and y mismatch';
3099 if ($color->isa('Imager::Color')) {
3100 for my $i (0..$#{$opts{'x'}}) {
3101 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3106 for my $i (0..$#{$opts{'x'}}) {
3107 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3115 if ($color->isa('Imager::Color')) {
3116 i_ppix($self->{IMG}, $x, $y, $color)
3120 i_ppixf($self->{IMG}, $x, $y, $color)
3131 my %opts = ( "type"=>'8bit', @_);
3133 unless (exists $opts{'x'} && exists $opts{'y'}) {
3134 $self->{ERRSTR} = 'missing x and y parameters';
3140 if (ref $x && ref $y) {
3141 unless (@$x == @$y) {
3142 $self->{ERRSTR} = 'length of x and y mismatch';
3146 if ($opts{"type"} eq '8bit') {
3147 for my $i (0..$#{$opts{'x'}}) {
3148 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3152 for my $i (0..$#{$opts{'x'}}) {
3153 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3156 return wantarray ? @result : \@result;
3159 if ($opts{"type"} eq '8bit') {
3160 return i_get_pixel($self->{IMG}, $x, $y);
3163 return i_gpixf($self->{IMG}, $x, $y);
3172 my %opts = ( type => '8bit', x=>0, @_);
3174 $self->_valid_image or return;
3176 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3178 unless (defined $opts{'y'}) {
3179 $self->_set_error("missing y parameter");
3183 if ($opts{type} eq '8bit') {
3184 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3187 elsif ($opts{type} eq 'float') {
3188 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3191 elsif ($opts{type} eq 'index') {
3192 unless (i_img_type($self->{IMG})) {
3193 $self->_set_error("type => index only valid on paletted images");
3196 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3200 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3207 my %opts = ( x=>0, @_);
3209 $self->_valid_image or return;
3211 unless (defined $opts{'y'}) {
3212 $self->_set_error("missing y parameter");
3217 if (ref $opts{pixels} && @{$opts{pixels}}) {
3218 # try to guess the type
3219 if ($opts{pixels}[0]->isa('Imager::Color')) {
3220 $opts{type} = '8bit';
3222 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3223 $opts{type} = 'float';
3226 $self->_set_error("missing type parameter and could not guess from pixels");
3232 $opts{type} = '8bit';
3236 if ($opts{type} eq '8bit') {
3237 if (ref $opts{pixels}) {
3238 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3241 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3244 elsif ($opts{type} eq 'float') {
3245 if (ref $opts{pixels}) {
3246 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3249 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3252 elsif ($opts{type} eq 'index') {
3253 if (ref $opts{pixels}) {
3254 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3257 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3261 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3268 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3270 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3272 unless (defined $opts{'y'}) {
3273 $self->_set_error("missing y parameter");
3277 unless ($opts{channels}) {
3278 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3281 if ($opts{target}) {
3282 my $target = $opts{target};
3283 my $offset = $opts{offset};
3284 if ($opts{type} eq '8bit') {
3285 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3286 $opts{y}, @{$opts{channels}})
3288 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3289 return scalar(@samples);
3291 elsif ($opts{type} eq 'float') {
3292 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3293 $opts{y}, @{$opts{channels}});
3294 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3295 return scalar(@samples);
3297 elsif ($opts{type} =~ /^(\d+)bit$/) {
3301 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3302 $opts{y}, $bits, $target,
3303 $offset, @{$opts{channels}});
3304 unless (defined $count) {
3305 $self->_set_error(Imager->_error_as_msg);
3312 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3317 if ($opts{type} eq '8bit') {
3318 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3319 $opts{y}, @{$opts{channels}});
3321 elsif ($opts{type} eq 'float') {
3322 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3323 $opts{y}, @{$opts{channels}});
3325 elsif ($opts{type} =~ /^(\d+)bit$/) {
3329 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3330 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3335 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3343 my %opts = ( x => 0, offset => 0, @_ );
3345 unless ($self->{IMG}) {
3346 $self->_set_error('setsamples: empty input image');
3350 unless(defined $opts{data} && ref $opts{data}) {
3351 $self->_set_error('setsamples: data parameter missing or invalid');
3355 unless ($opts{channels}) {
3356 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3359 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3360 $self->_set_error('setsamples: type parameter missing or invalid');
3365 unless (defined $opts{width}) {
3366 $opts{width} = $self->getwidth() - $opts{x};
3369 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3370 $opts{channels}, $opts{data}, $opts{offset},
3372 unless (defined $count) {
3373 $self->_set_error(Imager->_error_as_msg);
3380 # make an identity matrix of the given size
3384 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3385 for my $c (0 .. ($size-1)) {
3386 $matrix->[$c][$c] = 1;
3391 # general function to convert an image
3393 my ($self, %opts) = @_;
3396 unless (defined wantarray) {
3397 my @caller = caller;
3398 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3402 # the user can either specify a matrix or preset
3403 # the matrix overrides the preset
3404 if (!exists($opts{matrix})) {
3405 unless (exists($opts{preset})) {
3406 $self->{ERRSTR} = "convert() needs a matrix or preset";
3410 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3411 # convert to greyscale, keeping the alpha channel if any
3412 if ($self->getchannels == 3) {
3413 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3415 elsif ($self->getchannels == 4) {
3416 # preserve the alpha channel
3417 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3422 $matrix = _identity($self->getchannels);
3425 elsif ($opts{preset} eq 'noalpha') {
3426 # strip the alpha channel
3427 if ($self->getchannels == 2 or $self->getchannels == 4) {
3428 $matrix = _identity($self->getchannels);
3429 pop(@$matrix); # lose the alpha entry
3432 $matrix = _identity($self->getchannels);
3435 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3437 $matrix = [ [ 1 ] ];
3439 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3440 $matrix = [ [ 0, 1 ] ];
3442 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3443 $matrix = [ [ 0, 0, 1 ] ];
3445 elsif ($opts{preset} eq 'alpha') {
3446 if ($self->getchannels == 2 or $self->getchannels == 4) {
3447 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3450 # the alpha is just 1 <shrug>
3451 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3454 elsif ($opts{preset} eq 'rgb') {
3455 if ($self->getchannels == 1) {
3456 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3458 elsif ($self->getchannels == 2) {
3459 # preserve the alpha channel
3460 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3463 $matrix = _identity($self->getchannels);
3466 elsif ($opts{preset} eq 'addalpha') {
3467 if ($self->getchannels == 1) {
3468 $matrix = _identity(2);
3470 elsif ($self->getchannels == 3) {
3471 $matrix = _identity(4);
3474 $matrix = _identity($self->getchannels);
3478 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3484 $matrix = $opts{matrix};
3487 my $new = Imager->new;
3488 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3489 unless ($new->{IMG}) {
3490 # most likely a bad matrix
3491 $self->{ERRSTR} = _error_as_msg();
3498 # general function to map an image through lookup tables
3501 my ($self, %opts) = @_;
3502 my @chlist = qw( red green blue alpha );
3504 if (!exists($opts{'maps'})) {
3505 # make maps from channel maps
3507 for $chnum (0..$#chlist) {
3508 if (exists $opts{$chlist[$chnum]}) {
3509 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3510 } elsif (exists $opts{'all'}) {
3511 $opts{'maps'}[$chnum] = $opts{'all'};
3515 if ($opts{'maps'} and $self->{IMG}) {
3516 i_map($self->{IMG}, $opts{'maps'} );
3522 my ($self, %opts) = @_;
3524 defined $opts{mindist} or $opts{mindist} = 0;
3526 defined $opts{other}
3527 or return $self->_set_error("No 'other' parameter supplied");
3528 defined $opts{other}{IMG}
3529 or return $self->_set_error("No image data in 'other' image");
3532 or return $self->_set_error("No image data");
3534 my $result = Imager->new;
3535 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3537 or return $self->_set_error($self->_error_as_msg());
3542 # destructive border - image is shrunk by one pixel all around
3545 my ($self,%opts)=@_;
3546 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3547 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3551 # Get the width of an image
3555 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3556 return (i_img_info($self->{IMG}))[0];
3559 # Get the height of an image
3563 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3564 return (i_img_info($self->{IMG}))[1];
3567 # Get number of channels in an image
3571 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3572 return i_img_getchannels($self->{IMG});
3579 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3580 return i_img_getmask($self->{IMG});
3588 if (!defined($self->{IMG})) {
3589 $self->{ERRSTR} = 'image is empty';
3592 unless (defined $opts{mask}) {
3593 $self->_set_error("mask parameter required");
3596 i_img_setmask( $self->{IMG} , $opts{mask} );
3601 # Get number of colors in an image
3605 my %opts=('maxcolors'=>2**30,@_);
3606 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3607 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3608 return ($rc==-1? undef : $rc);
3611 # Returns a reference to a hash. The keys are colour named (packed) and the
3612 # values are the number of pixels in this colour.
3613 sub getcolorusagehash {
3616 my %opts = ( maxcolors => 2**30, @_ );
3617 my $max_colors = $opts{maxcolors};
3618 unless (defined $max_colors && $max_colors > 0) {
3619 $self->_set_error('maxcolors must be a positive integer');
3623 unless (defined $self->{IMG}) {
3624 $self->_set_error('empty input image');
3628 my $channels= $self->getchannels;
3629 # We don't want to look at the alpha channel, because some gifs using it
3630 # doesn't define it for every colour (but only for some)
3631 $channels -= 1 if $channels == 2 or $channels == 4;
3633 my $height = $self->getheight;
3634 for my $y (0 .. $height - 1) {
3635 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3636 while (length $colors) {
3637 $color_use{ substr($colors, 0, $channels, '') }++;
3639 keys %color_use > $max_colors
3645 # This will return a ordered array of the colour usage. Kind of the sorted
3646 # version of the values of the hash returned by getcolorusagehash.
3647 # You might want to add safety checks and change the names, etc...
3651 my %opts = ( maxcolors => 2**30, @_ );
3652 my $max_colors = $opts{maxcolors};
3653 unless (defined $max_colors && $max_colors > 0) {
3654 $self->_set_error('maxcolors must be a positive integer');
3658 unless (defined $self->{IMG}) {
3659 $self->_set_error('empty input image');
3663 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3666 # draw string to an image
3670 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3672 my %input=('x'=>0, 'y'=>0, @_);
3673 defined($input{string}) or $input{string} = $input{text};
3675 unless(defined $input{string}) {
3676 $self->{ERRSTR}="missing required parameter 'string'";
3680 unless($input{font}) {
3681 $self->{ERRSTR}="missing required parameter 'font'";
3685 unless ($input{font}->draw(image=>$self, %input)) {
3697 unless ($self->{IMG}) {
3698 $self->{ERRSTR}='empty input image';
3707 my %input=('x'=>0, 'y'=>0, @_);
3708 $input{string}||=$input{text};
3710 unless(exists $input{string}) {
3711 $self->_set_error("missing required parameter 'string'");
3715 unless($input{font}) {
3716 $self->_set_error("missing required parameter 'font'");
3721 unless (@result = $input{font}->align(image=>$img, %input)) {
3725 return wantarray ? @result : $result[0];
3728 my @file_limit_names = qw/width height bytes/;
3730 sub set_file_limits {
3737 @values{@file_limit_names} = (0) x @file_limit_names;
3740 @values{@file_limit_names} = i_get_image_file_limits();
3743 for my $key (keys %values) {
3744 defined $opts{$key} and $values{$key} = $opts{$key};
3747 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3750 sub get_file_limits {
3751 i_get_image_file_limits();
3754 # Shortcuts that can be exported
3756 sub newcolor { Imager::Color->new(@_); }
3757 sub newfont { Imager::Font->new(@_); }
3758 sub NCF { Imager::Color::Float->new(@_) }
3760 *NC=*newcolour=*newcolor;
3767 #### Utility routines
3770 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3774 my ($self, $msg) = @_;
3777 $self->{ERRSTR} = $msg;
3785 # Default guess for the type of an image from extension
3787 sub def_guess_type {
3790 $ext=($name =~ m/\.([^\.]+)$/)[0];
3791 return 'tiff' if ($ext =~ m/^tiff?$/);
3792 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3793 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3794 return 'png' if ($ext eq "png");
3795 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3796 return 'tga' if ($ext eq "tga");
3797 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3798 return 'gif' if ($ext eq "gif");
3799 return 'raw' if ($ext eq "raw");
3800 return lc $ext; # best guess
3805 return @combine_types;
3808 # get the minimum of a list
3812 for(@_) { if ($_<$mx) { $mx=$_; }}
3816 # get the maximum of a list
3820 for(@_) { if ($_>$mx) { $mx=$_; }}
3824 # string stuff for iptc headers
3828 $str = substr($str,3);
3829 $str =~ s/[\n\r]//g;
3836 # A little hack to parse iptc headers.
3841 my($caption,$photogr,$headln,$credit);
3843 my $str=$self->{IPTCRAW};
3848 @ar=split(/8BIM/,$str);
3853 @sar=split(/\034\002/);
3854 foreach $item (@sar) {
3855 if ($item =~ m/^x/) {
3856 $caption = _clean($item);
3859 if ($item =~ m/^P/) {
3860 $photogr = _clean($item);
3863 if ($item =~ m/^i/) {
3864 $headln = _clean($item);
3867 if ($item =~ m/^n/) {
3868 $credit = _clean($item);
3874 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3881 or die "Only C language supported";
3883 require Imager::ExtUtils;
3884 return Imager::ExtUtils->inline_config;
3887 # threads shouldn't try to close raw Imager objects
3888 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3892 # Below is the stub of documentation for your module. You better edit it!
3896 Imager - Perl extension for Generating 24 bit Images
3906 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3911 # see Imager::Files for information on the read() method
3912 my $im = Imager->new(file=>$file)
3913 or die Imager->errstr();
3915 $file =~ s/\.[^.]*$//;
3917 # Create smaller version
3918 # documented in Imager::Transformations
3919 my $thumb = $img->scale(scalefactor=>.3);
3921 # Autostretch individual channels
3922 $thumb->filter(type=>'autolevels');
3924 # try to save in one of these formats
3927 for $format ( qw( png gif jpeg tiff ppm ) ) {
3928 # Check if given format is supported
3929 if ($Imager::formats{$format}) {
3930 $file.="_low.$format";
3931 print "Storing image as: $file\n";
3932 # documented in Imager::Files
3933 $thumb->write(file=>$file) or
3941 Imager is a module for creating and altering images. It can read and
3942 write various image formats, draw primitive shapes like lines,and
3943 polygons, blend multiple images together in various ways, scale, crop,
3944 render text and more.
3946 =head2 Overview of documentation
3952 Imager - This document - Synopsis, Example, Table of Contents and
3957 L<Imager::Tutorial> - a brief introduction to Imager.
3961 L<Imager::Cookbook> - how to do various things with Imager.
3965 L<Imager::ImageTypes> - Basics of constructing image objects with
3966 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3967 8/16/double bits/channel, color maps, channel masks, image tags, color
3968 quantization. Also discusses basic image information methods.
3972 L<Imager::Files> - IO interaction, reading/writing images, format
3977 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3982 L<Imager::Color> - Color specification.
3986 L<Imager::Fill> - Fill pattern specification.
3990 L<Imager::Font> - General font rendering, bounding boxes and font
3995 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3996 blending, pasting, convert and map.
4000 L<Imager::Engines> - Programmable transformations through
4001 C<transform()>, C<transform2()> and C<matrix_transform()>.
4005 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4010 L<Imager::Expr> - Expressions for evaluation engine used by
4015 L<Imager::Matrix2d> - Helper class for affine transformations.
4019 L<Imager::Fountain> - Helper for making gradient profiles.
4023 L<Imager::API> - using Imager's C API
4027 L<Imager::APIRef> - API function reference
4031 L<Imager::Inline> - using Imager's C API from Inline::C
4035 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4039 =head2 Basic Overview
4041 An Image object is created with C<$img = Imager-E<gt>new()>.
4044 $img=Imager->new(); # create empty image
4045 $img->read(file=>'lena.png',type=>'png') or # read image from file
4046 die $img->errstr(); # give an explanation
4047 # if something failed
4049 or if you want to create an empty image:
4051 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4053 This example creates a completely black image of width 400 and height
4056 =head1 ERROR HANDLING
4058 In general a method will return false when it fails, if it does use
4059 the errstr() method to find out why:
4065 Returns the last error message in that context.
4067 If the last error you received was from calling an object method, such
4068 as read, call errstr() as an object method to find out why:
4070 my $image = Imager->new;
4071 $image->read(file => 'somefile.gif')
4072 or die $image->errstr;
4074 If it was a class method then call errstr() as a class method:
4076 my @imgs = Imager->read_multi(file => 'somefile.gif')
4077 or die Imager->errstr;
4079 Note that in some cases object methods are implemented in terms of
4080 class methods so a failing object method may set both.
4084 The C<Imager-E<gt>new> method is described in detail in
4085 L<Imager::ImageTypes>.
4089 Where to find information on methods for Imager class objects.
4091 addcolors() - L<Imager::ImageTypes/addcolors> - add colors to a
4094 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4096 align_string() - L<Imager::Draw/align_string> - draw text aligned on a
4099 arc() - L<Imager::Draw/arc> - draw a filled arc
4101 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4104 box() - L<Imager::Draw/box> - draw a filled or outline box.
4106 circle() - L<Imager::Draw/circle> - draw a filled circle
4108 colorcount() - L<Imager::Draw/colorcount> - the number of colors in an
4109 image's palette (paletted images only)
4111 combines() - L<Imager::Draw/combines> - return a list of the different
4112 combine type keywords
4114 compose() - L<Imager::Transformations/compose> - compose one image
4117 convert() - L<Imager::Transformations/"Color transformations"> -
4118 transform the color space
4120 copy() - L<Imager::Transformations/copy> - make a duplicate of an
4123 crop() - L<Imager::Transformations/crop> - extract part of an image
4125 def_guess_type() - L<Imager::Files/def_guess_type> - default function
4126 used to guess the output file format based on the output filename
4128 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4130 difference() - L<Imager::Filters/"Image Difference"> - produce a
4131 difference images from two input images.
4133 errstr() - L<"Basic Overview"> - the error from the last failed
4136 filter() - L<Imager::Filters> - image filtering
4138 findcolor() - L<Imager::ImageTypes/findcolor> - search the image
4139 palette, if it has one
4141 flip() - L<Imager::Transformations/flip> - flip an image, vertically,
4144 flood_fill() - L<Imager::Draw/flood_fill> - fill an enclosed or same
4147 getchannels() - L<Imager::ImageTypes/getchannels> - the number of
4148 samples per pixel for an image
4150 getcolorcount() - L<Imager::ImageTypes/getcolorcount> - the number of
4151 different colors used by an image (works for direct color images)
4153 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4154 palette, if it has one
4156 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4158 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4160 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4162 getheight() - L<Imager::ImageTypes/getwidth> - height of the image in
4165 getmask() - L<Imager::ImageTypes/getmask> - write mask for the image
4167 getpixel() - L<Imager::Draw/getpixel> - retrieve one or more pixel
4170 getsamples() - L<Imager::Draw/getsamples> - retrieve samples from a
4171 row or subrow of pixels.
4173 getscanline() - L<Imager::Draw/getscanline> - retrieve colors for a
4174 row or subrow of pixels.
4176 getwidth() - L<Imager::ImageTypes/getwidth> - width of the image in
4179 img_set() - L<Imager::ImageTypes/img_set> - re-use an Imager object
4182 init() - L<Imager::ImageTypes/init>
4184 is_bilevel() - L<Imager::ImageTypes/is_bilevel> - returns whether
4185 image write functions should write the image in their bi-level (blank
4186 and white, no grey levels) format
4188 line() - L<Imager::Draw/line> - draw an interval
4190 load_plugin() - L<Imager::Filters/load_plugin>
4192 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4195 masked() - L<Imager::ImageTypes/masked> - make a masked image
4197 matrix_transform() - L<Imager::Engines/matrix_transform>
4199 maxcolors() - L<Imager::ImageTypes/maxcolors>
4201 NC() - L<Imager::Handy/NC>
4203 NCF() - L<Imager::Handy/NCF>
4205 new() - L<Imager::ImageTypes/new>
4207 newcolor() - L<Imager::Handy/newcolor>
4209 newcolour() - L<Imager::Handy/newcolour>
4211 newfont() - L<Imager::Handy/newfont>
4213 NF() - L<Imager::Handy/NF>
4215 open() - L<Imager::Files> - an alias for read()
4217 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4220 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4222 polygon() - L<Imager::Draw/polygon>
4224 polyline() - L<Imager::Draw/polyline>
4226 read() - L<Imager::Files> - read a single image from an image file
4228 read_multi() - L<Imager::Files> - read multiple images from an image
4231 read_types() - L<Imager::Files/read_types> - list image types Imager
4234 register_filter() - L<Imager::Filters/register_filter>
4236 register_reader() - L<Imager::Files/register_reader>
4238 register_writer() - L<Imager::Files/register_writer>
4240 rotate() - L<Imager::Transformations/rotate>
4242 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4243 image and use the alpha channel
4245 scale() - L<Imager::Transformations/scale>
4247 scale_calculate() - L<Imager::Transformations/scale_calculate>
4249 scaleX() - L<Imager::Transformations/scaleX>
4251 scaleY() - L<Imager::Transformations/scaleY>
4253 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4256 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4258 setmask() - L<Imager::ImageTypes/setmask>
4260 setpixel() - L<Imager::Draw/setpixel>
4262 setsamples() - L<Imager::Draw/setsamples>
4264 setscanline() - L<Imager::Draw/setscanline>
4266 settag() - L<Imager::ImageTypes/settag>
4268 string() - L<Imager::Draw/string> - draw text on an image
4270 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4272 to_paletted() - L<Imager::ImageTypes/to_paletted>
4274 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4276 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4278 transform() - L<Imager::Engines/"transform">
4280 transform2() - L<Imager::Engines/"transform2">
4282 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4284 unload_plugin() - L<Imager::Filters/unload_plugin>
4286 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4289 write() - L<Imager::Files> - write an image to a file
4291 write_multi() - L<Imager::Files> - write multiple image to an image
4294 write_types() - L<Imager::Files/read_types> - list image types Imager
4297 =head1 CONCEPT INDEX
4299 animated GIF - L<Imager::Files/"Writing an animated GIF">
4301 aspect ratio - L<Imager::ImageTypes/i_xres>,
4302 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4304 blend - alpha blending one image onto another
4305 L<Imager::Transformations/rubthrough>
4307 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4309 boxes, drawing - L<Imager::Draw/box>
4311 changes between image - L<Imager::Filters/"Image Difference">
4313 color - L<Imager::Color>
4315 color names - L<Imager::Color>, L<Imager::Color::Table>
4317 combine modes - L<Imager::Draw/"Combine Types">
4319 compare images - L<Imager::Filters/"Image Difference">
4321 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4323 convolution - L<Imager::Filters/conv>
4325 cropping - L<Imager::Transformations/crop>
4327 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4329 C<diff> images - L<Imager::Filters/"Image Difference">
4331 dpi - L<Imager::ImageTypes/i_xres>,
4332 L<Imager::Cookbook/"Image spatial resolution">
4334 drawing boxes - L<Imager::Draw/box>
4336 drawing lines - L<Imager::Draw/line>
4338 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4340 error message - L<"ERROR HANDLING">
4342 files, font - L<Imager::Font>
4344 files, image - L<Imager::Files>
4346 filling, types of fill - L<Imager::Fill>
4348 filling, boxes - L<Imager::Draw/box>
4350 filling, flood fill - L<Imager::Draw/flood_fill>
4352 flood fill - L<Imager::Draw/flood_fill>
4354 fonts - L<Imager::Font>
4356 fonts, drawing with - L<Imager::Draw/string>,
4357 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4359 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4361 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4363 fountain fill - L<Imager::Fill/"Fountain fills">,
4364 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4365 L<Imager::Filters/gradgen>
4367 GIF files - L<Imager::Files/"GIF">
4369 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4371 gradient fill - L<Imager::Fill/"Fountain fills">,
4372 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4373 L<Imager::Filters/gradgen>
4375 grayscale, convert image to - L<Imager::Transformations/convert>
4377 guassian blur - L<Imager::Filters/guassian>
4379 hatch fills - L<Imager::Fill/"Hatched fills">
4381 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4383 invert image - L<Imager::Filters/hardinvert>
4385 JPEG - L<Imager::Files/"JPEG">
4387 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4389 lines, drawing - L<Imager::Draw/line>
4391 matrix - L<Imager::Matrix2d>,
4392 L<Imager::Transformations/"Matrix Transformations">,
4393 L<Imager::Font/transform>
4395 metadata, image - L<Imager::ImageTypes/"Tags">
4397 mosaic - L<Imager::Filters/mosaic>
4399 noise, filter - L<Imager::Filters/noise>
4401 noise, rendered - L<Imager::Filters/turbnoise>,
4402 L<Imager::Filters/radnoise>
4404 paste - L<Imager::Transformations/paste>,
4405 L<Imager::Transformations/rubthrough>
4407 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4408 L<Imager::ImageTypes/new>
4410 posterize - L<Imager::Filters/postlevels>
4412 png files - L<Imager::Files>, L<Imager::Files/"PNG">
4414 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
4416 rectangles, drawing - L<Imager::Draw/box>
4418 resizing an image - L<Imager::Transformations/scale>,
4419 L<Imager::Transformations/crop>
4421 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4423 saving an image - L<Imager::Files>
4425 scaling - L<Imager::Transformations/scale>
4427 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4429 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4431 size, image - L<Imager::ImageTypes/getwidth>,
4432 L<Imager::ImageTypes/getheight>
4434 size, text - L<Imager::Font/bounding_box>
4436 tags, image metadata - L<Imager::ImageTypes/"Tags">
4438 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4439 L<Imager::Font::Wrap>
4441 text, wrapping text in an area - L<Imager::Font::Wrap>
4443 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4445 tiles, color - L<Imager::Filters/mosaic>
4447 unsharp mask - L<Imager::Filters/unsharpmask>
4449 watermark - L<Imager::Filters/watermark>
4451 writing an image to a file - L<Imager::Files>
4455 Imager doesn't support perl threads.
4457 Imager has limited code to prevent double frees if you create images,
4458 colors etc, and then create a thread, but has no code to prevent two
4459 threads entering Imager's error handling code, and none is likely to
4464 The best place to get help with Imager is the mailing list.
4466 To subscribe send a message with C<subscribe> in the body to:
4468 imager-devel+request@molar.is
4474 L<http://www.molar.is/en/lists/imager-devel/>
4478 where you can also find the mailing list archive.
4480 You can report bugs by pointing your browser at:
4484 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4488 or by sending an email to:
4492 bug-Imager@rt.cpan.org
4496 Please remember to include the versions of Imager, perl, supporting
4497 libraries, and any relevant code. If you have specific images that
4498 cause the problems, please include those too.
4500 If you don't want to publish your email address on a mailing list you
4501 can use CPAN::Forum:
4503 http://www.cpanforum.com/dist/Imager
4505 You will need to register to post.
4507 =head1 CONTRIBUTING TO IMAGER
4513 If you like or dislike Imager, you can add a public review of Imager
4516 http://cpanratings.perl.org/dist/Imager
4518 This requires a Bitcard Account (http://www.bitcard.org).
4520 You can also send email to the maintainer below.
4522 If you send me a bug report via email, it will be copied to RT.
4526 I accept patches, preferably against the main branch in subversion.
4527 You should include an explanation of the reason for why the patch is
4530 Your patch should include regression tests where possible, otherwise
4531 it will be delayed until I get a chance to write them.
4535 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4537 Arnar M. Hrafnkelsson is the original author of Imager.
4539 Many others have contributed to Imager, please see the README for a
4544 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4545 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4546 L<Imager::Font>(3), L<Imager::Transformations>(3),
4547 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4548 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4550 L<http://imager.perl.org/>
4552 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4554 Other perl imaging modules include:
4556 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).