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();
3110 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
3112 unless (exists $opts{'x'} && exists $opts{'y'}) {
3113 $self->{ERRSTR} = 'missing x and y parameters';
3119 my $color = _color($opts{color})
3121 if (ref $x && ref $y) {
3122 unless (@$x == @$y) {
3123 $self->{ERRSTR} = 'length of x and y mismatch';
3127 if ($color->isa('Imager::Color')) {
3128 for my $i (0..$#{$opts{'x'}}) {
3129 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3134 for my $i (0..$#{$opts{'x'}}) {
3135 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3143 if ($color->isa('Imager::Color')) {
3144 i_ppix($self->{IMG}, $x, $y, $color)
3148 i_ppixf($self->{IMG}, $x, $y, $color)
3159 my %opts = ( "type"=>'8bit', @_);
3161 unless (exists $opts{'x'} && exists $opts{'y'}) {
3162 $self->{ERRSTR} = 'missing x and y parameters';
3168 if (ref $x && ref $y) {
3169 unless (@$x == @$y) {
3170 $self->{ERRSTR} = 'length of x and y mismatch';
3174 if ($opts{"type"} eq '8bit') {
3175 for my $i (0..$#{$opts{'x'}}) {
3176 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3180 for my $i (0..$#{$opts{'x'}}) {
3181 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3184 return wantarray ? @result : \@result;
3187 if ($opts{"type"} eq '8bit') {
3188 return i_get_pixel($self->{IMG}, $x, $y);
3191 return i_gpixf($self->{IMG}, $x, $y);
3200 my %opts = ( type => '8bit', x=>0, @_);
3202 $self->_valid_image or return;
3204 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3206 unless (defined $opts{'y'}) {
3207 $self->_set_error("missing y parameter");
3211 if ($opts{type} eq '8bit') {
3212 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3215 elsif ($opts{type} eq 'float') {
3216 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3219 elsif ($opts{type} eq 'index') {
3220 unless (i_img_type($self->{IMG})) {
3221 $self->_set_error("type => index only valid on paletted images");
3224 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3228 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3235 my %opts = ( x=>0, @_);
3237 $self->_valid_image or return;
3239 unless (defined $opts{'y'}) {
3240 $self->_set_error("missing y parameter");
3245 if (ref $opts{pixels} && @{$opts{pixels}}) {
3246 # try to guess the type
3247 if ($opts{pixels}[0]->isa('Imager::Color')) {
3248 $opts{type} = '8bit';
3250 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3251 $opts{type} = 'float';
3254 $self->_set_error("missing type parameter and could not guess from pixels");
3260 $opts{type} = '8bit';
3264 if ($opts{type} eq '8bit') {
3265 if (ref $opts{pixels}) {
3266 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3269 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3272 elsif ($opts{type} eq 'float') {
3273 if (ref $opts{pixels}) {
3274 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3277 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3280 elsif ($opts{type} eq 'index') {
3281 if (ref $opts{pixels}) {
3282 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3285 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3289 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3296 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3298 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3300 unless (defined $opts{'y'}) {
3301 $self->_set_error("missing y parameter");
3305 unless ($opts{channels}) {
3306 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3309 if ($opts{target}) {
3310 my $target = $opts{target};
3311 my $offset = $opts{offset};
3312 if ($opts{type} eq '8bit') {
3313 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3314 $opts{y}, @{$opts{channels}})
3316 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3317 return scalar(@samples);
3319 elsif ($opts{type} eq 'float') {
3320 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3321 $opts{y}, @{$opts{channels}});
3322 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3323 return scalar(@samples);
3325 elsif ($opts{type} =~ /^(\d+)bit$/) {
3329 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3330 $opts{y}, $bits, $target,
3331 $offset, @{$opts{channels}});
3332 unless (defined $count) {
3333 $self->_set_error(Imager->_error_as_msg);
3340 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3345 if ($opts{type} eq '8bit') {
3346 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3347 $opts{y}, @{$opts{channels}});
3349 elsif ($opts{type} eq 'float') {
3350 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3351 $opts{y}, @{$opts{channels}});
3353 elsif ($opts{type} =~ /^(\d+)bit$/) {
3357 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3358 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3363 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3371 my %opts = ( x => 0, offset => 0, @_ );
3373 unless ($self->{IMG}) {
3374 $self->_set_error('setsamples: empty input image');
3378 unless(defined $opts{data} && ref $opts{data}) {
3379 $self->_set_error('setsamples: data parameter missing or invalid');
3383 unless ($opts{channels}) {
3384 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3387 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3388 $self->_set_error('setsamples: type parameter missing or invalid');
3393 unless (defined $opts{width}) {
3394 $opts{width} = $self->getwidth() - $opts{x};
3397 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3398 $opts{channels}, $opts{data}, $opts{offset},
3400 unless (defined $count) {
3401 $self->_set_error(Imager->_error_as_msg);
3408 # make an identity matrix of the given size
3412 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3413 for my $c (0 .. ($size-1)) {
3414 $matrix->[$c][$c] = 1;
3419 # general function to convert an image
3421 my ($self, %opts) = @_;
3424 unless (defined wantarray) {
3425 my @caller = caller;
3426 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3430 # the user can either specify a matrix or preset
3431 # the matrix overrides the preset
3432 if (!exists($opts{matrix})) {
3433 unless (exists($opts{preset})) {
3434 $self->{ERRSTR} = "convert() needs a matrix or preset";
3438 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3439 # convert to greyscale, keeping the alpha channel if any
3440 if ($self->getchannels == 3) {
3441 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3443 elsif ($self->getchannels == 4) {
3444 # preserve the alpha channel
3445 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3450 $matrix = _identity($self->getchannels);
3453 elsif ($opts{preset} eq 'noalpha') {
3454 # strip the alpha channel
3455 if ($self->getchannels == 2 or $self->getchannels == 4) {
3456 $matrix = _identity($self->getchannels);
3457 pop(@$matrix); # lose the alpha entry
3460 $matrix = _identity($self->getchannels);
3463 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3465 $matrix = [ [ 1 ] ];
3467 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3468 $matrix = [ [ 0, 1 ] ];
3470 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3471 $matrix = [ [ 0, 0, 1 ] ];
3473 elsif ($opts{preset} eq 'alpha') {
3474 if ($self->getchannels == 2 or $self->getchannels == 4) {
3475 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3478 # the alpha is just 1 <shrug>
3479 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3482 elsif ($opts{preset} eq 'rgb') {
3483 if ($self->getchannels == 1) {
3484 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3486 elsif ($self->getchannels == 2) {
3487 # preserve the alpha channel
3488 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3491 $matrix = _identity($self->getchannels);
3494 elsif ($opts{preset} eq 'addalpha') {
3495 if ($self->getchannels == 1) {
3496 $matrix = _identity(2);
3498 elsif ($self->getchannels == 3) {
3499 $matrix = _identity(4);
3502 $matrix = _identity($self->getchannels);
3506 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3512 $matrix = $opts{matrix};
3515 my $new = Imager->new;
3516 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3517 unless ($new->{IMG}) {
3518 # most likely a bad matrix
3519 $self->{ERRSTR} = _error_as_msg();
3526 # general function to map an image through lookup tables
3529 my ($self, %opts) = @_;
3530 my @chlist = qw( red green blue alpha );
3532 if (!exists($opts{'maps'})) {
3533 # make maps from channel maps
3535 for $chnum (0..$#chlist) {
3536 if (exists $opts{$chlist[$chnum]}) {
3537 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3538 } elsif (exists $opts{'all'}) {
3539 $opts{'maps'}[$chnum] = $opts{'all'};
3543 if ($opts{'maps'} and $self->{IMG}) {
3544 i_map($self->{IMG}, $opts{'maps'} );
3550 my ($self, %opts) = @_;
3552 defined $opts{mindist} or $opts{mindist} = 0;
3554 defined $opts{other}
3555 or return $self->_set_error("No 'other' parameter supplied");
3556 defined $opts{other}{IMG}
3557 or return $self->_set_error("No image data in 'other' image");
3560 or return $self->_set_error("No image data");
3562 my $result = Imager->new;
3563 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3565 or return $self->_set_error($self->_error_as_msg());
3570 # destructive border - image is shrunk by one pixel all around
3573 my ($self,%opts)=@_;
3574 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3575 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3579 # Get the width of an image
3583 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3584 return (i_img_info($self->{IMG}))[0];
3587 # Get the height of an image
3591 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3592 return (i_img_info($self->{IMG}))[1];
3595 # Get number of channels in an image
3599 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3600 return i_img_getchannels($self->{IMG});
3607 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3608 return i_img_getmask($self->{IMG});
3616 if (!defined($self->{IMG})) {
3617 $self->{ERRSTR} = 'image is empty';
3620 unless (defined $opts{mask}) {
3621 $self->_set_error("mask parameter required");
3624 i_img_setmask( $self->{IMG} , $opts{mask} );
3629 # Get number of colors in an image
3633 my %opts=('maxcolors'=>2**30,@_);
3634 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3635 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3636 return ($rc==-1? undef : $rc);
3639 # Returns a reference to a hash. The keys are colour named (packed) and the
3640 # values are the number of pixels in this colour.
3641 sub getcolorusagehash {
3644 my %opts = ( maxcolors => 2**30, @_ );
3645 my $max_colors = $opts{maxcolors};
3646 unless (defined $max_colors && $max_colors > 0) {
3647 $self->_set_error('maxcolors must be a positive integer');
3651 unless (defined $self->{IMG}) {
3652 $self->_set_error('empty input image');
3656 my $channels= $self->getchannels;
3657 # We don't want to look at the alpha channel, because some gifs using it
3658 # doesn't define it for every colour (but only for some)
3659 $channels -= 1 if $channels == 2 or $channels == 4;
3661 my $height = $self->getheight;
3662 for my $y (0 .. $height - 1) {
3663 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3664 while (length $colors) {
3665 $color_use{ substr($colors, 0, $channels, '') }++;
3667 keys %color_use > $max_colors
3673 # This will return a ordered array of the colour usage. Kind of the sorted
3674 # version of the values of the hash returned by getcolorusagehash.
3675 # You might want to add safety checks and change the names, etc...
3679 my %opts = ( maxcolors => 2**30, @_ );
3680 my $max_colors = $opts{maxcolors};
3681 unless (defined $max_colors && $max_colors > 0) {
3682 $self->_set_error('maxcolors must be a positive integer');
3686 unless (defined $self->{IMG}) {
3687 $self->_set_error('empty input image');
3691 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3694 # draw string to an image
3698 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3700 my %input=('x'=>0, 'y'=>0, @_);
3701 defined($input{string}) or $input{string} = $input{text};
3703 unless(defined $input{string}) {
3704 $self->{ERRSTR}="missing required parameter 'string'";
3708 unless($input{font}) {
3709 $self->{ERRSTR}="missing required parameter 'font'";
3713 unless ($input{font}->draw(image=>$self, %input)) {
3725 unless ($self->{IMG}) {
3726 $self->{ERRSTR}='empty input image';
3735 my %input=('x'=>0, 'y'=>0, @_);
3736 $input{string}||=$input{text};
3738 unless(exists $input{string}) {
3739 $self->_set_error("missing required parameter 'string'");
3743 unless($input{font}) {
3744 $self->_set_error("missing required parameter 'font'");
3749 unless (@result = $input{font}->align(image=>$img, %input)) {
3753 return wantarray ? @result : $result[0];
3756 my @file_limit_names = qw/width height bytes/;
3758 sub set_file_limits {
3765 @values{@file_limit_names} = (0) x @file_limit_names;
3768 @values{@file_limit_names} = i_get_image_file_limits();
3771 for my $key (keys %values) {
3772 defined $opts{$key} and $values{$key} = $opts{$key};
3775 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3778 sub get_file_limits {
3779 i_get_image_file_limits();
3782 # Shortcuts that can be exported
3784 sub newcolor { Imager::Color->new(@_); }
3785 sub newfont { Imager::Font->new(@_); }
3786 sub NCF { Imager::Color::Float->new(@_) }
3788 *NC=*newcolour=*newcolor;
3795 #### Utility routines
3798 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3802 my ($self, $msg) = @_;
3805 $self->{ERRSTR} = $msg;
3813 # Default guess for the type of an image from extension
3815 sub def_guess_type {
3818 $ext=($name =~ m/\.([^\.]+)$/)[0];
3819 return 'tiff' if ($ext =~ m/^tiff?$/);
3820 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3821 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3822 return 'png' if ($ext eq "png");
3823 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3824 return 'tga' if ($ext eq "tga");
3825 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3826 return 'gif' if ($ext eq "gif");
3827 return 'raw' if ($ext eq "raw");
3828 return lc $ext; # best guess
3833 return @combine_types;
3836 # get the minimum of a list
3840 for(@_) { if ($_<$mx) { $mx=$_; }}
3844 # get the maximum of a list
3848 for(@_) { if ($_>$mx) { $mx=$_; }}
3852 # string stuff for iptc headers
3856 $str = substr($str,3);
3857 $str =~ s/[\n\r]//g;
3864 # A little hack to parse iptc headers.
3869 my($caption,$photogr,$headln,$credit);
3871 my $str=$self->{IPTCRAW};
3876 @ar=split(/8BIM/,$str);
3881 @sar=split(/\034\002/);
3882 foreach $item (@sar) {
3883 if ($item =~ m/^x/) {
3884 $caption = _clean($item);
3887 if ($item =~ m/^P/) {
3888 $photogr = _clean($item);
3891 if ($item =~ m/^i/) {
3892 $headln = _clean($item);
3895 if ($item =~ m/^n/) {
3896 $credit = _clean($item);
3902 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3909 or die "Only C language supported";
3911 require Imager::ExtUtils;
3912 return Imager::ExtUtils->inline_config;
3915 # threads shouldn't try to close raw Imager objects
3916 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3920 # Below is the stub of documentation for your module. You better edit it!
3924 Imager - Perl extension for Generating 24 bit Images
3934 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3939 # see Imager::Files for information on the read() method
3940 my $im = Imager->new(file=>$file)
3941 or die Imager->errstr();
3943 $file =~ s/\.[^.]*$//;
3945 # Create smaller version
3946 # documented in Imager::Transformations
3947 my $thumb = $img->scale(scalefactor=>.3);
3949 # Autostretch individual channels
3950 $thumb->filter(type=>'autolevels');
3952 # try to save in one of these formats
3955 for $format ( qw( png gif jpeg tiff ppm ) ) {
3956 # Check if given format is supported
3957 if ($Imager::formats{$format}) {
3958 $file.="_low.$format";
3959 print "Storing image as: $file\n";
3960 # documented in Imager::Files
3961 $thumb->write(file=>$file) or
3969 Imager is a module for creating and altering images. It can read and
3970 write various image formats, draw primitive shapes like lines,and
3971 polygons, blend multiple images together in various ways, scale, crop,
3972 render text and more.
3974 =head2 Overview of documentation
3980 Imager - This document - Synopsis, Example, Table of Contents and
3985 L<Imager::Tutorial> - a brief introduction to Imager.
3989 L<Imager::Cookbook> - how to do various things with Imager.
3993 L<Imager::ImageTypes> - Basics of constructing image objects with
3994 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3995 8/16/double bits/channel, color maps, channel masks, image tags, color
3996 quantization. Also discusses basic image information methods.
4000 L<Imager::Files> - IO interaction, reading/writing images, format
4005 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4010 L<Imager::Color> - Color specification.
4014 L<Imager::Fill> - Fill pattern specification.
4018 L<Imager::Font> - General font rendering, bounding boxes and font
4023 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4024 blending, pasting, convert and map.
4028 L<Imager::Engines> - Programmable transformations through
4029 C<transform()>, C<transform2()> and C<matrix_transform()>.
4033 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4038 L<Imager::Expr> - Expressions for evaluation engine used by
4043 L<Imager::Matrix2d> - Helper class for affine transformations.
4047 L<Imager::Fountain> - Helper for making gradient profiles.
4051 L<Imager::API> - using Imager's C API
4055 L<Imager::APIRef> - API function reference
4059 L<Imager::Inline> - using Imager's C API from Inline::C
4063 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4067 =head2 Basic Overview
4069 An Image object is created with C<$img = Imager-E<gt>new()>.
4072 $img=Imager->new(); # create empty image
4073 $img->read(file=>'lena.png',type=>'png') or # read image from file
4074 die $img->errstr(); # give an explanation
4075 # if something failed
4077 or if you want to create an empty image:
4079 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4081 This example creates a completely black image of width 400 and height
4084 =head1 ERROR HANDLING
4086 In general a method will return false when it fails, if it does use
4087 the C<errstr()> method to find out why:
4093 Returns the last error message in that context.
4095 If the last error you received was from calling an object method, such
4096 as read, call errstr() as an object method to find out why:
4098 my $image = Imager->new;
4099 $image->read(file => 'somefile.gif')
4100 or die $image->errstr;
4102 If it was a class method then call errstr() as a class method:
4104 my @imgs = Imager->read_multi(file => 'somefile.gif')
4105 or die Imager->errstr;
4107 Note that in some cases object methods are implemented in terms of
4108 class methods so a failing object method may set both.
4112 The C<Imager-E<gt>new> method is described in detail in
4113 L<Imager::ImageTypes>.
4117 Where to find information on methods for Imager class objects.
4119 addcolors() - L<Imager::ImageTypes/addcolors> - add colors to a
4122 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4124 align_string() - L<Imager::Draw/align_string> - draw text aligned on a
4127 arc() - L<Imager::Draw/arc> - draw a filled arc
4129 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4132 box() - L<Imager::Draw/box> - draw a filled or outline box.
4134 circle() - L<Imager::Draw/circle> - draw a filled circle
4136 colorcount() - L<Imager::Draw/colorcount> - the number of colors in an
4137 image's palette (paletted images only)
4139 combines() - L<Imager::Draw/combines> - return a list of the different
4140 combine type keywords
4142 compose() - L<Imager::Transformations/compose> - compose one image
4145 convert() - L<Imager::Transformations/"Color transformations"> -
4146 transform the color space
4148 copy() - L<Imager::Transformations/copy> - make a duplicate of an
4151 crop() - L<Imager::Transformations/crop> - extract part of an image
4153 def_guess_type() - L<Imager::Files/def_guess_type> - default function
4154 used to guess the output file format based on the output file name
4156 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4158 difference() - L<Imager::Filters/"Image Difference"> - produce a
4159 difference images from two input images.
4161 errstr() - L<"Basic Overview"> - the error from the last failed
4164 filter() - L<Imager::Filters> - image filtering
4166 findcolor() - L<Imager::ImageTypes/findcolor> - search the image
4167 palette, if it has one
4169 flip() - L<Imager::Transformations/flip> - flip an image, vertically,
4172 flood_fill() - L<Imager::Draw/flood_fill> - fill an enclosed or same
4175 getchannels() - L<Imager::ImageTypes/getchannels> - the number of
4176 samples per pixel for an image
4178 getcolorcount() - L<Imager::ImageTypes/getcolorcount> - the number of
4179 different colors used by an image (works for direct color images)
4181 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4182 palette, if it has one
4184 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4186 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4188 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4190 getheight() - L<Imager::ImageTypes/getwidth> - height of the image in
4193 getmask() - L<Imager::ImageTypes/getmask> - write mask for the image
4195 getpixel() - L<Imager::Draw/getpixel> - retrieve one or more pixel
4198 getsamples() - L<Imager::Draw/getsamples> - retrieve samples from a
4199 row or partial row of pixels.
4201 getscanline() - L<Imager::Draw/getscanline> - retrieve colors for a
4202 row or partial row of pixels.
4204 getwidth() - L<Imager::ImageTypes/getwidth> - width of the image in
4207 img_set() - L<Imager::ImageTypes/img_set> - re-use an Imager object
4210 init() - L<Imager::ImageTypes/init>
4212 is_bilevel() - L<Imager::ImageTypes/is_bilevel> - returns whether
4213 image write functions should write the image in their bilevel (blank
4214 and white, no gray levels) format
4216 line() - L<Imager::Draw/line> - draw an interval
4218 load_plugin() - L<Imager::Filters/load_plugin>
4220 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4223 masked() - L<Imager::ImageTypes/masked> - make a masked image
4225 matrix_transform() - L<Imager::Engines/matrix_transform>
4227 maxcolors() - L<Imager::ImageTypes/maxcolors>
4229 NC() - L<Imager::Handy/NC>
4231 NCF() - L<Imager::Handy/NCF>
4233 new() - L<Imager::ImageTypes/new>
4235 newcolor() - L<Imager::Handy/newcolor>
4237 newcolour() - L<Imager::Handy/newcolour>
4239 newfont() - L<Imager::Handy/newfont>
4241 NF() - L<Imager::Handy/NF>
4243 open() - L<Imager::Files> - an alias for read()
4247 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4250 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4252 polygon() - L<Imager::Draw/polygon>
4254 polyline() - L<Imager::Draw/polyline>
4256 read() - L<Imager::Files> - read a single image from an image file
4258 read_multi() - L<Imager::Files> - read multiple images from an image
4261 read_types() - L<Imager::Files/read_types> - list image types Imager
4264 register_filter() - L<Imager::Filters/register_filter>
4266 register_reader() - L<Imager::Files/register_reader>
4268 register_writer() - L<Imager::Files/register_writer>
4270 rotate() - L<Imager::Transformations/rotate>
4272 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4273 image and use the alpha channel
4275 scale() - L<Imager::Transformations/scale>
4277 scale_calculate() - L<Imager::Transformations/scale_calculate>
4279 scaleX() - L<Imager::Transformations/scaleX>
4281 scaleY() - L<Imager::Transformations/scaleY>
4283 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4286 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4288 setmask() - L<Imager::ImageTypes/setmask>
4290 setpixel() - L<Imager::Draw/setpixel>
4292 setsamples() - L<Imager::Draw/setsamples>
4294 setscanline() - L<Imager::Draw/setscanline>
4296 settag() - L<Imager::ImageTypes/settag>
4298 string() - L<Imager::Draw/string> - draw text on an image
4300 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4302 to_paletted() - L<Imager::ImageTypes/to_paletted>
4304 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4306 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4308 transform() - L<Imager::Engines/"transform">
4310 transform2() - L<Imager::Engines/"transform2">
4312 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4314 unload_plugin() - L<Imager::Filters/unload_plugin>
4316 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4319 write() - L<Imager::Files> - write an image to a file
4321 write_multi() - L<Imager::Files> - write multiple image to an image
4324 write_types() - L<Imager::Files/read_types> - list image types Imager
4327 =head1 CONCEPT INDEX
4329 animated GIF - L<Imager::Files/"Writing an animated GIF">
4331 aspect ratio - L<Imager::ImageTypes/i_xres>,
4332 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4334 blend - alpha blending one image onto another
4335 L<Imager::Transformations/rubthrough>
4337 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4339 boxes, drawing - L<Imager::Draw/box>
4341 changes between image - L<Imager::Filters/"Image Difference">
4343 color - L<Imager::Color>
4345 color names - L<Imager::Color>, L<Imager::Color::Table>
4347 combine modes - L<Imager::Draw/"Combine Types">
4349 compare images - L<Imager::Filters/"Image Difference">
4351 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4353 convolution - L<Imager::Filters/conv>
4355 cropping - L<Imager::Transformations/crop>
4357 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4359 C<diff> images - L<Imager::Filters/"Image Difference">
4361 dpi - L<Imager::ImageTypes/i_xres>,
4362 L<Imager::Cookbook/"Image spatial resolution">
4364 drawing boxes - L<Imager::Draw/box>
4366 drawing lines - L<Imager::Draw/line>
4368 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4370 error message - L<"ERROR HANDLING">
4372 files, font - L<Imager::Font>
4374 files, image - L<Imager::Files>
4376 filling, types of fill - L<Imager::Fill>
4378 filling, boxes - L<Imager::Draw/box>
4380 filling, flood fill - L<Imager::Draw/flood_fill>
4382 flood fill - L<Imager::Draw/flood_fill>
4384 fonts - L<Imager::Font>
4386 fonts, drawing with - L<Imager::Draw/string>,
4387 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4389 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4391 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4393 fountain fill - L<Imager::Fill/"Fountain fills">,
4394 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4395 L<Imager::Filters/gradgen>
4397 GIF files - L<Imager::Files/"GIF">
4399 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4401 gradient fill - L<Imager::Fill/"Fountain fills">,
4402 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4403 L<Imager::Filters/gradgen>
4405 gray scale, convert image to - L<Imager::Transformations/convert>
4407 guassian blur - L<Imager::Filters/guassian>
4409 hatch fills - L<Imager::Fill/"Hatched fills">
4411 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4413 invert image - L<Imager::Filters/hardinvert>
4415 JPEG - L<Imager::Files/"JPEG">
4417 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4419 lines, drawing - L<Imager::Draw/line>
4421 matrix - L<Imager::Matrix2d>,
4422 L<Imager::Transformations/"Matrix Transformations">,
4423 L<Imager::Font/transform>
4425 metadata, image - L<Imager::ImageTypes/"Tags">
4427 mosaic - L<Imager::Filters/mosaic>
4429 noise, filter - L<Imager::Filters/noise>
4431 noise, rendered - L<Imager::Filters/turbnoise>,
4432 L<Imager::Filters/radnoise>
4434 paste - L<Imager::Transformations/paste>,
4435 L<Imager::Transformations/rubthrough>
4437 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4438 L<Imager::ImageTypes/new>
4440 =for stopwords posterize
4442 posterize - L<Imager::Filters/postlevels>
4444 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4446 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4448 rectangles, drawing - L<Imager::Draw/box>
4450 resizing an image - L<Imager::Transformations/scale>,
4451 L<Imager::Transformations/crop>
4453 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4455 saving an image - L<Imager::Files>
4457 scaling - L<Imager::Transformations/scale>
4459 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4461 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4463 size, image - L<Imager::ImageTypes/getwidth>,
4464 L<Imager::ImageTypes/getheight>
4466 size, text - L<Imager::Font/bounding_box>
4468 tags, image metadata - L<Imager::ImageTypes/"Tags">
4470 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4471 L<Imager::Font::Wrap>
4473 text, wrapping text in an area - L<Imager::Font::Wrap>
4475 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4477 tiles, color - L<Imager::Filters/mosaic>
4479 =for stopwords unsharp
4481 unsharp mask - L<Imager::Filters/unsharpmask>
4483 watermark - L<Imager::Filters/watermark>
4485 writing an image to a file - L<Imager::Files>
4489 Imager doesn't support perl threads.
4491 Imager has limited code to prevent double frees if you create images,
4492 colors etc, and then create a thread, but has no code to prevent two
4493 threads entering Imager's error handling code, and none is likely to
4498 The best place to get help with Imager is the mailing list.
4500 To subscribe send a message with C<subscribe> in the body to:
4502 imager-devel+request@molar.is
4508 L<http://www.molar.is/en/lists/imager-devel/>
4512 where you can also find the mailing list archive.
4514 You can report bugs by pointing your browser at:
4518 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4522 or by sending an email to:
4526 bug-Imager@rt.cpan.org
4530 Please remember to include the versions of Imager, perl, supporting
4531 libraries, and any relevant code. If you have specific images that
4532 cause the problems, please include those too.
4534 If you don't want to publish your email address on a mailing list you
4535 can use CPAN::Forum:
4537 http://www.cpanforum.com/dist/Imager
4539 You will need to register to post.
4541 =head1 CONTRIBUTING TO IMAGER
4547 If you like or dislike Imager, you can add a public review of Imager
4550 http://cpanratings.perl.org/dist/Imager
4552 =for stopwords Bitcard
4554 This requires a Bitcard account (http://www.bitcard.org).
4556 You can also send email to the maintainer below.
4558 If you send me a bug report via email, it will be copied to Request
4563 I accept patches, preferably against the main branch in subversion.
4564 You should include an explanation of the reason for why the patch is
4567 Your patch should include regression tests where possible, otherwise
4568 it will be delayed until I get a chance to write them.
4572 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4574 Arnar M. Hrafnkelsson is the original author of Imager.
4576 Many others have contributed to Imager, please see the C<README> for a
4581 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4582 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4583 L<Imager::Font>(3), L<Imager::Transformations>(3),
4584 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4585 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4587 L<http://imager.perl.org/>
4589 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4591 Other perl imaging modules include:
4593 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).