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 defined $hsh{data}) {
649 # allow $img = Imager->new(file => $filename)
652 # type is already used as a parameter to new(), rename it for the
654 if ($hsh{filetype}) {
655 $extras{type} = $hsh{filetype};
657 unless ($self->read(%hsh, %extras)) {
658 $Imager::ERRSTR = $self->{ERRSTR};
666 # Copy an entire image with no changes
667 # - if an image has magic the copy of it will not be magical
671 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
673 unless (defined wantarray) {
675 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
679 my $newcopy=Imager->new();
680 $newcopy->{IMG} = i_copy($self->{IMG});
689 unless ($self->{IMG}) {
690 $self->_set_error('empty input image');
693 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
694 my $src = $input{img} || $input{src};
696 $self->_set_error("no source image");
699 $input{left}=0 if $input{left} <= 0;
700 $input{top}=0 if $input{top} <= 0;
702 my($r,$b)=i_img_info($src->{IMG});
703 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
704 my ($src_right, $src_bottom);
705 if ($input{src_coords}) {
706 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
709 if (defined $input{src_maxx}) {
710 $src_right = $input{src_maxx};
712 elsif (defined $input{width}) {
713 if ($input{width} <= 0) {
714 $self->_set_error("paste: width must me positive");
717 $src_right = $src_left + $input{width};
722 if (defined $input{src_maxy}) {
723 $src_bottom = $input{src_maxy};
725 elsif (defined $input{height}) {
726 if ($input{height} < 0) {
727 $self->_set_error("paste: height must be positive");
730 $src_bottom = $src_top + $input{height};
737 $src_right > $r and $src_right = $r;
738 $src_bottom > $b and $src_bottom = $b;
740 if ($src_right <= $src_left
741 || $src_bottom < $src_top) {
742 $self->_set_error("nothing to paste");
746 i_copyto($self->{IMG}, $src->{IMG},
747 $src_left, $src_top, $src_right, $src_bottom,
748 $input{left}, $input{top});
750 return $self; # What should go here??
753 # Crop an image - i.e. return a new image that is smaller
757 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
759 unless (defined wantarray) {
761 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
767 my ($w, $h, $l, $r, $b, $t) =
768 @hsh{qw(width height left right bottom top)};
770 # work through the various possibilities
775 elsif (!defined $r) {
776 $r = $self->getwidth;
788 $l = int(0.5+($self->getwidth()-$w)/2);
793 $r = $self->getwidth;
799 elsif (!defined $b) {
800 $b = $self->getheight;
812 $t=int(0.5+($self->getheight()-$h)/2);
817 $b = $self->getheight;
820 ($l,$r)=($r,$l) if $l>$r;
821 ($t,$b)=($b,$t) if $t>$b;
824 $r > $self->getwidth and $r = $self->getwidth;
826 $b > $self->getheight and $b = $self->getheight;
828 if ($l == $r || $t == $b) {
829 $self->_set_error("resulting image would have no content");
832 if( $r < $l or $b < $t ) {
833 $self->_set_error("attempting to crop outside of the image");
836 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
838 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
843 my ($self, %opts) = @_;
845 $self->{IMG} or return $self->_set_error("Not a valid image");
847 my $x = $opts{xsize} || $self->getwidth;
848 my $y = $opts{ysize} || $self->getheight;
849 my $channels = $opts{channels} || $self->getchannels;
851 my $out = Imager->new;
852 if ($channels == $self->getchannels) {
853 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
856 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
858 unless ($out->{IMG}) {
859 $self->{ERRSTR} = $self->_error_as_msg;
866 # Sets an image to a certain size and channel number
867 # if there was previously data in the image it is discarded
872 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
874 if (defined($self->{IMG})) {
875 # let IIM_DESTROY destroy it, it's possible this image is
876 # referenced from a virtual image (like masked)
877 #i_img_destroy($self->{IMG});
881 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
882 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
883 $hsh{maxcolors} || 256);
885 elsif ($hsh{bits} eq 'double') {
886 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
888 elsif ($hsh{bits} == 16) {
889 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
892 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
896 unless ($self->{IMG}) {
897 $self->{ERRSTR} = Imager->_error_as_msg();
904 # created a masked version of the current image
908 $self or return undef;
909 my %opts = (left => 0,
911 right => $self->getwidth,
912 bottom => $self->getheight,
914 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
916 my $result = Imager->new;
917 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
918 $opts{top}, $opts{right} - $opts{left},
919 $opts{bottom} - $opts{top});
920 # keep references to the mask and base images so they don't
922 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
927 # convert an RGB image into a paletted image
931 if (@_ != 1 && !ref $_[0]) {
938 unless (defined wantarray) {
940 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
944 my $result = Imager->new;
945 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
947 #print "Type ", i_img_type($result->{IMG}), "\n";
949 if ($result->{IMG}) {
953 $self->{ERRSTR} = $self->_error_as_msg;
958 # convert a paletted (or any image) to an 8-bit/channel RGB images
963 unless (defined wantarray) {
965 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
970 $result = Imager->new;
971 $result->{IMG} = i_img_to_rgb($self->{IMG})
978 # convert a paletted (or any image) to an 8-bit/channel RGB images
983 unless (defined wantarray) {
985 warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
990 $result = Imager->new;
991 $result->{IMG} = i_img_to_rgb16($self->{IMG})
1000 my %opts = (colors=>[], @_);
1002 unless ($self->{IMG}) {
1003 $self->_set_error("empty input image");
1007 my @colors = @{$opts{colors}}
1010 for my $color (@colors) {
1011 $color = _color($color);
1013 $self->_set_error($Imager::ERRSTR);
1018 return i_addcolors($self->{IMG}, @colors);
1023 my %opts = (start=>0, colors=>[], @_);
1025 unless ($self->{IMG}) {
1026 $self->_set_error("empty input image");
1030 my @colors = @{$opts{colors}}
1033 for my $color (@colors) {
1034 $color = _color($color);
1036 $self->_set_error($Imager::ERRSTR);
1041 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1047 if (!exists $opts{start} && !exists $opts{count}) {
1050 $opts{count} = $self->colorcount;
1052 elsif (!exists $opts{count}) {
1055 elsif (!exists $opts{start}) {
1060 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1064 i_colorcount($_[0]{IMG});
1068 i_maxcolors($_[0]{IMG});
1074 $opts{color} or return undef;
1076 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1081 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1082 if ($bits && $bits == length(pack("d", 1)) * 8) {
1091 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1097 $self->{IMG} and i_img_virtual($self->{IMG});
1103 $self->{IMG} or return;
1105 return i_img_is_monochrome($self->{IMG});
1109 my ($self, %opts) = @_;
1111 $self->{IMG} or return;
1113 if (defined $opts{name}) {
1117 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1118 push @result, (i_tags_get($self->{IMG}, $found))[1];
1121 return wantarray ? @result : $result[0];
1123 elsif (defined $opts{code}) {
1127 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1128 push @result, (i_tags_get($self->{IMG}, $found))[1];
1135 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1138 return i_tags_count($self->{IMG});
1147 return -1 unless $self->{IMG};
1149 if (defined $opts{value}) {
1150 if ($opts{value} =~ /^\d+$/) {
1152 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1155 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1158 elsif (defined $opts{data}) {
1159 # force addition as a string
1160 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1163 $self->{ERRSTR} = "No value supplied";
1167 elsif ($opts{code}) {
1168 if (defined $opts{value}) {
1169 if ($opts{value} =~ /^\d+$/) {
1171 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1174 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1177 elsif (defined $opts{data}) {
1178 # force addition as a string
1179 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1182 $self->{ERRSTR} = "No value supplied";
1195 return 0 unless $self->{IMG};
1197 if (defined $opts{'index'}) {
1198 return i_tags_delete($self->{IMG}, $opts{'index'});
1200 elsif (defined $opts{name}) {
1201 return i_tags_delbyname($self->{IMG}, $opts{name});
1203 elsif (defined $opts{code}) {
1204 return i_tags_delbycode($self->{IMG}, $opts{code});
1207 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1213 my ($self, %opts) = @_;
1216 $self->deltag(name=>$opts{name});
1217 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1219 elsif (defined $opts{code}) {
1220 $self->deltag(code=>$opts{code});
1221 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1229 sub _get_reader_io {
1230 my ($self, $input) = @_;
1233 return $input->{io}, undef;
1235 elsif ($input->{fd}) {
1236 return io_new_fd($input->{fd});
1238 elsif ($input->{fh}) {
1239 my $fd = fileno($input->{fh});
1240 unless (defined $fd) {
1241 $self->_set_error("Handle in fh option not opened");
1244 return io_new_fd($fd);
1246 elsif ($input->{file}) {
1247 my $file = IO::File->new($input->{file}, "r");
1249 $self->_set_error("Could not open $input->{file}: $!");
1253 return (io_new_fd(fileno($file)), $file);
1255 elsif ($input->{data}) {
1256 return io_new_buffer($input->{data});
1258 elsif ($input->{callback} || $input->{readcb}) {
1259 if (!$input->{seekcb}) {
1260 $self->_set_error("Need a seekcb parameter");
1262 if ($input->{maxbuffer}) {
1263 return io_new_cb($input->{writecb},
1264 $input->{callback} || $input->{readcb},
1265 $input->{seekcb}, $input->{closecb},
1266 $input->{maxbuffer});
1269 return io_new_cb($input->{writecb},
1270 $input->{callback} || $input->{readcb},
1271 $input->{seekcb}, $input->{closecb});
1275 $self->_set_error("file/fd/fh/data/callback parameter missing");
1280 sub _get_writer_io {
1281 my ($self, $input, $type) = @_;
1284 return $input->{io};
1286 elsif ($input->{fd}) {
1287 return io_new_fd($input->{fd});
1289 elsif ($input->{fh}) {
1290 my $fd = fileno($input->{fh});
1291 unless (defined $fd) {
1292 $self->_set_error("Handle in fh option not opened");
1296 my $oldfh = select($input->{fh});
1297 # flush anything that's buffered, and make sure anything else is flushed
1300 return io_new_fd($fd);
1302 elsif ($input->{file}) {
1303 my $fh = new IO::File($input->{file},"w+");
1305 $self->_set_error("Could not open file $input->{file}: $!");
1308 binmode($fh) or die;
1309 return (io_new_fd(fileno($fh)), $fh);
1311 elsif ($input->{data}) {
1312 return io_new_bufchain();
1314 elsif ($input->{callback} || $input->{writecb}) {
1315 if ($input->{maxbuffer}) {
1316 return io_new_cb($input->{callback} || $input->{writecb},
1318 $input->{seekcb}, $input->{closecb},
1319 $input->{maxbuffer});
1322 return io_new_cb($input->{callback} || $input->{writecb},
1324 $input->{seekcb}, $input->{closecb});
1328 $self->_set_error("file/fd/fh/data/callback parameter missing");
1333 # Read an image from file
1339 if (defined($self->{IMG})) {
1340 # let IIM_DESTROY do the destruction, since the image may be
1341 # referenced from elsewhere
1342 #i_img_destroy($self->{IMG});
1343 undef($self->{IMG});
1346 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1348 unless ($input{'type'}) {
1349 $input{'type'} = i_test_format_probe($IO, -1);
1352 unless ($input{'type'}) {
1353 $self->_set_error('type parameter missing and not possible to guess from extension');
1357 _reader_autoload($input{type});
1359 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1360 return $readers{$input{type}}{single}->($self, $IO, %input);
1363 unless ($formats{$input{'type'}}) {
1364 my $read_types = join ', ', sort Imager->read_types();
1365 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1370 if ( $input{'type'} eq 'jpeg' ) {
1371 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1372 if ( !defined($self->{IMG}) ) {
1373 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1375 $self->{DEBUG} && print "loading a jpeg file\n";
1379 my $allow_incomplete = $input{allow_incomplete};
1380 defined $allow_incomplete or $allow_incomplete = 0;
1382 if ( $input{'type'} eq 'tiff' ) {
1383 my $page = $input{'page'};
1384 defined $page or $page = 0;
1385 $self->{IMG}=i_readtiff_wiol( $IO, $allow_incomplete, $page );
1386 if ( !defined($self->{IMG}) ) {
1387 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1389 $self->{DEBUG} && print "loading a tiff file\n";
1393 if ( $input{'type'} eq 'pnm' ) {
1394 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1395 if ( !defined($self->{IMG}) ) {
1396 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1399 $self->{DEBUG} && print "loading a pnm file\n";
1403 if ( $input{'type'} eq 'png' ) {
1404 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1405 if ( !defined($self->{IMG}) ) {
1406 $self->{ERRSTR} = $self->_error_as_msg();
1409 $self->{DEBUG} && print "loading a png file\n";
1412 if ( $input{'type'} eq 'bmp' ) {
1413 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1414 if ( !defined($self->{IMG}) ) {
1415 $self->{ERRSTR}=$self->_error_as_msg();
1418 $self->{DEBUG} && print "loading a bmp file\n";
1421 if ( $input{'type'} eq 'gif' ) {
1422 if ($input{colors} && !ref($input{colors})) {
1423 # must be a reference to a scalar that accepts the colour map
1424 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1427 if ($input{'gif_consolidate'}) {
1428 if ($input{colors}) {
1430 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1432 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1436 $self->{IMG} =i_readgif_wiol( $IO );
1440 my $page = $input{'page'};
1441 defined $page or $page = 0;
1442 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1443 if ($self->{IMG} && $input{colors}) {
1444 ${ $input{colors} } =
1445 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1449 if ( !defined($self->{IMG}) ) {
1450 $self->{ERRSTR}=$self->_error_as_msg();
1453 $self->{DEBUG} && print "loading a gif file\n";
1456 if ( $input{'type'} eq 'tga' ) {
1457 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1458 if ( !defined($self->{IMG}) ) {
1459 $self->{ERRSTR}=$self->_error_as_msg();
1462 $self->{DEBUG} && print "loading a tga file\n";
1465 if ( $input{'type'} eq 'raw' ) {
1466 unless ( $input{xsize} && $input{ysize} ) {
1467 $self->_set_error('missing xsize or ysize parameter for raw');
1471 my $interleave = _first($input{raw_interleave}, $input{interleave});
1472 unless (defined $interleave) {
1473 my @caller = caller;
1474 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1477 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1478 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1480 $self->{IMG} = i_readraw_wiol( $IO,
1486 if ( !defined($self->{IMG}) ) {
1487 $self->{ERRSTR}=$self->_error_as_msg();
1490 $self->{DEBUG} && print "loading a raw file\n";
1496 sub register_reader {
1497 my ($class, %opts) = @_;
1500 or die "register_reader called with no type parameter\n";
1502 my $type = $opts{type};
1504 defined $opts{single} || defined $opts{multiple}
1505 or die "register_reader called with no single or multiple parameter\n";
1507 $readers{$type} = { };
1508 if ($opts{single}) {
1509 $readers{$type}{single} = $opts{single};
1511 if ($opts{multiple}) {
1512 $readers{$type}{multiple} = $opts{multiple};
1518 sub register_writer {
1519 my ($class, %opts) = @_;
1522 or die "register_writer called with no type parameter\n";
1524 my $type = $opts{type};
1526 defined $opts{single} || defined $opts{multiple}
1527 or die "register_writer called with no single or multiple parameter\n";
1529 $writers{$type} = { };
1530 if ($opts{single}) {
1531 $writers{$type}{single} = $opts{single};
1533 if ($opts{multiple}) {
1534 $writers{$type}{multiple} = $opts{multiple};
1545 grep($file_formats{$_}, keys %formats),
1546 qw(ico sgi), # formats not handled directly, but supplied with Imager
1557 grep($file_formats{$_}, keys %formats),
1558 qw(ico sgi), # formats not handled directly, but supplied with Imager
1564 # probes for an Imager::File::whatever module
1565 sub _reader_autoload {
1568 return if $formats{$type} || $readers{$type};
1570 return unless $type =~ /^\w+$/;
1572 my $file = "Imager/File/\U$type\E.pm";
1574 unless ($attempted_to_load{$file}) {
1576 ++$attempted_to_load{$file};
1580 # try to get a reader specific module
1581 my $file = "Imager/File/\U$type\EReader.pm";
1582 unless ($attempted_to_load{$file}) {
1584 ++$attempted_to_load{$file};
1592 # probes for an Imager::File::whatever module
1593 sub _writer_autoload {
1596 return if $formats{$type} || $readers{$type};
1598 return unless $type =~ /^\w+$/;
1600 my $file = "Imager/File/\U$type\E.pm";
1602 unless ($attempted_to_load{$file}) {
1604 ++$attempted_to_load{$file};
1608 # try to get a writer specific module
1609 my $file = "Imager/File/\U$type\EWriter.pm";
1610 unless ($attempted_to_load{$file}) {
1612 ++$attempted_to_load{$file};
1620 sub _fix_gif_positions {
1621 my ($opts, $opt, $msg, @imgs) = @_;
1623 my $positions = $opts->{'gif_positions'};
1625 for my $pos (@$positions) {
1626 my ($x, $y) = @$pos;
1627 my $img = $imgs[$index++];
1628 $img->settag(name=>'gif_left', value=>$x);
1629 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1631 $$msg .= "replaced with the gif_left and gif_top tags";
1636 gif_each_palette=>'gif_local_map',
1637 interlace => 'gif_interlace',
1638 gif_delays => 'gif_delay',
1639 gif_positions => \&_fix_gif_positions,
1640 gif_loop_count => 'gif_loop',
1643 # options that should be converted to colors
1644 my %color_opts = map { $_ => 1 } qw/i_background/;
1647 my ($self, $opts, $prefix, @imgs) = @_;
1649 for my $opt (keys %$opts) {
1651 if ($obsolete_opts{$opt}) {
1652 my $new = $obsolete_opts{$opt};
1653 my $msg = "Obsolete option $opt ";
1655 $new->($opts, $opt, \$msg, @imgs);
1658 $msg .= "replaced with the $new tag ";
1661 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1662 warn $msg if $warn_obsolete && $^W;
1664 next unless $tagname =~ /^\Q$prefix/;
1665 my $value = $opts->{$opt};
1666 if ($color_opts{$opt}) {
1667 $value = _color($value);
1669 $self->_set_error($Imager::ERRSTR);
1674 if (UNIVERSAL::isa($value, "Imager::Color")) {
1675 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1676 for my $img (@imgs) {
1677 $img->settag(name=>$tagname, value=>$tag);
1680 elsif (ref($value) eq 'ARRAY') {
1681 for my $i (0..$#$value) {
1682 my $val = $value->[$i];
1684 if (UNIVERSAL::isa($val, "Imager::Color")) {
1685 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1687 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1690 $self->_set_error("Unknown reference type " . ref($value) .
1691 " supplied in array for $opt");
1697 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1702 $self->_set_error("Unknown reference type " . ref($value) .
1703 " supplied for $opt");
1708 # set it as a tag for every image
1709 for my $img (@imgs) {
1710 $img->settag(name=>$tagname, value=>$value);
1718 # Write an image to file
1721 my %input=(jpegquality=>75,
1731 $self->_set_opts(\%input, "i_", $self)
1734 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1736 if (!$input{'type'} and $input{file}) {
1737 $input{'type'}=$FORMATGUESS->($input{file});
1739 if (!$input{'type'}) {
1740 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1744 _writer_autoload($input{type});
1747 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1748 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1751 $writers{$input{type}}{single}->($self, $IO, %input)
1755 if (!$formats{$input{'type'}}) {
1756 my $write_types = join ', ', sort Imager->write_types();
1757 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1761 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1764 if ($input{'type'} eq 'tiff') {
1765 $self->_set_opts(\%input, "tiff_", $self)
1767 $self->_set_opts(\%input, "exif_", $self)
1770 if (defined $input{class} && $input{class} eq 'fax') {
1771 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1772 $self->{ERRSTR} = $self->_error_as_msg();
1776 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1777 $self->{ERRSTR} = $self->_error_as_msg();
1781 } elsif ( $input{'type'} eq 'pnm' ) {
1782 $self->_set_opts(\%input, "pnm_", $self)
1784 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1785 $self->{ERRSTR} = $self->_error_as_msg();
1788 $self->{DEBUG} && print "writing a pnm file\n";
1789 } elsif ( $input{'type'} eq 'raw' ) {
1790 $self->_set_opts(\%input, "raw_", $self)
1792 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1793 $self->{ERRSTR} = $self->_error_as_msg();
1796 $self->{DEBUG} && print "writing a raw file\n";
1797 } elsif ( $input{'type'} eq 'png' ) {
1798 $self->_set_opts(\%input, "png_", $self)
1800 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1801 $self->{ERRSTR}='unable to write png image';
1804 $self->{DEBUG} && print "writing a png file\n";
1805 } elsif ( $input{'type'} eq 'jpeg' ) {
1806 $self->_set_opts(\%input, "jpeg_", $self)
1808 $self->_set_opts(\%input, "exif_", $self)
1810 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1811 $self->{ERRSTR} = $self->_error_as_msg();
1814 $self->{DEBUG} && print "writing a jpeg file\n";
1815 } elsif ( $input{'type'} eq 'bmp' ) {
1816 $self->_set_opts(\%input, "bmp_", $self)
1818 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1819 $self->{ERRSTR} = $self->_error_as_msg;
1822 $self->{DEBUG} && print "writing a bmp file\n";
1823 } elsif ( $input{'type'} eq 'tga' ) {
1824 $self->_set_opts(\%input, "tga_", $self)
1827 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1828 $self->{ERRSTR}=$self->_error_as_msg();
1831 $self->{DEBUG} && print "writing a tga file\n";
1832 } elsif ( $input{'type'} eq 'gif' ) {
1833 $self->_set_opts(\%input, "gif_", $self)
1835 # compatibility with the old interfaces
1836 if ($input{gifquant} eq 'lm') {
1837 $input{make_colors} = 'addi';
1838 $input{translate} = 'perturb';
1839 $input{perturb} = $input{lmdither};
1840 } elsif ($input{gifquant} eq 'gen') {
1841 # just pass options through
1843 $input{make_colors} = 'webmap'; # ignored
1844 $input{translate} = 'giflib';
1846 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1847 $self->{ERRSTR} = $self->_error_as_msg;
1853 if (exists $input{'data'}) {
1854 my $data = io_slurp($IO);
1856 $self->{ERRSTR}='Could not slurp from buffer';
1859 ${$input{data}} = $data;
1865 my ($class, $opts, @images) = @_;
1867 my $type = $opts->{type};
1869 if (!$type && $opts->{'file'}) {
1870 $type = $FORMATGUESS->($opts->{'file'});
1873 $class->_set_error('type parameter missing and not possible to guess from extension');
1876 # translate to ImgRaw
1877 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1878 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1881 $class->_set_opts($opts, "i_", @images)
1883 my @work = map $_->{IMG}, @images;
1885 _writer_autoload($type);
1888 if ($writers{$type} && $writers{$type}{multiple}) {
1889 ($IO, $file) = $class->_get_writer_io($opts, $type)
1892 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1896 if (!$formats{$type}) {
1897 my $write_types = join ', ', sort Imager->write_types();
1898 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1902 ($IO, $file) = $class->_get_writer_io($opts, $type)
1905 if ($type eq 'gif') {
1906 $class->_set_opts($opts, "gif_", @images)
1908 my $gif_delays = $opts->{gif_delays};
1909 local $opts->{gif_delays} = $gif_delays;
1910 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1911 # assume the caller wants the same delay for each frame
1912 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1914 unless (i_writegif_wiol($IO, $opts, @work)) {
1915 $class->_set_error($class->_error_as_msg());
1919 elsif ($type eq 'tiff') {
1920 $class->_set_opts($opts, "tiff_", @images)
1922 $class->_set_opts($opts, "exif_", @images)
1925 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1926 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1927 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1930 $res = i_writetiff_multi_wiol($IO, @work);
1933 $class->_set_error($class->_error_as_msg());
1939 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1944 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1950 if (exists $opts->{'data'}) {
1951 my $data = io_slurp($IO);
1953 Imager->_set_error('Could not slurp from buffer');
1956 ${$opts->{data}} = $data;
1961 # read multiple images from a file
1963 my ($class, %opts) = @_;
1965 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1968 my $type = $opts{'type'};
1970 $type = i_test_format_probe($IO, -1);
1973 if ($opts{file} && !$type) {
1975 $type = $FORMATGUESS->($opts{file});
1979 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1983 _reader_autoload($type);
1985 if ($readers{$type} && $readers{$type}{multiple}) {
1986 return $readers{$type}{multiple}->($IO, %opts);
1989 unless ($formats{$type}) {
1990 my $read_types = join ', ', sort Imager->read_types();
1991 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1996 if ($type eq 'gif') {
1997 @imgs = i_readgif_multi_wiol($IO);
1999 elsif ($type eq 'tiff') {
2000 @imgs = i_readtiff_multi_wiol($IO, -1);
2002 elsif ($type eq 'pnm') {
2003 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2006 my $img = Imager->new;
2007 if ($img->read(%opts, io => $IO, type => $type)) {
2010 Imager->_set_error($img->errstr);
2015 $ERRSTR = _error_as_msg();
2019 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2023 # Destroy an Imager object
2027 # delete $instances{$self};
2028 if (defined($self->{IMG})) {
2029 # the following is now handled by the XS DESTROY method for
2030 # Imager::ImgRaw object
2031 # Re-enabling this will break virtual images
2032 # tested for in t/t020masked.t
2033 # i_img_destroy($self->{IMG});
2034 undef($self->{IMG});
2036 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2040 # Perform an inplace filter of an image
2041 # that is the image will be overwritten with the data
2047 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2049 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2051 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2052 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2055 if ($filters{$input{'type'}}{names}) {
2056 my $names = $filters{$input{'type'}}{names};
2057 for my $name (keys %$names) {
2058 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2059 $input{$name} = $names->{$name}{$input{$name}};
2063 if (defined($filters{$input{'type'}}{defaults})) {
2064 %hsh=( image => $self->{IMG},
2066 %{$filters{$input{'type'}}{defaults}},
2069 %hsh=( image => $self->{IMG},
2074 my @cs=@{$filters{$input{'type'}}{callseq}};
2077 if (!defined($hsh{$_})) {
2078 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2083 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2084 &{$filters{$input{'type'}}{callsub}}(%hsh);
2087 chomp($self->{ERRSTR} = $@);
2093 $self->{DEBUG} && print "callseq is: @cs\n";
2094 $self->{DEBUG} && print "matching callseq is: @b\n";
2099 sub register_filter {
2101 my %hsh = ( defaults => {}, @_ );
2104 or die "register_filter() with no type\n";
2105 defined $hsh{callsub}
2106 or die "register_filter() with no callsub\n";
2107 defined $hsh{callseq}
2108 or die "register_filter() with no callseq\n";
2110 exists $filters{$hsh{type}}
2113 $filters{$hsh{type}} = \%hsh;
2118 sub scale_calculate {
2121 my %opts = ('type'=>'max', @_);
2123 # none of these should be references
2124 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2125 if (defined $opts{$name} && ref $opts{$name}) {
2126 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2131 my ($x_scale, $y_scale);
2132 my $width = $opts{width};
2133 my $height = $opts{height};
2135 defined $width or $width = $self->getwidth;
2136 defined $height or $height = $self->getheight;
2139 unless (defined $width && defined $height) {
2140 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2145 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2146 $x_scale = $opts{'xscalefactor'};
2147 $y_scale = $opts{'yscalefactor'};
2149 elsif ($opts{'xscalefactor'}) {
2150 $x_scale = $opts{'xscalefactor'};
2151 $y_scale = $opts{'scalefactor'} || $x_scale;
2153 elsif ($opts{'yscalefactor'}) {
2154 $y_scale = $opts{'yscalefactor'};
2155 $x_scale = $opts{'scalefactor'} || $y_scale;
2158 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2161 # work out the scaling
2162 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2163 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2164 $opts{ypixels} / $height );
2165 if ($opts{'type'} eq 'min') {
2166 $x_scale = $y_scale = _min($xpix,$ypix);
2168 elsif ($opts{'type'} eq 'max') {
2169 $x_scale = $y_scale = _max($xpix,$ypix);
2171 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2176 $self->_set_error('invalid value for type parameter');
2179 } elsif ($opts{xpixels}) {
2180 $x_scale = $y_scale = $opts{xpixels} / $width;
2182 elsif ($opts{ypixels}) {
2183 $x_scale = $y_scale = $opts{ypixels}/$height;
2185 elsif ($opts{constrain} && ref $opts{constrain}
2186 && $opts{constrain}->can('constrain')) {
2187 # we've been passed an Image::Math::Constrain object or something
2188 # that looks like one
2190 (undef, undef, $scalefactor)
2191 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2192 unless ($scalefactor) {
2193 $self->_set_error('constrain method failed on constrain parameter');
2196 $x_scale = $y_scale = $scalefactor;
2199 my $new_width = int($x_scale * $width + 0.5);
2200 $new_width > 0 or $new_width = 1;
2201 my $new_height = int($y_scale * $height + 0.5);
2202 $new_height > 0 or $new_height = 1;
2204 return ($x_scale, $y_scale, $new_width, $new_height);
2208 # Scale an image to requested size and return the scaled version
2212 my %opts = (qtype=>'normal' ,@_);
2213 my $img = Imager->new();
2214 my $tmp = Imager->new();
2216 unless (defined wantarray) {
2217 my @caller = caller;
2218 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2222 unless ($self->{IMG}) {
2223 $self->_set_error('empty input image');
2227 my ($x_scale, $y_scale, $new_width, $new_height) =
2228 $self->scale_calculate(%opts)
2231 if ($opts{qtype} eq 'normal') {
2232 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2233 if ( !defined($tmp->{IMG}) ) {
2234 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2237 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2238 if ( !defined($img->{IMG}) ) {
2239 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2245 elsif ($opts{'qtype'} eq 'preview') {
2246 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2247 if ( !defined($img->{IMG}) ) {
2248 $self->{ERRSTR}='unable to scale image';
2253 elsif ($opts{'qtype'} eq 'mixing') {
2254 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2255 unless ($img->{IMG}) {
2256 $self->_set_error(Imager->_error_as_msg);
2262 $self->_set_error('invalid value for qtype parameter');
2267 # Scales only along the X axis
2271 my %opts = ( scalefactor=>0.5, @_ );
2273 unless (defined wantarray) {
2274 my @caller = caller;
2275 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2279 unless ($self->{IMG}) {
2280 $self->{ERRSTR} = 'empty input image';
2284 my $img = Imager->new();
2286 my $scalefactor = $opts{scalefactor};
2288 if ($opts{pixels}) {
2289 $scalefactor = $opts{pixels} / $self->getwidth();
2292 unless ($self->{IMG}) {
2293 $self->{ERRSTR}='empty input image';
2297 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2299 if ( !defined($img->{IMG}) ) {
2300 $self->{ERRSTR} = 'unable to scale image';
2307 # Scales only along the Y axis
2311 my %opts = ( scalefactor => 0.5, @_ );
2313 unless (defined wantarray) {
2314 my @caller = caller;
2315 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2319 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2321 my $img = Imager->new();
2323 my $scalefactor = $opts{scalefactor};
2325 if ($opts{pixels}) {
2326 $scalefactor = $opts{pixels} / $self->getheight();
2329 unless ($self->{IMG}) {
2330 $self->{ERRSTR} = 'empty input image';
2333 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2335 if ( !defined($img->{IMG}) ) {
2336 $self->{ERRSTR} = 'unable to scale image';
2343 # Transform returns a spatial transformation of the input image
2344 # this moves pixels to a new location in the returned image.
2345 # NOTE - should make a utility function to check transforms for
2350 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2352 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2354 # print Dumper(\%opts);
2357 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2359 eval ("use Affix::Infix2Postfix;");
2362 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2365 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2366 {op=>'-',trans=>'Sub'},
2367 {op=>'*',trans=>'Mult'},
2368 {op=>'/',trans=>'Div'},
2369 {op=>'-','type'=>'unary',trans=>'u-'},
2371 {op=>'func','type'=>'unary'}],
2372 'grouping'=>[qw( \( \) )],
2373 'func'=>[qw( sin cos )],
2378 @xt=$I2P->translate($opts{'xexpr'});
2379 @yt=$I2P->translate($opts{'yexpr'});
2381 $numre=$I2P->{'numre'};
2384 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2385 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2386 @{$opts{'parm'}}=@pt;
2389 # print Dumper(\%opts);
2391 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2392 $self->{ERRSTR}='transform: no xopcodes given.';
2396 @op=@{$opts{'xopcodes'}};
2398 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2399 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2402 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2408 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2409 $self->{ERRSTR}='transform: no yopcodes given.';
2413 @op=@{$opts{'yopcodes'}};
2415 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2416 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2419 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2424 if ( !exists $opts{'parm'}) {
2425 $self->{ERRSTR}='transform: no parameter arg given.';
2429 # print Dumper(\@ropx);
2430 # print Dumper(\@ropy);
2431 # print Dumper(\@ropy);
2433 my $img = Imager->new();
2434 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2435 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2441 my ($opts, @imgs) = @_;
2443 require "Imager/Expr.pm";
2445 $opts->{variables} = [ qw(x y) ];
2446 my ($width, $height) = @{$opts}{qw(width height)};
2448 $width ||= $imgs[0]->getwidth();
2449 $height ||= $imgs[0]->getheight();
2451 for my $img (@imgs) {
2452 $opts->{constants}{"w$img_num"} = $img->getwidth();
2453 $opts->{constants}{"h$img_num"} = $img->getheight();
2454 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2455 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2460 $opts->{constants}{w} = $width;
2461 $opts->{constants}{cx} = $width/2;
2464 $Imager::ERRSTR = "No width supplied";
2468 $opts->{constants}{h} = $height;
2469 $opts->{constants}{cy} = $height/2;
2472 $Imager::ERRSTR = "No height supplied";
2475 my $code = Imager::Expr->new($opts);
2477 $Imager::ERRSTR = Imager::Expr::error();
2480 my $channels = $opts->{channels} || 3;
2481 unless ($channels >= 1 && $channels <= 4) {
2482 return Imager->_set_error("channels must be an integer between 1 and 4");
2485 my $img = Imager->new();
2486 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2487 $channels, $code->code(),
2488 $code->nregs(), $code->cregs(),
2489 [ map { $_->{IMG} } @imgs ]);
2490 if (!defined $img->{IMG}) {
2491 $Imager::ERRSTR = Imager->_error_as_msg();
2502 unless ($self->{IMG}) {
2503 $self->{ERRSTR}='empty input image';
2506 unless ($opts{src} && $opts{src}->{IMG}) {
2507 $self->{ERRSTR}='empty input image for src';
2511 %opts = (src_minx => 0,
2513 src_maxx => $opts{src}->getwidth(),
2514 src_maxy => $opts{src}->getheight(),
2518 defined $tx or $tx = $opts{left};
2519 defined $tx or $tx = 0;
2522 defined $ty or $ty = $opts{top};
2523 defined $ty or $ty = 0;
2525 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2526 $opts{src_minx}, $opts{src_miny},
2527 $opts{src_maxx}, $opts{src_maxy})) {
2528 $self->_set_error($self->_error_as_msg());
2545 unless ($self->{IMG}) {
2546 $self->_set_error("compose: empty input image");
2550 unless ($opts{src}) {
2551 $self->_set_error("compose: src parameter missing");
2555 unless ($opts{src}{IMG}) {
2556 $self->_set_error("compose: src parameter empty image");
2559 my $src = $opts{src};
2561 my $left = $opts{left};
2562 defined $left or $left = $opts{tx};
2563 defined $left or $left = 0;
2565 my $top = $opts{top};
2566 defined $top or $top = $opts{ty};
2567 defined $top or $top = 0;
2569 my $src_left = $opts{src_left};
2570 defined $src_left or $src_left = $opts{src_minx};
2571 defined $src_left or $src_left = 0;
2573 my $src_top = $opts{src_top};
2574 defined $src_top or $src_top = $opts{src_miny};
2575 defined $src_top or $src_top = 0;
2577 my $width = $opts{width};
2578 if (!defined $width && defined $opts{src_maxx}) {
2579 $width = $opts{src_maxx} - $src_left;
2581 defined $width or $width = $src->getwidth() - $src_left;
2583 my $height = $opts{height};
2584 if (!defined $height && defined $opts{src_maxy}) {
2585 $height = $opts{src_maxy} - $src_top;
2587 defined $height or $height = $src->getheight() - $src_top;
2589 my $combine = $self->_combine($opts{combine}, 'normal');
2592 unless ($opts{mask}{IMG}) {
2593 $self->_set_error("compose: mask parameter empty image");
2597 my $mask_left = $opts{mask_left};
2598 defined $mask_left or $mask_left = $opts{mask_minx};
2599 defined $mask_left or $mask_left = 0;
2601 my $mask_top = $opts{mask_top};
2602 defined $mask_top or $mask_top = $opts{mask_miny};
2603 defined $mask_top or $mask_top = 0;
2605 i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2606 $left, $top, $src_left, $src_top,
2607 $mask_left, $mask_top, $width, $height,
2608 $combine, $opts{opacity})
2612 i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2613 $width, $height, $combine, $opts{opacity})
2623 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2625 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2626 $dir = $xlate{$opts{'dir'}};
2627 return $self if i_flipxy($self->{IMG}, $dir);
2635 unless (defined wantarray) {
2636 my @caller = caller;
2637 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2641 if (defined $opts{right}) {
2642 my $degrees = $opts{right};
2644 $degrees += 360 * int(((-$degrees)+360)/360);
2646 $degrees = $degrees % 360;
2647 if ($degrees == 0) {
2648 return $self->copy();
2650 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2651 my $result = Imager->new();
2652 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2656 $self->{ERRSTR} = $self->_error_as_msg();
2661 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2665 elsif (defined $opts{radians} || defined $opts{degrees}) {
2666 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2668 my $back = $opts{back};
2669 my $result = Imager->new;
2671 $back = _color($back);
2673 $self->_set_error(Imager->errstr);
2677 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2680 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2682 if ($result->{IMG}) {
2686 $self->{ERRSTR} = $self->_error_as_msg();
2691 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2696 sub matrix_transform {
2700 unless (defined wantarray) {
2701 my @caller = caller;
2702 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2706 if ($opts{matrix}) {
2707 my $xsize = $opts{xsize} || $self->getwidth;
2708 my $ysize = $opts{ysize} || $self->getheight;
2710 my $result = Imager->new;
2712 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2713 $opts{matrix}, $opts{back})
2717 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2725 $self->{ERRSTR} = "matrix parameter required";
2731 *yatf = \&matrix_transform;
2733 # These two are supported for legacy code only
2736 return Imager::Color->new(@_);
2740 return Imager::Color::set(@_);
2743 # Draws a box between the specified corner points.
2746 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2747 my $dflcl=i_color_new(255,255,255,255);
2748 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2750 if (exists $opts{'box'}) {
2751 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2752 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2753 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2754 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2757 if ($opts{filled}) {
2758 my $color = _color($opts{'color'});
2760 $self->{ERRSTR} = $Imager::ERRSTR;
2763 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2764 $opts{ymax}, $color);
2766 elsif ($opts{fill}) {
2767 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2768 # assume it's a hash ref
2769 require 'Imager/Fill.pm';
2770 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2771 $self->{ERRSTR} = $Imager::ERRSTR;
2775 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2776 $opts{ymax},$opts{fill}{fill});
2779 my $color = _color($opts{'color'});
2781 $self->{ERRSTR} = $Imager::ERRSTR;
2784 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2792 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2793 my $dflcl= [ 255, 255, 255, 255];
2798 'r'=>_min($self->getwidth(),$self->getheight())/3,
2799 'x'=>$self->getwidth()/2,
2800 'y'=>$self->getheight()/2,
2807 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2808 # assume it's a hash ref
2809 require 'Imager/Fill.pm';
2810 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2811 $self->{ERRSTR} = $Imager::ERRSTR;
2815 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2816 $opts{'d2'}, $opts{fill}{fill});
2818 elsif ($opts{filled}) {
2819 my $color = _color($opts{'color'});
2821 $self->{ERRSTR} = $Imager::ERRSTR;
2824 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2825 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2829 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2830 $opts{'d1'}, $opts{'d2'}, $color);
2834 my $color = _color($opts{'color'});
2835 if ($opts{d2} - $opts{d1} >= 360) {
2836 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2839 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2845 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2846 # assume it's a hash ref
2847 require 'Imager/Fill.pm';
2848 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2849 $self->{ERRSTR} = $Imager::ERRSTR;
2853 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2854 $opts{'d2'}, $opts{fill}{fill});
2857 my $color = _color($opts{'color'});
2859 $self->{ERRSTR} = $Imager::ERRSTR;
2862 if ($opts{filled}) {
2863 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2864 $opts{'d1'}, $opts{'d2'}, $color);
2867 if ($opts{d1} == 0 && $opts{d2} == 361) {
2868 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2871 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2877 $self->_set_error($self->_error_as_msg);
2884 # Draws a line from one point to the other
2885 # the endpoint is set if the endp parameter is set which it is by default.
2886 # to turn of the endpoint being set use endp=>0 when calling line.
2890 my $dflcl=i_color_new(0,0,0,0);
2891 my %opts=(color=>$dflcl,
2894 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2896 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2897 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2899 my $color = _color($opts{'color'});
2901 $self->{ERRSTR} = $Imager::ERRSTR;
2905 $opts{antialias} = $opts{aa} if defined $opts{aa};
2906 if ($opts{antialias}) {
2907 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2908 $color, $opts{endp});
2910 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2911 $color, $opts{endp});
2916 # Draws a line between an ordered set of points - It more or less just transforms this
2917 # into a list of lines.
2921 my ($pt,$ls,@points);
2922 my $dflcl=i_color_new(0,0,0,0);
2923 my %opts=(color=>$dflcl,@_);
2925 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2927 if (exists($opts{points})) { @points=@{$opts{points}}; }
2928 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2929 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2932 # print Dumper(\@points);
2934 my $color = _color($opts{'color'});
2936 $self->{ERRSTR} = $Imager::ERRSTR;
2939 $opts{antialias} = $opts{aa} if defined $opts{aa};
2940 if ($opts{antialias}) {
2943 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2950 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2960 my ($pt,$ls,@points);
2961 my $dflcl = i_color_new(0,0,0,0);
2962 my %opts = (color=>$dflcl, @_);
2964 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2966 if (exists($opts{points})) {
2967 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2968 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2971 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2972 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2975 if ($opts{'fill'}) {
2976 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2977 # assume it's a hash ref
2978 require 'Imager/Fill.pm';
2979 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2980 $self->{ERRSTR} = $Imager::ERRSTR;
2984 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2985 $opts{'fill'}{'fill'});
2988 my $color = _color($opts{'color'});
2990 $self->{ERRSTR} = $Imager::ERRSTR;
2993 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3000 # this the multipoint bezier curve
3001 # this is here more for testing that actual usage since
3002 # this is not a good algorithm. Usually the curve would be
3003 # broken into smaller segments and each done individually.
3007 my ($pt,$ls,@points);
3008 my $dflcl=i_color_new(0,0,0,0);
3009 my %opts=(color=>$dflcl,@_);
3011 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3013 if (exists $opts{points}) {
3014 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3015 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3018 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3019 $self->{ERRSTR}='Missing or invalid points.';
3023 my $color = _color($opts{'color'});
3025 $self->{ERRSTR} = $Imager::ERRSTR;
3028 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3034 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3037 unless (exists $opts{'x'} && exists $opts{'y'}) {
3038 $self->{ERRSTR} = "missing seed x and y parameters";
3042 if ($opts{border}) {
3043 my $border = _color($opts{border});
3045 $self->_set_error($Imager::ERRSTR);
3049 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3050 # assume it's a hash ref
3051 require Imager::Fill;
3052 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3053 $self->{ERRSTR} = $Imager::ERRSTR;
3057 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3058 $opts{fill}{fill}, $border);
3061 my $color = _color($opts{'color'});
3063 $self->{ERRSTR} = $Imager::ERRSTR;
3066 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3073 $self->{ERRSTR} = $self->_error_as_msg();
3079 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3080 # assume it's a hash ref
3081 require 'Imager/Fill.pm';
3082 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3083 $self->{ERRSTR} = $Imager::ERRSTR;
3087 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3090 my $color = _color($opts{'color'});
3092 $self->{ERRSTR} = $Imager::ERRSTR;
3095 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3101 $self->{ERRSTR} = $self->_error_as_msg();
3108 my ($self, %opts) = @_;
3110 my $color = $opts{color};
3111 unless (defined $color) {
3112 $color = $self->{fg};
3113 defined $color or $color = NC(255, 255, 255);
3116 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3117 $color = _color($color)
3121 unless (exists $opts{'x'} && exists $opts{'y'}) {
3122 $self->{ERRSTR} = 'missing x and y parameters';
3128 if (ref $x && ref $y) {
3129 unless (@$x == @$y) {
3130 $self->{ERRSTR} = 'length of x and y mismatch';
3134 if ($color->isa('Imager::Color')) {
3135 for my $i (0..$#{$opts{'x'}}) {
3136 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3141 for my $i (0..$#{$opts{'x'}}) {
3142 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3150 if ($color->isa('Imager::Color')) {
3151 i_ppix($self->{IMG}, $x, $y, $color)
3155 i_ppixf($self->{IMG}, $x, $y, $color)
3166 my %opts = ( "type"=>'8bit', @_);
3168 unless (exists $opts{'x'} && exists $opts{'y'}) {
3169 $self->{ERRSTR} = 'missing x and y parameters';
3175 if (ref $x && ref $y) {
3176 unless (@$x == @$y) {
3177 $self->{ERRSTR} = 'length of x and y mismatch';
3181 if ($opts{"type"} eq '8bit') {
3182 for my $i (0..$#{$opts{'x'}}) {
3183 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3187 for my $i (0..$#{$opts{'x'}}) {
3188 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3191 return wantarray ? @result : \@result;
3194 if ($opts{"type"} eq '8bit') {
3195 return i_get_pixel($self->{IMG}, $x, $y);
3198 return i_gpixf($self->{IMG}, $x, $y);
3207 my %opts = ( type => '8bit', x=>0, @_);
3209 $self->_valid_image or return;
3211 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3213 unless (defined $opts{'y'}) {
3214 $self->_set_error("missing y parameter");
3218 if ($opts{type} eq '8bit') {
3219 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3222 elsif ($opts{type} eq 'float') {
3223 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3226 elsif ($opts{type} eq 'index') {
3227 unless (i_img_type($self->{IMG})) {
3228 $self->_set_error("type => index only valid on paletted images");
3231 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3235 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3242 my %opts = ( x=>0, @_);
3244 $self->_valid_image or return;
3246 unless (defined $opts{'y'}) {
3247 $self->_set_error("missing y parameter");
3252 if (ref $opts{pixels} && @{$opts{pixels}}) {
3253 # try to guess the type
3254 if ($opts{pixels}[0]->isa('Imager::Color')) {
3255 $opts{type} = '8bit';
3257 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3258 $opts{type} = 'float';
3261 $self->_set_error("missing type parameter and could not guess from pixels");
3267 $opts{type} = '8bit';
3271 if ($opts{type} eq '8bit') {
3272 if (ref $opts{pixels}) {
3273 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3276 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3279 elsif ($opts{type} eq 'float') {
3280 if (ref $opts{pixels}) {
3281 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3284 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3287 elsif ($opts{type} eq 'index') {
3288 if (ref $opts{pixels}) {
3289 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3292 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3296 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3303 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3305 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3307 unless (defined $opts{'y'}) {
3308 $self->_set_error("missing y parameter");
3312 unless ($opts{channels}) {
3313 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3316 if ($opts{target}) {
3317 my $target = $opts{target};
3318 my $offset = $opts{offset};
3319 if ($opts{type} eq '8bit') {
3320 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3321 $opts{y}, @{$opts{channels}})
3323 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3324 return scalar(@samples);
3326 elsif ($opts{type} eq 'float') {
3327 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3328 $opts{y}, @{$opts{channels}});
3329 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3330 return scalar(@samples);
3332 elsif ($opts{type} =~ /^(\d+)bit$/) {
3336 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3337 $opts{y}, $bits, $target,
3338 $offset, @{$opts{channels}});
3339 unless (defined $count) {
3340 $self->_set_error(Imager->_error_as_msg);
3347 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3352 if ($opts{type} eq '8bit') {
3353 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3354 $opts{y}, @{$opts{channels}});
3356 elsif ($opts{type} eq 'float') {
3357 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3358 $opts{y}, @{$opts{channels}});
3360 elsif ($opts{type} =~ /^(\d+)bit$/) {
3364 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3365 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3370 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3378 my %opts = ( x => 0, offset => 0, @_ );
3380 unless ($self->{IMG}) {
3381 $self->_set_error('setsamples: empty input image');
3385 unless(defined $opts{data} && ref $opts{data}) {
3386 $self->_set_error('setsamples: data parameter missing or invalid');
3390 unless ($opts{channels}) {
3391 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3394 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3395 $self->_set_error('setsamples: type parameter missing or invalid');
3400 unless (defined $opts{width}) {
3401 $opts{width} = $self->getwidth() - $opts{x};
3404 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3405 $opts{channels}, $opts{data}, $opts{offset},
3407 unless (defined $count) {
3408 $self->_set_error(Imager->_error_as_msg);
3415 # make an identity matrix of the given size
3419 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3420 for my $c (0 .. ($size-1)) {
3421 $matrix->[$c][$c] = 1;
3426 # general function to convert an image
3428 my ($self, %opts) = @_;
3431 unless (defined wantarray) {
3432 my @caller = caller;
3433 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3437 # the user can either specify a matrix or preset
3438 # the matrix overrides the preset
3439 if (!exists($opts{matrix})) {
3440 unless (exists($opts{preset})) {
3441 $self->{ERRSTR} = "convert() needs a matrix or preset";
3445 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3446 # convert to greyscale, keeping the alpha channel if any
3447 if ($self->getchannels == 3) {
3448 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3450 elsif ($self->getchannels == 4) {
3451 # preserve the alpha channel
3452 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3457 $matrix = _identity($self->getchannels);
3460 elsif ($opts{preset} eq 'noalpha') {
3461 # strip the alpha channel
3462 if ($self->getchannels == 2 or $self->getchannels == 4) {
3463 $matrix = _identity($self->getchannels);
3464 pop(@$matrix); # lose the alpha entry
3467 $matrix = _identity($self->getchannels);
3470 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3472 $matrix = [ [ 1 ] ];
3474 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3475 $matrix = [ [ 0, 1 ] ];
3477 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3478 $matrix = [ [ 0, 0, 1 ] ];
3480 elsif ($opts{preset} eq 'alpha') {
3481 if ($self->getchannels == 2 or $self->getchannels == 4) {
3482 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3485 # the alpha is just 1 <shrug>
3486 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3489 elsif ($opts{preset} eq 'rgb') {
3490 if ($self->getchannels == 1) {
3491 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3493 elsif ($self->getchannels == 2) {
3494 # preserve the alpha channel
3495 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3498 $matrix = _identity($self->getchannels);
3501 elsif ($opts{preset} eq 'addalpha') {
3502 if ($self->getchannels == 1) {
3503 $matrix = _identity(2);
3505 elsif ($self->getchannels == 3) {
3506 $matrix = _identity(4);
3509 $matrix = _identity($self->getchannels);
3513 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3519 $matrix = $opts{matrix};
3522 my $new = Imager->new;
3523 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3524 unless ($new->{IMG}) {
3525 # most likely a bad matrix
3526 $self->{ERRSTR} = _error_as_msg();
3533 # general function to map an image through lookup tables
3536 my ($self, %opts) = @_;
3537 my @chlist = qw( red green blue alpha );
3539 if (!exists($opts{'maps'})) {
3540 # make maps from channel maps
3542 for $chnum (0..$#chlist) {
3543 if (exists $opts{$chlist[$chnum]}) {
3544 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3545 } elsif (exists $opts{'all'}) {
3546 $opts{'maps'}[$chnum] = $opts{'all'};
3550 if ($opts{'maps'} and $self->{IMG}) {
3551 i_map($self->{IMG}, $opts{'maps'} );
3557 my ($self, %opts) = @_;
3559 defined $opts{mindist} or $opts{mindist} = 0;
3561 defined $opts{other}
3562 or return $self->_set_error("No 'other' parameter supplied");
3563 defined $opts{other}{IMG}
3564 or return $self->_set_error("No image data in 'other' image");
3567 or return $self->_set_error("No image data");
3569 my $result = Imager->new;
3570 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3572 or return $self->_set_error($self->_error_as_msg());
3577 # destructive border - image is shrunk by one pixel all around
3580 my ($self,%opts)=@_;
3581 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3582 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3586 # Get the width of an image
3590 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3591 return (i_img_info($self->{IMG}))[0];
3594 # Get the height of an image
3598 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3599 return (i_img_info($self->{IMG}))[1];
3602 # Get number of channels in an image
3606 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3607 return i_img_getchannels($self->{IMG});
3614 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3615 return i_img_getmask($self->{IMG});
3623 if (!defined($self->{IMG})) {
3624 $self->{ERRSTR} = 'image is empty';
3627 unless (defined $opts{mask}) {
3628 $self->_set_error("mask parameter required");
3631 i_img_setmask( $self->{IMG} , $opts{mask} );
3636 # Get number of colors in an image
3640 my %opts=('maxcolors'=>2**30,@_);
3641 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3642 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3643 return ($rc==-1? undef : $rc);
3646 # Returns a reference to a hash. The keys are colour named (packed) and the
3647 # values are the number of pixels in this colour.
3648 sub getcolorusagehash {
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 my $channels= $self->getchannels;
3664 # We don't want to look at the alpha channel, because some gifs using it
3665 # doesn't define it for every colour (but only for some)
3666 $channels -= 1 if $channels == 2 or $channels == 4;
3668 my $height = $self->getheight;
3669 for my $y (0 .. $height - 1) {
3670 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3671 while (length $colors) {
3672 $color_use{ substr($colors, 0, $channels, '') }++;
3674 keys %color_use > $max_colors
3680 # This will return a ordered array of the colour usage. Kind of the sorted
3681 # version of the values of the hash returned by getcolorusagehash.
3682 # You might want to add safety checks and change the names, etc...
3686 my %opts = ( maxcolors => 2**30, @_ );
3687 my $max_colors = $opts{maxcolors};
3688 unless (defined $max_colors && $max_colors > 0) {
3689 $self->_set_error('maxcolors must be a positive integer');
3693 unless (defined $self->{IMG}) {
3694 $self->_set_error('empty input image');
3698 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3701 # draw string to an image
3705 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3707 my %input=('x'=>0, 'y'=>0, @_);
3708 defined($input{string}) or $input{string} = $input{text};
3710 unless(defined $input{string}) {
3711 $self->{ERRSTR}="missing required parameter 'string'";
3715 unless($input{font}) {
3716 $self->{ERRSTR}="missing required parameter 'font'";
3720 unless ($input{font}->draw(image=>$self, %input)) {
3732 unless ($self->{IMG}) {
3733 $self->{ERRSTR}='empty input image';
3742 my %input=('x'=>0, 'y'=>0, @_);
3743 $input{string}||=$input{text};
3745 unless(exists $input{string}) {
3746 $self->_set_error("missing required parameter 'string'");
3750 unless($input{font}) {
3751 $self->_set_error("missing required parameter 'font'");
3756 unless (@result = $input{font}->align(image=>$img, %input)) {
3760 return wantarray ? @result : $result[0];
3763 my @file_limit_names = qw/width height bytes/;
3765 sub set_file_limits {
3772 @values{@file_limit_names} = (0) x @file_limit_names;
3775 @values{@file_limit_names} = i_get_image_file_limits();
3778 for my $key (keys %values) {
3779 defined $opts{$key} and $values{$key} = $opts{$key};
3782 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3785 sub get_file_limits {
3786 i_get_image_file_limits();
3789 # Shortcuts that can be exported
3791 sub newcolor { Imager::Color->new(@_); }
3792 sub newfont { Imager::Font->new(@_); }
3793 sub NCF { Imager::Color::Float->new(@_) }
3795 *NC=*newcolour=*newcolor;
3802 #### Utility routines
3805 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3809 my ($self, $msg) = @_;
3812 $self->{ERRSTR} = $msg;
3820 # Default guess for the type of an image from extension
3822 sub def_guess_type {
3825 $ext=($name =~ m/\.([^\.]+)$/)[0];
3826 return 'tiff' if ($ext =~ m/^tiff?$/);
3827 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3828 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3829 return 'png' if ($ext eq "png");
3830 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3831 return 'tga' if ($ext eq "tga");
3832 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3833 return 'gif' if ($ext eq "gif");
3834 return 'raw' if ($ext eq "raw");
3835 return lc $ext; # best guess
3840 return @combine_types;
3843 # get the minimum of a list
3847 for(@_) { if ($_<$mx) { $mx=$_; }}
3851 # get the maximum of a list
3855 for(@_) { if ($_>$mx) { $mx=$_; }}
3859 # string stuff for iptc headers
3863 $str = substr($str,3);
3864 $str =~ s/[\n\r]//g;
3871 # A little hack to parse iptc headers.
3876 my($caption,$photogr,$headln,$credit);
3878 my $str=$self->{IPTCRAW};
3883 @ar=split(/8BIM/,$str);
3888 @sar=split(/\034\002/);
3889 foreach $item (@sar) {
3890 if ($item =~ m/^x/) {
3891 $caption = _clean($item);
3894 if ($item =~ m/^P/) {
3895 $photogr = _clean($item);
3898 if ($item =~ m/^i/) {
3899 $headln = _clean($item);
3902 if ($item =~ m/^n/) {
3903 $credit = _clean($item);
3909 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3916 or die "Only C language supported";
3918 require Imager::ExtUtils;
3919 return Imager::ExtUtils->inline_config;
3922 # threads shouldn't try to close raw Imager objects
3923 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3927 # Below is the stub of documentation for your module. You better edit it!
3931 Imager - Perl extension for Generating 24 bit Images
3941 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3946 # see Imager::Files for information on the read() method
3947 my $im = Imager->new(file=>$file)
3948 or die Imager->errstr();
3950 $file =~ s/\.[^.]*$//;
3952 # Create smaller version
3953 # documented in Imager::Transformations
3954 my $thumb = $img->scale(scalefactor=>.3);
3956 # Autostretch individual channels
3957 $thumb->filter(type=>'autolevels');
3959 # try to save in one of these formats
3962 for $format ( qw( png gif jpeg tiff ppm ) ) {
3963 # Check if given format is supported
3964 if ($Imager::formats{$format}) {
3965 $file.="_low.$format";
3966 print "Storing image as: $file\n";
3967 # documented in Imager::Files
3968 $thumb->write(file=>$file) or
3976 Imager is a module for creating and altering images. It can read and
3977 write various image formats, draw primitive shapes like lines,and
3978 polygons, blend multiple images together in various ways, scale, crop,
3979 render text and more.
3981 =head2 Overview of documentation
3987 Imager - This document - Synopsis, Example, Table of Contents and
3992 L<Imager::Tutorial> - a brief introduction to Imager.
3996 L<Imager::Cookbook> - how to do various things with Imager.
4000 L<Imager::ImageTypes> - Basics of constructing image objects with
4001 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4002 8/16/double bits/channel, color maps, channel masks, image tags, color
4003 quantization. Also discusses basic image information methods.
4007 L<Imager::Files> - IO interaction, reading/writing images, format
4012 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4017 L<Imager::Color> - Color specification.
4021 L<Imager::Fill> - Fill pattern specification.
4025 L<Imager::Font> - General font rendering, bounding boxes and font
4030 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4031 blending, pasting, convert and map.
4035 L<Imager::Engines> - Programmable transformations through
4036 C<transform()>, C<transform2()> and C<matrix_transform()>.
4040 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4045 L<Imager::Expr> - Expressions for evaluation engine used by
4050 L<Imager::Matrix2d> - Helper class for affine transformations.
4054 L<Imager::Fountain> - Helper for making gradient profiles.
4058 L<Imager::API> - using Imager's C API
4062 L<Imager::APIRef> - API function reference
4066 L<Imager::Inline> - using Imager's C API from Inline::C
4070 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4074 =head2 Basic Overview
4076 An Image object is created with C<$img = Imager-E<gt>new()>.
4079 $img=Imager->new(); # create empty image
4080 $img->read(file=>'lena.png',type=>'png') or # read image from file
4081 die $img->errstr(); # give an explanation
4082 # if something failed
4084 or if you want to create an empty image:
4086 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4088 This example creates a completely black image of width 400 and height
4091 =head1 ERROR HANDLING
4093 In general a method will return false when it fails, if it does use
4094 the C<errstr()> method to find out why:
4100 Returns the last error message in that context.
4102 If the last error you received was from calling an object method, such
4103 as read, call errstr() as an object method to find out why:
4105 my $image = Imager->new;
4106 $image->read(file => 'somefile.gif')
4107 or die $image->errstr;
4109 If it was a class method then call errstr() as a class method:
4111 my @imgs = Imager->read_multi(file => 'somefile.gif')
4112 or die Imager->errstr;
4114 Note that in some cases object methods are implemented in terms of
4115 class methods so a failing object method may set both.
4119 The C<Imager-E<gt>new> method is described in detail in
4120 L<Imager::ImageTypes>.
4124 Where to find information on methods for Imager class objects.
4126 addcolors() - L<Imager::ImageTypes/addcolors> - add colors to a
4129 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4131 align_string() - L<Imager::Draw/align_string> - draw text aligned on a
4134 arc() - L<Imager::Draw/arc> - draw a filled arc
4136 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4139 box() - L<Imager::Draw/box> - draw a filled or outline box.
4141 circle() - L<Imager::Draw/circle> - draw a filled circle
4143 colorcount() - L<Imager::Draw/colorcount> - the number of colors in an
4144 image's palette (paletted images only)
4146 combines() - L<Imager::Draw/combines> - return a list of the different
4147 combine type keywords
4149 compose() - L<Imager::Transformations/compose> - compose one image
4152 convert() - L<Imager::Transformations/"Color transformations"> -
4153 transform the color space
4155 copy() - L<Imager::Transformations/copy> - make a duplicate of an
4158 crop() - L<Imager::Transformations/crop> - extract part of an image
4160 def_guess_type() - L<Imager::Files/def_guess_type> - default function
4161 used to guess the output file format based on the output file name
4163 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4165 difference() - L<Imager::Filters/"Image Difference"> - produce a
4166 difference images from two input images.
4168 errstr() - L<"Basic Overview"> - the error from the last failed
4171 filter() - L<Imager::Filters> - image filtering
4173 findcolor() - L<Imager::ImageTypes/findcolor> - search the image
4174 palette, if it has one
4176 flip() - L<Imager::Transformations/flip> - flip an image, vertically,
4179 flood_fill() - L<Imager::Draw/flood_fill> - fill an enclosed or same
4182 getchannels() - L<Imager::ImageTypes/getchannels> - the number of
4183 samples per pixel for an image
4185 getcolorcount() - L<Imager::ImageTypes/getcolorcount> - the number of
4186 different colors used by an image (works for direct color images)
4188 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4189 palette, if it has one
4191 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4193 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4195 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4197 getheight() - L<Imager::ImageTypes/getwidth> - height of the image in
4200 getmask() - L<Imager::ImageTypes/getmask> - write mask for the image
4202 getpixel() - L<Imager::Draw/getpixel> - retrieve one or more pixel
4205 getsamples() - L<Imager::Draw/getsamples> - retrieve samples from a
4206 row or partial row of pixels.
4208 getscanline() - L<Imager::Draw/getscanline> - retrieve colors for a
4209 row or partial row of pixels.
4211 getwidth() - L<Imager::ImageTypes/getwidth> - width of the image in
4214 img_set() - L<Imager::ImageTypes/img_set> - re-use an Imager object
4217 init() - L<Imager::ImageTypes/init>
4219 is_bilevel() - L<Imager::ImageTypes/is_bilevel> - returns whether
4220 image write functions should write the image in their bilevel (blank
4221 and white, no gray levels) format
4223 line() - L<Imager::Draw/line> - draw an interval
4225 load_plugin() - L<Imager::Filters/load_plugin>
4227 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4230 masked() - L<Imager::ImageTypes/masked> - make a masked image
4232 matrix_transform() - L<Imager::Engines/matrix_transform>
4234 maxcolors() - L<Imager::ImageTypes/maxcolors>
4236 NC() - L<Imager::Handy/NC>
4238 NCF() - L<Imager::Handy/NCF>
4240 new() - L<Imager::ImageTypes/new>
4242 newcolor() - L<Imager::Handy/newcolor>
4244 newcolour() - L<Imager::Handy/newcolour>
4246 newfont() - L<Imager::Handy/newfont>
4248 NF() - L<Imager::Handy/NF>
4250 open() - L<Imager::Files> - an alias for read()
4254 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4257 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4259 polygon() - L<Imager::Draw/polygon>
4261 polyline() - L<Imager::Draw/polyline>
4263 read() - L<Imager::Files> - read a single image from an image file
4265 read_multi() - L<Imager::Files> - read multiple images from an image
4268 read_types() - L<Imager::Files/read_types> - list image types Imager
4271 register_filter() - L<Imager::Filters/register_filter>
4273 register_reader() - L<Imager::Files/register_reader>
4275 register_writer() - L<Imager::Files/register_writer>
4277 rotate() - L<Imager::Transformations/rotate>
4279 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4280 image and use the alpha channel
4282 scale() - L<Imager::Transformations/scale>
4284 scale_calculate() - L<Imager::Transformations/scale_calculate>
4286 scaleX() - L<Imager::Transformations/scaleX>
4288 scaleY() - L<Imager::Transformations/scaleY>
4290 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4293 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4295 setmask() - L<Imager::ImageTypes/setmask>
4297 setpixel() - L<Imager::Draw/setpixel>
4299 setsamples() - L<Imager::Draw/setsamples>
4301 setscanline() - L<Imager::Draw/setscanline>
4303 settag() - L<Imager::ImageTypes/settag>
4305 string() - L<Imager::Draw/string> - draw text on an image
4307 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4309 to_paletted() - L<Imager::ImageTypes/to_paletted>
4311 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4313 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4315 transform() - L<Imager::Engines/"transform">
4317 transform2() - L<Imager::Engines/"transform2">
4319 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4321 unload_plugin() - L<Imager::Filters/unload_plugin>
4323 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4326 write() - L<Imager::Files> - write an image to a file
4328 write_multi() - L<Imager::Files> - write multiple image to an image
4331 write_types() - L<Imager::Files/read_types> - list image types Imager
4334 =head1 CONCEPT INDEX
4336 animated GIF - L<Imager::Files/"Writing an animated GIF">
4338 aspect ratio - L<Imager::ImageTypes/i_xres>,
4339 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4341 blend - alpha blending one image onto another
4342 L<Imager::Transformations/rubthrough>
4344 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4346 boxes, drawing - L<Imager::Draw/box>
4348 changes between image - L<Imager::Filters/"Image Difference">
4350 color - L<Imager::Color>
4352 color names - L<Imager::Color>, L<Imager::Color::Table>
4354 combine modes - L<Imager::Draw/"Combine Types">
4356 compare images - L<Imager::Filters/"Image Difference">
4358 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4360 convolution - L<Imager::Filters/conv>
4362 cropping - L<Imager::Transformations/crop>
4364 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4366 C<diff> images - L<Imager::Filters/"Image Difference">
4368 dpi - L<Imager::ImageTypes/i_xres>,
4369 L<Imager::Cookbook/"Image spatial resolution">
4371 drawing boxes - L<Imager::Draw/box>
4373 drawing lines - L<Imager::Draw/line>
4375 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4377 error message - L<"ERROR HANDLING">
4379 files, font - L<Imager::Font>
4381 files, image - L<Imager::Files>
4383 filling, types of fill - L<Imager::Fill>
4385 filling, boxes - L<Imager::Draw/box>
4387 filling, flood fill - L<Imager::Draw/flood_fill>
4389 flood fill - L<Imager::Draw/flood_fill>
4391 fonts - L<Imager::Font>
4393 fonts, drawing with - L<Imager::Draw/string>,
4394 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4396 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4398 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4400 fountain fill - L<Imager::Fill/"Fountain fills">,
4401 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4402 L<Imager::Filters/gradgen>
4404 GIF files - L<Imager::Files/"GIF">
4406 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4408 gradient fill - L<Imager::Fill/"Fountain fills">,
4409 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4410 L<Imager::Filters/gradgen>
4412 gray scale, convert image to - L<Imager::Transformations/convert>
4414 guassian blur - L<Imager::Filters/guassian>
4416 hatch fills - L<Imager::Fill/"Hatched fills">
4418 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4420 invert image - L<Imager::Filters/hardinvert>
4422 JPEG - L<Imager::Files/"JPEG">
4424 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4426 lines, drawing - L<Imager::Draw/line>
4428 matrix - L<Imager::Matrix2d>,
4429 L<Imager::Transformations/"Matrix Transformations">,
4430 L<Imager::Font/transform>
4432 metadata, image - L<Imager::ImageTypes/"Tags">
4434 mosaic - L<Imager::Filters/mosaic>
4436 noise, filter - L<Imager::Filters/noise>
4438 noise, rendered - L<Imager::Filters/turbnoise>,
4439 L<Imager::Filters/radnoise>
4441 paste - L<Imager::Transformations/paste>,
4442 L<Imager::Transformations/rubthrough>
4444 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4445 L<Imager::ImageTypes/new>
4447 =for stopwords posterize
4449 posterize - L<Imager::Filters/postlevels>
4451 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4453 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4455 rectangles, drawing - L<Imager::Draw/box>
4457 resizing an image - L<Imager::Transformations/scale>,
4458 L<Imager::Transformations/crop>
4460 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4462 saving an image - L<Imager::Files>
4464 scaling - L<Imager::Transformations/scale>
4466 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4468 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4470 size, image - L<Imager::ImageTypes/getwidth>,
4471 L<Imager::ImageTypes/getheight>
4473 size, text - L<Imager::Font/bounding_box>
4475 tags, image metadata - L<Imager::ImageTypes/"Tags">
4477 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4478 L<Imager::Font::Wrap>
4480 text, wrapping text in an area - L<Imager::Font::Wrap>
4482 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4484 tiles, color - L<Imager::Filters/mosaic>
4486 =for stopwords unsharp
4488 unsharp mask - L<Imager::Filters/unsharpmask>
4490 watermark - L<Imager::Filters/watermark>
4492 writing an image to a file - L<Imager::Files>
4496 Imager doesn't support perl threads.
4498 Imager has limited code to prevent double frees if you create images,
4499 colors etc, and then create a thread, but has no code to prevent two
4500 threads entering Imager's error handling code, and none is likely to
4505 The best place to get help with Imager is the mailing list.
4507 To subscribe send a message with C<subscribe> in the body to:
4509 imager-devel+request@molar.is
4515 L<http://www.molar.is/en/lists/imager-devel/>
4519 where you can also find the mailing list archive.
4521 You can report bugs by pointing your browser at:
4525 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4529 or by sending an email to:
4533 bug-Imager@rt.cpan.org
4537 Please remember to include the versions of Imager, perl, supporting
4538 libraries, and any relevant code. If you have specific images that
4539 cause the problems, please include those too.
4541 If you don't want to publish your email address on a mailing list you
4542 can use CPAN::Forum:
4544 http://www.cpanforum.com/dist/Imager
4546 You will need to register to post.
4548 =head1 CONTRIBUTING TO IMAGER
4554 If you like or dislike Imager, you can add a public review of Imager
4557 http://cpanratings.perl.org/dist/Imager
4559 =for stopwords Bitcard
4561 This requires a Bitcard account (http://www.bitcard.org).
4563 You can also send email to the maintainer below.
4565 If you send me a bug report via email, it will be copied to Request
4570 I accept patches, preferably against the main branch in subversion.
4571 You should include an explanation of the reason for why the patch is
4574 Your patch should include regression tests where possible, otherwise
4575 it will be delayed until I get a chance to write them.
4579 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4581 Arnar M. Hrafnkelsson is the original author of Imager.
4583 Many others have contributed to Imager, please see the C<README> for a
4588 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4589 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4590 L<Imager::Font>(3), L<Imager::Transformations>(3),
4591 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4592 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4594 L<http://imager.perl.org/>
4596 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4598 Other perl imaging modules include:
4600 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).