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/;
166 XSLoader::load(Imager => $VERSION);
170 push @ISA, 'DynaLoader';
171 bootstrap Imager $VERSION;
176 Imager::Font::__init();
177 for(i_list_formats()) { $formats{$_}++; }
179 if (!$formats{'t1'} and !$formats{'tt'}
180 && !$formats{'ft2'} && !$formats{'w32'}) {
181 $fontstate='no font support';
184 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
188 # the members of the subhashes under %filters are:
189 # callseq - a list of the parameters to the underlying filter in the
190 # order they are passed
191 # callsub - a code ref that takes a named parameter list and calls the
193 # defaults - a hash of default values
194 # names - defines names for value of given parameters so if the names
195 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
196 # foo parameter, the filter will receive 1 for the foo
199 callseq => ['image','intensity'],
200 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
204 callseq => ['image', 'amount', 'subtype'],
205 defaults => { amount=>3,subtype=>0 },
206 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
209 $filters{hardinvert} ={
210 callseq => ['image'],
212 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
215 $filters{autolevels} ={
216 callseq => ['image','lsat','usat','skew'],
217 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
218 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
221 $filters{turbnoise} ={
222 callseq => ['image'],
223 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
224 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
227 $filters{radnoise} ={
228 callseq => ['image'],
229 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
230 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
234 callseq => ['image', 'coef'],
236 callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
241 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
242 defaults => { dist => 0 },
246 my @colors = @{$hsh{colors}};
249 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
253 $filters{nearest_color} =
255 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
260 # make sure the segments are specified with colors
262 for my $color (@{$hsh{colors}}) {
263 my $new_color = _color($color)
264 or die $Imager::ERRSTR."\n";
265 push @colors, $new_color;
268 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
270 or die Imager->_error_as_msg() . "\n";
273 $filters{gaussian} = {
274 callseq => [ 'image', 'stddev' ],
276 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
280 callseq => [ qw(image size) ],
281 defaults => { size => 20 },
282 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
286 callseq => [ qw(image bump elevation lightx lighty st) ],
287 defaults => { elevation=>0, st=> 2 },
290 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
291 $hsh{lightx}, $hsh{lighty}, $hsh{st});
294 $filters{bumpmap_complex} =
296 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
307 Ia => Imager::Color->new(rgb=>[0,0,0]),
308 Il => Imager::Color->new(rgb=>[255,255,255]),
309 Is => Imager::Color->new(rgb=>[255,255,255]),
313 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
314 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
315 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
319 $filters{postlevels} =
321 callseq => [ qw(image levels) ],
322 defaults => { levels => 10 },
323 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
325 $filters{watermark} =
327 callseq => [ qw(image wmark tx ty pixdiff) ],
328 defaults => { pixdiff=>10, tx=>0, ty=>0 },
332 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
338 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
340 ftype => { linear => 0,
346 repeat => { none => 0,
361 multiply => 2, mult => 2,
364 subtract => 5, 'sub' => 5,
374 defaults => { ftype => 0, repeat => 0, combine => 0,
375 super_sample => 0, ssample_param => 4,
378 Imager::Color->new(0,0,0),
379 Imager::Color->new(255, 255, 255),
388 # make sure the segments are specified with colors
390 for my $segment (@{$hsh{segments}}) {
391 my @new_segment = @$segment;
393 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
394 push @segments, \@new_segment;
397 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
398 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
399 $hsh{ssample_param}, \@segments)
400 or die Imager->_error_as_msg() . "\n";
403 $filters{unsharpmask} =
405 callseq => [ qw(image stddev scale) ],
406 defaults => { stddev=>2.0, scale=>1.0 },
410 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
414 $FORMATGUESS=\&def_guess_type;
424 # NOTE: this might be moved to an import override later on
429 if ($_[$i] eq '-log-stderr') {
437 goto &Exporter::import;
441 i_init_log($_[0],$_[1]);
442 i_log_entry("Imager $VERSION starting\n", 1);
447 my %parms=(loglevel=>1,@_);
449 init_log($parms{'log'},$parms{'loglevel'});
452 if (exists $parms{'warn_obsolete'}) {
453 $warn_obsolete = $parms{'warn_obsolete'};
456 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
457 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
461 if (exists $parms{'t1log'}) {
462 i_init_fonts($parms{'t1log'});
468 print "shutdown code\n";
469 # for(keys %instances) { $instances{$_}->DESTROY(); }
470 malloc_state(); # how do decide if this should be used? -- store something from the import
471 print "Imager exiting\n";
475 # Load a filter plugin
480 my ($DSO_handle,$str)=DSO_open($filename);
481 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
482 my %funcs=DSO_funclist($DSO_handle);
483 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
485 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
487 $DSOs{$filename}=[$DSO_handle,\%funcs];
490 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
491 $DEBUG && print "eval string:\n",$evstr,"\n";
503 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
504 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
505 for(keys %{$funcref}) {
507 $DEBUG && print "unloading: $_\n";
509 my $rc=DSO_close($DSO_handle);
510 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
514 # take the results of i_error() and make a message out of it
516 return join(": ", map $_->[0], i_errors());
519 # this function tries to DWIM for color parameters
520 # color objects are used as is
521 # simple scalars are simply treated as single parameters to Imager::Color->new
522 # hashrefs are treated as named argument lists to Imager::Color->new
523 # arrayrefs are treated as list arguments to Imager::Color->new iff any
525 # other arrayrefs are treated as list arguments to Imager::Color::Float
529 # perl 5.6.0 seems to do weird things to $arg if we don't make an
530 # explicitly stringified copy
531 # I vaguely remember a bug on this on p5p, but couldn't find it
532 # through bugs.perl.org (I had trouble getting it to find any bugs)
533 my $copy = $arg . "";
537 if (UNIVERSAL::isa($arg, "Imager::Color")
538 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
542 if ($copy =~ /^HASH\(/) {
543 $result = Imager::Color->new(%$arg);
545 elsif ($copy =~ /^ARRAY\(/) {
546 $result = Imager::Color->new(@$arg);
549 $Imager::ERRSTR = "Not a color";
554 # assume Imager::Color::new knows how to handle it
555 $result = Imager::Color->new($arg);
564 $self->{IMG} and return 1;
566 $self->_set_error('empty input image');
572 # Methods to be called on objects.
575 # Create a new Imager object takes very few parameters.
576 # usually you call this method and then call open from
577 # the resulting object
584 $self->{IMG}=undef; # Just to indicate what exists
585 $self->{ERRSTR}=undef; #
586 $self->{DEBUG}=$DEBUG;
587 $self->{DEBUG} && print "Initialized Imager\n";
588 if (defined $hsh{xsize} && defined $hsh{ysize}) {
589 unless ($self->img_set(%hsh)) {
590 $Imager::ERRSTR = $self->{ERRSTR};
597 # Copy an entire image with no changes
598 # - if an image has magic the copy of it will not be magical
602 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
604 unless (defined wantarray) {
606 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
610 my $newcopy=Imager->new();
611 $newcopy->{IMG} = i_copy($self->{IMG});
620 unless ($self->{IMG}) {
621 $self->_set_error('empty input image');
624 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
625 my $src = $input{img} || $input{src};
627 $self->_set_error("no source image");
630 $input{left}=0 if $input{left} <= 0;
631 $input{top}=0 if $input{top} <= 0;
633 my($r,$b)=i_img_info($src->{IMG});
634 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
635 my ($src_right, $src_bottom);
636 if ($input{src_coords}) {
637 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
640 if (defined $input{src_maxx}) {
641 $src_right = $input{src_maxx};
643 elsif (defined $input{width}) {
644 if ($input{width} <= 0) {
645 $self->_set_error("paste: width must me positive");
648 $src_right = $src_left + $input{width};
653 if (defined $input{src_maxy}) {
654 $src_bottom = $input{src_maxy};
656 elsif (defined $input{height}) {
657 if ($input{height} < 0) {
658 $self->_set_error("paste: height must be positive");
661 $src_bottom = $src_top + $input{height};
668 $src_right > $r and $src_right = $r;
669 $src_bottom > $b and $src_bottom = $b;
671 if ($src_right <= $src_left
672 || $src_bottom < $src_top) {
673 $self->_set_error("nothing to paste");
677 i_copyto($self->{IMG}, $src->{IMG},
678 $src_left, $src_top, $src_right, $src_bottom,
679 $input{left}, $input{top});
681 return $self; # What should go here??
684 # Crop an image - i.e. return a new image that is smaller
688 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
690 unless (defined wantarray) {
692 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
698 my ($w, $h, $l, $r, $b, $t) =
699 @hsh{qw(width height left right bottom top)};
701 # work through the various possibilities
706 elsif (!defined $r) {
707 $r = $self->getwidth;
719 $l = int(0.5+($self->getwidth()-$w)/2);
724 $r = $self->getwidth;
730 elsif (!defined $b) {
731 $b = $self->getheight;
743 $t=int(0.5+($self->getheight()-$h)/2);
748 $b = $self->getheight;
751 ($l,$r)=($r,$l) if $l>$r;
752 ($t,$b)=($b,$t) if $t>$b;
755 $r > $self->getwidth and $r = $self->getwidth;
757 $b > $self->getheight and $b = $self->getheight;
759 if ($l == $r || $t == $b) {
760 $self->_set_error("resulting image would have no content");
763 if( $r < $l or $b < $t ) {
764 $self->_set_error("attempting to crop outside of the image");
767 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
769 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
774 my ($self, %opts) = @_;
776 $self->{IMG} or return $self->_set_error("Not a valid image");
778 my $x = $opts{xsize} || $self->getwidth;
779 my $y = $opts{ysize} || $self->getheight;
780 my $channels = $opts{channels} || $self->getchannels;
782 my $out = Imager->new;
783 if ($channels == $self->getchannels) {
784 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
787 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
789 unless ($out->{IMG}) {
790 $self->{ERRSTR} = $self->_error_as_msg;
797 # Sets an image to a certain size and channel number
798 # if there was previously data in the image it is discarded
803 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
805 if (defined($self->{IMG})) {
806 # let IIM_DESTROY destroy it, it's possible this image is
807 # referenced from a virtual image (like masked)
808 #i_img_destroy($self->{IMG});
812 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
813 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
814 $hsh{maxcolors} || 256);
816 elsif ($hsh{bits} eq 'double') {
817 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
819 elsif ($hsh{bits} == 16) {
820 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
823 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
827 unless ($self->{IMG}) {
828 $self->{ERRSTR} = Imager->_error_as_msg();
835 # created a masked version of the current image
839 $self or return undef;
840 my %opts = (left => 0,
842 right => $self->getwidth,
843 bottom => $self->getheight,
845 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
847 my $result = Imager->new;
848 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
849 $opts{top}, $opts{right} - $opts{left},
850 $opts{bottom} - $opts{top});
851 # keep references to the mask and base images so they don't
853 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
858 # convert an RGB image into a paletted image
862 if (@_ != 1 && !ref $_[0]) {
869 unless (defined wantarray) {
871 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
875 my $result = Imager->new;
876 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
878 #print "Type ", i_img_type($result->{IMG}), "\n";
880 if ($result->{IMG}) {
884 $self->{ERRSTR} = $self->_error_as_msg;
889 # convert a paletted (or any image) to an 8-bit/channel RGB images
894 unless (defined wantarray) {
896 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
901 $result = Imager->new;
902 $result->{IMG} = i_img_to_rgb($self->{IMG})
909 # convert a paletted (or any image) to an 8-bit/channel RGB images
914 unless (defined wantarray) {
916 warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
921 $result = Imager->new;
922 $result->{IMG} = i_img_to_rgb16($self->{IMG})
931 my %opts = (colors=>[], @_);
933 unless ($self->{IMG}) {
934 $self->_set_error("empty input image");
938 my @colors = @{$opts{colors}}
941 for my $color (@colors) {
942 $color = _color($color);
944 $self->_set_error($Imager::ERRSTR);
949 return i_addcolors($self->{IMG}, @colors);
954 my %opts = (start=>0, colors=>[], @_);
956 unless ($self->{IMG}) {
957 $self->_set_error("empty input image");
961 my @colors = @{$opts{colors}}
964 for my $color (@colors) {
965 $color = _color($color);
967 $self->_set_error($Imager::ERRSTR);
972 return i_setcolors($self->{IMG}, $opts{start}, @colors);
978 if (!exists $opts{start} && !exists $opts{count}) {
981 $opts{count} = $self->colorcount;
983 elsif (!exists $opts{count}) {
986 elsif (!exists $opts{start}) {
991 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
995 i_colorcount($_[0]{IMG});
999 i_maxcolors($_[0]{IMG});
1005 $opts{color} or return undef;
1007 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1012 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1013 if ($bits && $bits == length(pack("d", 1)) * 8) {
1022 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1028 $self->{IMG} and i_img_virtual($self->{IMG});
1034 $self->{IMG} or return;
1036 return i_img_is_monochrome($self->{IMG});
1040 my ($self, %opts) = @_;
1042 $self->{IMG} or return;
1044 if (defined $opts{name}) {
1048 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1049 push @result, (i_tags_get($self->{IMG}, $found))[1];
1052 return wantarray ? @result : $result[0];
1054 elsif (defined $opts{code}) {
1058 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1059 push @result, (i_tags_get($self->{IMG}, $found))[1];
1066 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1069 return i_tags_count($self->{IMG});
1078 return -1 unless $self->{IMG};
1080 if (defined $opts{value}) {
1081 if ($opts{value} =~ /^\d+$/) {
1083 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1086 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1089 elsif (defined $opts{data}) {
1090 # force addition as a string
1091 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1094 $self->{ERRSTR} = "No value supplied";
1098 elsif ($opts{code}) {
1099 if (defined $opts{value}) {
1100 if ($opts{value} =~ /^\d+$/) {
1102 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1105 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1108 elsif (defined $opts{data}) {
1109 # force addition as a string
1110 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1113 $self->{ERRSTR} = "No value supplied";
1126 return 0 unless $self->{IMG};
1128 if (defined $opts{'index'}) {
1129 return i_tags_delete($self->{IMG}, $opts{'index'});
1131 elsif (defined $opts{name}) {
1132 return i_tags_delbyname($self->{IMG}, $opts{name});
1134 elsif (defined $opts{code}) {
1135 return i_tags_delbycode($self->{IMG}, $opts{code});
1138 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1144 my ($self, %opts) = @_;
1147 $self->deltag(name=>$opts{name});
1148 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1150 elsif (defined $opts{code}) {
1151 $self->deltag(code=>$opts{code});
1152 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1160 sub _get_reader_io {
1161 my ($self, $input) = @_;
1164 return $input->{io}, undef;
1166 elsif ($input->{fd}) {
1167 return io_new_fd($input->{fd});
1169 elsif ($input->{fh}) {
1170 my $fd = fileno($input->{fh});
1172 $self->_set_error("Handle in fh option not opened");
1175 return io_new_fd($fd);
1177 elsif ($input->{file}) {
1178 my $file = IO::File->new($input->{file}, "r");
1180 $self->_set_error("Could not open $input->{file}: $!");
1184 return (io_new_fd(fileno($file)), $file);
1186 elsif ($input->{data}) {
1187 return io_new_buffer($input->{data});
1189 elsif ($input->{callback} || $input->{readcb}) {
1190 if (!$input->{seekcb}) {
1191 $self->_set_error("Need a seekcb parameter");
1193 if ($input->{maxbuffer}) {
1194 return io_new_cb($input->{writecb},
1195 $input->{callback} || $input->{readcb},
1196 $input->{seekcb}, $input->{closecb},
1197 $input->{maxbuffer});
1200 return io_new_cb($input->{writecb},
1201 $input->{callback} || $input->{readcb},
1202 $input->{seekcb}, $input->{closecb});
1206 $self->_set_error("file/fd/fh/data/callback parameter missing");
1211 sub _get_writer_io {
1212 my ($self, $input, $type) = @_;
1215 return $input->{io};
1217 elsif ($input->{fd}) {
1218 return io_new_fd($input->{fd});
1220 elsif ($input->{fh}) {
1221 my $fd = fileno($input->{fh});
1223 $self->_set_error("Handle in fh option not opened");
1227 my $oldfh = select($input->{fh});
1228 # flush anything that's buffered, and make sure anything else is flushed
1231 return io_new_fd($fd);
1233 elsif ($input->{file}) {
1234 my $fh = new IO::File($input->{file},"w+");
1236 $self->_set_error("Could not open file $input->{file}: $!");
1239 binmode($fh) or die;
1240 return (io_new_fd(fileno($fh)), $fh);
1242 elsif ($input->{data}) {
1243 return io_new_bufchain();
1245 elsif ($input->{callback} || $input->{writecb}) {
1246 if ($input->{maxbuffer}) {
1247 return io_new_cb($input->{callback} || $input->{writecb},
1249 $input->{seekcb}, $input->{closecb},
1250 $input->{maxbuffer});
1253 return io_new_cb($input->{callback} || $input->{writecb},
1255 $input->{seekcb}, $input->{closecb});
1259 $self->_set_error("file/fd/fh/data/callback parameter missing");
1264 # Read an image from file
1270 if (defined($self->{IMG})) {
1271 # let IIM_DESTROY do the destruction, since the image may be
1272 # referenced from elsewhere
1273 #i_img_destroy($self->{IMG});
1274 undef($self->{IMG});
1277 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1279 unless ($input{'type'}) {
1280 $input{'type'} = i_test_format_probe($IO, -1);
1283 unless ($input{'type'}) {
1284 $self->_set_error('type parameter missing and not possible to guess from extension');
1288 _reader_autoload($input{type});
1290 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1291 return $readers{$input{type}}{single}->($self, $IO, %input);
1294 unless ($formats{$input{'type'}}) {
1295 my $read_types = join ', ', sort Imager->read_types();
1296 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1301 if ( $input{'type'} eq 'jpeg' ) {
1302 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1303 if ( !defined($self->{IMG}) ) {
1304 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1306 $self->{DEBUG} && print "loading a jpeg file\n";
1310 my $allow_incomplete = $input{allow_incomplete};
1311 defined $allow_incomplete or $allow_incomplete = 0;
1313 if ( $input{'type'} eq 'tiff' ) {
1314 my $page = $input{'page'};
1315 defined $page or $page = 0;
1316 $self->{IMG}=i_readtiff_wiol( $IO, $allow_incomplete, $page );
1317 if ( !defined($self->{IMG}) ) {
1318 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1320 $self->{DEBUG} && print "loading a tiff file\n";
1324 if ( $input{'type'} eq 'pnm' ) {
1325 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1326 if ( !defined($self->{IMG}) ) {
1327 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1330 $self->{DEBUG} && print "loading a pnm file\n";
1334 if ( $input{'type'} eq 'png' ) {
1335 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1336 if ( !defined($self->{IMG}) ) {
1337 $self->{ERRSTR} = $self->_error_as_msg();
1340 $self->{DEBUG} && print "loading a png file\n";
1343 if ( $input{'type'} eq 'bmp' ) {
1344 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1345 if ( !defined($self->{IMG}) ) {
1346 $self->{ERRSTR}=$self->_error_as_msg();
1349 $self->{DEBUG} && print "loading a bmp file\n";
1352 if ( $input{'type'} eq 'gif' ) {
1353 if ($input{colors} && !ref($input{colors})) {
1354 # must be a reference to a scalar that accepts the colour map
1355 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1358 if ($input{'gif_consolidate'}) {
1359 if ($input{colors}) {
1361 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1363 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1367 $self->{IMG} =i_readgif_wiol( $IO );
1371 my $page = $input{'page'};
1372 defined $page or $page = 0;
1373 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1374 if ($self->{IMG} && $input{colors}) {
1375 ${ $input{colors} } =
1376 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1380 if ( !defined($self->{IMG}) ) {
1381 $self->{ERRSTR}=$self->_error_as_msg();
1384 $self->{DEBUG} && print "loading a gif file\n";
1387 if ( $input{'type'} eq 'tga' ) {
1388 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1389 if ( !defined($self->{IMG}) ) {
1390 $self->{ERRSTR}=$self->_error_as_msg();
1393 $self->{DEBUG} && print "loading a tga file\n";
1396 if ( $input{'type'} eq 'raw' ) {
1397 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1399 if ( !($params{xsize} && $params{ysize}) ) {
1400 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1404 $self->{IMG} = i_readraw_wiol( $IO,
1407 $params{datachannels},
1408 $params{storechannels},
1409 $params{interleave});
1410 if ( !defined($self->{IMG}) ) {
1411 $self->{ERRSTR}=$self->_error_as_msg();
1414 $self->{DEBUG} && print "loading a raw file\n";
1420 sub register_reader {
1421 my ($class, %opts) = @_;
1424 or die "register_reader called with no type parameter\n";
1426 my $type = $opts{type};
1428 defined $opts{single} || defined $opts{multiple}
1429 or die "register_reader called with no single or multiple parameter\n";
1431 $readers{$type} = { };
1432 if ($opts{single}) {
1433 $readers{$type}{single} = $opts{single};
1435 if ($opts{multiple}) {
1436 $readers{$type}{multiple} = $opts{multiple};
1442 sub register_writer {
1443 my ($class, %opts) = @_;
1446 or die "register_writer called with no type parameter\n";
1448 my $type = $opts{type};
1450 defined $opts{single} || defined $opts{multiple}
1451 or die "register_writer called with no single or multiple parameter\n";
1453 $writers{$type} = { };
1454 if ($opts{single}) {
1455 $writers{$type}{single} = $opts{single};
1457 if ($opts{multiple}) {
1458 $writers{$type}{multiple} = $opts{multiple};
1469 grep($file_formats{$_}, keys %formats),
1470 qw(ico sgi), # formats not handled directly, but supplied with Imager
1481 grep($file_formats{$_}, keys %formats),
1482 qw(ico sgi), # formats not handled directly, but supplied with Imager
1488 # probes for an Imager::File::whatever module
1489 sub _reader_autoload {
1492 return if $formats{$type} || $readers{$type};
1494 return unless $type =~ /^\w+$/;
1496 my $file = "Imager/File/\U$type\E.pm";
1498 unless ($attempted_to_load{$file}) {
1500 ++$attempted_to_load{$file};
1504 # try to get a reader specific module
1505 my $file = "Imager/File/\U$type\EReader.pm";
1506 unless ($attempted_to_load{$file}) {
1508 ++$attempted_to_load{$file};
1516 # probes for an Imager::File::whatever module
1517 sub _writer_autoload {
1520 return if $formats{$type} || $readers{$type};
1522 return unless $type =~ /^\w+$/;
1524 my $file = "Imager/File/\U$type\E.pm";
1526 unless ($attempted_to_load{$file}) {
1528 ++$attempted_to_load{$file};
1532 # try to get a writer specific module
1533 my $file = "Imager/File/\U$type\EWriter.pm";
1534 unless ($attempted_to_load{$file}) {
1536 ++$attempted_to_load{$file};
1544 sub _fix_gif_positions {
1545 my ($opts, $opt, $msg, @imgs) = @_;
1547 my $positions = $opts->{'gif_positions'};
1549 for my $pos (@$positions) {
1550 my ($x, $y) = @$pos;
1551 my $img = $imgs[$index++];
1552 $img->settag(name=>'gif_left', value=>$x);
1553 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1555 $$msg .= "replaced with the gif_left and gif_top tags";
1560 gif_each_palette=>'gif_local_map',
1561 interlace => 'gif_interlace',
1562 gif_delays => 'gif_delay',
1563 gif_positions => \&_fix_gif_positions,
1564 gif_loop_count => 'gif_loop',
1568 my ($self, $opts, $prefix, @imgs) = @_;
1570 for my $opt (keys %$opts) {
1572 if ($obsolete_opts{$opt}) {
1573 my $new = $obsolete_opts{$opt};
1574 my $msg = "Obsolete option $opt ";
1576 $new->($opts, $opt, \$msg, @imgs);
1579 $msg .= "replaced with the $new tag ";
1582 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1583 warn $msg if $warn_obsolete && $^W;
1585 next unless $tagname =~ /^\Q$prefix/;
1586 my $value = $opts->{$opt};
1588 if (UNIVERSAL::isa($value, "Imager::Color")) {
1589 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1590 for my $img (@imgs) {
1591 $img->settag(name=>$tagname, value=>$tag);
1594 elsif (ref($value) eq 'ARRAY') {
1595 for my $i (0..$#$value) {
1596 my $val = $value->[$i];
1598 if (UNIVERSAL::isa($val, "Imager::Color")) {
1599 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1601 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1604 $self->_set_error("Unknown reference type " . ref($value) .
1605 " supplied in array for $opt");
1611 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1616 $self->_set_error("Unknown reference type " . ref($value) .
1617 " supplied for $opt");
1622 # set it as a tag for every image
1623 for my $img (@imgs) {
1624 $img->settag(name=>$tagname, value=>$value);
1632 # Write an image to file
1635 my %input=(jpegquality=>75,
1645 $self->_set_opts(\%input, "i_", $self)
1648 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1650 if (!$input{'type'} and $input{file}) {
1651 $input{'type'}=$FORMATGUESS->($input{file});
1653 if (!$input{'type'}) {
1654 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1658 _writer_autoload($input{type});
1661 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1662 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1665 $writers{$input{type}}{single}->($self, $IO, %input)
1669 if (!$formats{$input{'type'}}) {
1670 my $write_types = join ', ', sort Imager->write_types();
1671 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1675 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1678 if ($input{'type'} eq 'tiff') {
1679 $self->_set_opts(\%input, "tiff_", $self)
1681 $self->_set_opts(\%input, "exif_", $self)
1684 if (defined $input{class} && $input{class} eq 'fax') {
1685 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1686 $self->{ERRSTR} = $self->_error_as_msg();
1690 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1691 $self->{ERRSTR} = $self->_error_as_msg();
1695 } elsif ( $input{'type'} eq 'pnm' ) {
1696 $self->_set_opts(\%input, "pnm_", $self)
1698 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1699 $self->{ERRSTR} = $self->_error_as_msg();
1702 $self->{DEBUG} && print "writing a pnm file\n";
1703 } elsif ( $input{'type'} eq 'raw' ) {
1704 $self->_set_opts(\%input, "raw_", $self)
1706 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1707 $self->{ERRSTR} = $self->_error_as_msg();
1710 $self->{DEBUG} && print "writing a raw file\n";
1711 } elsif ( $input{'type'} eq 'png' ) {
1712 $self->_set_opts(\%input, "png_", $self)
1714 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1715 $self->{ERRSTR}='unable to write png image';
1718 $self->{DEBUG} && print "writing a png file\n";
1719 } elsif ( $input{'type'} eq 'jpeg' ) {
1720 $self->_set_opts(\%input, "jpeg_", $self)
1722 $self->_set_opts(\%input, "exif_", $self)
1724 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1725 $self->{ERRSTR} = $self->_error_as_msg();
1728 $self->{DEBUG} && print "writing a jpeg file\n";
1729 } elsif ( $input{'type'} eq 'bmp' ) {
1730 $self->_set_opts(\%input, "bmp_", $self)
1732 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1733 $self->{ERRSTR} = $self->_error_as_msg;
1736 $self->{DEBUG} && print "writing a bmp file\n";
1737 } elsif ( $input{'type'} eq 'tga' ) {
1738 $self->_set_opts(\%input, "tga_", $self)
1741 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1742 $self->{ERRSTR}=$self->_error_as_msg();
1745 $self->{DEBUG} && print "writing a tga file\n";
1746 } elsif ( $input{'type'} eq 'gif' ) {
1747 $self->_set_opts(\%input, "gif_", $self)
1749 # compatibility with the old interfaces
1750 if ($input{gifquant} eq 'lm') {
1751 $input{make_colors} = 'addi';
1752 $input{translate} = 'perturb';
1753 $input{perturb} = $input{lmdither};
1754 } elsif ($input{gifquant} eq 'gen') {
1755 # just pass options through
1757 $input{make_colors} = 'webmap'; # ignored
1758 $input{translate} = 'giflib';
1760 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1761 $self->{ERRSTR} = $self->_error_as_msg;
1767 if (exists $input{'data'}) {
1768 my $data = io_slurp($IO);
1770 $self->{ERRSTR}='Could not slurp from buffer';
1773 ${$input{data}} = $data;
1779 my ($class, $opts, @images) = @_;
1781 my $type = $opts->{type};
1783 if (!$type && $opts->{'file'}) {
1784 $type = $FORMATGUESS->($opts->{'file'});
1787 $class->_set_error('type parameter missing and not possible to guess from extension');
1790 # translate to ImgRaw
1791 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1792 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1795 $class->_set_opts($opts, "i_", @images)
1797 my @work = map $_->{IMG}, @images;
1799 _writer_autoload($type);
1802 if ($writers{$type} && $writers{$type}{multiple}) {
1803 ($IO, $file) = $class->_get_writer_io($opts, $type)
1806 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1810 if (!$formats{$type}) {
1811 my $write_types = join ', ', sort Imager->write_types();
1812 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1816 ($IO, $file) = $class->_get_writer_io($opts, $type)
1819 if ($type eq 'gif') {
1820 $class->_set_opts($opts, "gif_", @images)
1822 my $gif_delays = $opts->{gif_delays};
1823 local $opts->{gif_delays} = $gif_delays;
1824 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1825 # assume the caller wants the same delay for each frame
1826 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1828 unless (i_writegif_wiol($IO, $opts, @work)) {
1829 $class->_set_error($class->_error_as_msg());
1833 elsif ($type eq 'tiff') {
1834 $class->_set_opts($opts, "tiff_", @images)
1836 $class->_set_opts($opts, "exif_", @images)
1839 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1840 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1841 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1844 $res = i_writetiff_multi_wiol($IO, @work);
1847 $class->_set_error($class->_error_as_msg());
1853 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1858 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1864 if (exists $opts->{'data'}) {
1865 my $data = io_slurp($IO);
1867 Imager->_set_error('Could not slurp from buffer');
1870 ${$opts->{data}} = $data;
1875 # read multiple images from a file
1877 my ($class, %opts) = @_;
1879 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1882 my $type = $opts{'type'};
1884 $type = i_test_format_probe($IO, -1);
1887 if ($opts{file} && !$type) {
1889 $type = $FORMATGUESS->($opts{file});
1893 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1897 _reader_autoload($type);
1899 if ($readers{$type} && $readers{$type}{multiple}) {
1900 return $readers{$type}{multiple}->($IO, %opts);
1903 if ($type eq 'gif') {
1905 @imgs = i_readgif_multi_wiol($IO);
1908 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1912 $ERRSTR = _error_as_msg();
1916 elsif ($type eq 'tiff') {
1917 my @imgs = i_readtiff_multi_wiol($IO, -1);
1920 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1924 $ERRSTR = _error_as_msg();
1929 my $img = Imager->new;
1930 if ($img->read(%opts, io => $IO, type => $type)) {
1933 Imager->_set_error($img->errstr);
1939 # Destroy an Imager object
1943 # delete $instances{$self};
1944 if (defined($self->{IMG})) {
1945 # the following is now handled by the XS DESTROY method for
1946 # Imager::ImgRaw object
1947 # Re-enabling this will break virtual images
1948 # tested for in t/t020masked.t
1949 # i_img_destroy($self->{IMG});
1950 undef($self->{IMG});
1952 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1956 # Perform an inplace filter of an image
1957 # that is the image will be overwritten with the data
1963 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1965 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1967 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1968 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1971 if ($filters{$input{'type'}}{names}) {
1972 my $names = $filters{$input{'type'}}{names};
1973 for my $name (keys %$names) {
1974 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1975 $input{$name} = $names->{$name}{$input{$name}};
1979 if (defined($filters{$input{'type'}}{defaults})) {
1980 %hsh=( image => $self->{IMG},
1982 %{$filters{$input{'type'}}{defaults}},
1985 %hsh=( image => $self->{IMG},
1990 my @cs=@{$filters{$input{'type'}}{callseq}};
1993 if (!defined($hsh{$_})) {
1994 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1999 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2000 &{$filters{$input{'type'}}{callsub}}(%hsh);
2003 chomp($self->{ERRSTR} = $@);
2009 $self->{DEBUG} && print "callseq is: @cs\n";
2010 $self->{DEBUG} && print "matching callseq is: @b\n";
2015 sub register_filter {
2017 my %hsh = ( defaults => {}, @_ );
2020 or die "register_filter() with no type\n";
2021 defined $hsh{callsub}
2022 or die "register_filter() with no callsub\n";
2023 defined $hsh{callseq}
2024 or die "register_filter() with no callseq\n";
2026 exists $filters{$hsh{type}}
2029 $filters{$hsh{type}} = \%hsh;
2034 sub scale_calculate {
2037 my %opts = ('type'=>'max', @_);
2039 my ($x_scale, $y_scale);
2040 my $width = $opts{width};
2041 my $height = $opts{height};
2043 defined $width or $width = $self->getwidth;
2044 defined $height or $height = $self->getheight;
2047 unless (defined $width && defined $height) {
2048 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2053 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2054 $x_scale = $opts{'xscalefactor'};
2055 $y_scale = $opts{'yscalefactor'};
2057 elsif ($opts{'xscalefactor'}) {
2058 $x_scale = $opts{'xscalefactor'};
2059 $y_scale = $opts{'scalefactor'} || $x_scale;
2061 elsif ($opts{'yscalefactor'}) {
2062 $y_scale = $opts{'yscalefactor'};
2063 $x_scale = $opts{'scalefactor'} || $y_scale;
2066 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2069 # work out the scaling
2070 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2071 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2072 $opts{ypixels} / $height );
2073 if ($opts{'type'} eq 'min') {
2074 $x_scale = $y_scale = _min($xpix,$ypix);
2076 elsif ($opts{'type'} eq 'max') {
2077 $x_scale = $y_scale = _max($xpix,$ypix);
2079 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2084 $self->_set_error('invalid value for type parameter');
2087 } elsif ($opts{xpixels}) {
2088 $x_scale = $y_scale = $opts{xpixels} / $width;
2090 elsif ($opts{ypixels}) {
2091 $x_scale = $y_scale = $opts{ypixels}/$height;
2093 elsif ($opts{constrain} && ref $opts{constrain}
2094 && $opts{constrain}->can('constrain')) {
2095 # we've been passed an Image::Math::Constrain object or something
2096 # that looks like one
2098 (undef, undef, $scalefactor)
2099 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2100 unless ($scalefactor) {
2101 $self->_set_error('constrain method failed on constrain parameter');
2104 $x_scale = $y_scale = $scalefactor;
2107 my $new_width = int($x_scale * $width + 0.5);
2108 $new_width > 0 or $new_width = 1;
2109 my $new_height = int($y_scale * $height + 0.5);
2110 $new_height > 0 or $new_height = 1;
2112 return ($x_scale, $y_scale, $new_width, $new_height);
2116 # Scale an image to requested size and return the scaled version
2120 my %opts = (qtype=>'normal' ,@_);
2121 my $img = Imager->new();
2122 my $tmp = Imager->new();
2124 unless (defined wantarray) {
2125 my @caller = caller;
2126 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2130 unless ($self->{IMG}) {
2131 $self->_set_error('empty input image');
2135 my ($x_scale, $y_scale, $new_width, $new_height) =
2136 $self->scale_calculate(%opts)
2139 if ($opts{qtype} eq 'normal') {
2140 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2141 if ( !defined($tmp->{IMG}) ) {
2142 $self->{ERRSTR} = 'unable to scale image';
2145 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2146 if ( !defined($img->{IMG}) ) {
2147 $self->{ERRSTR}='unable to scale image';
2153 elsif ($opts{'qtype'} eq 'preview') {
2154 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2155 if ( !defined($img->{IMG}) ) {
2156 $self->{ERRSTR}='unable to scale image';
2161 elsif ($opts{'qtype'} eq 'mixing') {
2162 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2163 unless ($img->{IMG}) {
2164 $self->_set_error(Imager->_error_as_meg);
2170 $self->_set_error('invalid value for qtype parameter');
2175 # Scales only along the X axis
2179 my %opts = ( scalefactor=>0.5, @_ );
2181 unless (defined wantarray) {
2182 my @caller = caller;
2183 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2187 unless ($self->{IMG}) {
2188 $self->{ERRSTR} = 'empty input image';
2192 my $img = Imager->new();
2194 my $scalefactor = $opts{scalefactor};
2196 if ($opts{pixels}) {
2197 $scalefactor = $opts{pixels} / $self->getwidth();
2200 unless ($self->{IMG}) {
2201 $self->{ERRSTR}='empty input image';
2205 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2207 if ( !defined($img->{IMG}) ) {
2208 $self->{ERRSTR} = 'unable to scale image';
2215 # Scales only along the Y axis
2219 my %opts = ( scalefactor => 0.5, @_ );
2221 unless (defined wantarray) {
2222 my @caller = caller;
2223 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2227 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2229 my $img = Imager->new();
2231 my $scalefactor = $opts{scalefactor};
2233 if ($opts{pixels}) {
2234 $scalefactor = $opts{pixels} / $self->getheight();
2237 unless ($self->{IMG}) {
2238 $self->{ERRSTR} = 'empty input image';
2241 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2243 if ( !defined($img->{IMG}) ) {
2244 $self->{ERRSTR} = 'unable to scale image';
2251 # Transform returns a spatial transformation of the input image
2252 # this moves pixels to a new location in the returned image.
2253 # NOTE - should make a utility function to check transforms for
2258 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2260 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2262 # print Dumper(\%opts);
2265 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2267 eval ("use Affix::Infix2Postfix;");
2270 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2273 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2274 {op=>'-',trans=>'Sub'},
2275 {op=>'*',trans=>'Mult'},
2276 {op=>'/',trans=>'Div'},
2277 {op=>'-','type'=>'unary',trans=>'u-'},
2279 {op=>'func','type'=>'unary'}],
2280 'grouping'=>[qw( \( \) )],
2281 'func'=>[qw( sin cos )],
2286 @xt=$I2P->translate($opts{'xexpr'});
2287 @yt=$I2P->translate($opts{'yexpr'});
2289 $numre=$I2P->{'numre'};
2292 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2293 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2294 @{$opts{'parm'}}=@pt;
2297 # print Dumper(\%opts);
2299 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2300 $self->{ERRSTR}='transform: no xopcodes given.';
2304 @op=@{$opts{'xopcodes'}};
2306 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2307 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2310 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2316 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2317 $self->{ERRSTR}='transform: no yopcodes given.';
2321 @op=@{$opts{'yopcodes'}};
2323 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2324 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2327 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2332 if ( !exists $opts{'parm'}) {
2333 $self->{ERRSTR}='transform: no parameter arg given.';
2337 # print Dumper(\@ropx);
2338 # print Dumper(\@ropy);
2339 # print Dumper(\@ropy);
2341 my $img = Imager->new();
2342 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2343 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2349 my ($opts, @imgs) = @_;
2351 require "Imager/Expr.pm";
2353 $opts->{variables} = [ qw(x y) ];
2354 my ($width, $height) = @{$opts}{qw(width height)};
2356 $width ||= $imgs[0]->getwidth();
2357 $height ||= $imgs[0]->getheight();
2359 for my $img (@imgs) {
2360 $opts->{constants}{"w$img_num"} = $img->getwidth();
2361 $opts->{constants}{"h$img_num"} = $img->getheight();
2362 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2363 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2368 $opts->{constants}{w} = $width;
2369 $opts->{constants}{cx} = $width/2;
2372 $Imager::ERRSTR = "No width supplied";
2376 $opts->{constants}{h} = $height;
2377 $opts->{constants}{cy} = $height/2;
2380 $Imager::ERRSTR = "No height supplied";
2383 my $code = Imager::Expr->new($opts);
2385 $Imager::ERRSTR = Imager::Expr::error();
2388 my $channels = $opts->{channels} || 3;
2389 unless ($channels >= 1 && $channels <= 4) {
2390 return Imager->_set_error("channels must be an integer between 1 and 4");
2393 my $img = Imager->new();
2394 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2395 $channels, $code->code(),
2396 $code->nregs(), $code->cregs(),
2397 [ map { $_->{IMG} } @imgs ]);
2398 if (!defined $img->{IMG}) {
2399 $Imager::ERRSTR = Imager->_error_as_msg();
2408 my %opts=(tx => 0,ty => 0, @_);
2410 unless ($self->{IMG}) {
2411 $self->{ERRSTR}='empty input image';
2414 unless ($opts{src} && $opts{src}->{IMG}) {
2415 $self->{ERRSTR}='empty input image for src';
2419 %opts = (src_minx => 0,
2421 src_maxx => $opts{src}->getwidth(),
2422 src_maxy => $opts{src}->getheight(),
2425 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
2426 $opts{src_minx}, $opts{src_miny},
2427 $opts{src_maxx}, $opts{src_maxy})) {
2428 $self->_set_error($self->_error_as_msg());
2438 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2440 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2441 $dir = $xlate{$opts{'dir'}};
2442 return $self if i_flipxy($self->{IMG}, $dir);
2450 unless (defined wantarray) {
2451 my @caller = caller;
2452 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2456 if (defined $opts{right}) {
2457 my $degrees = $opts{right};
2459 $degrees += 360 * int(((-$degrees)+360)/360);
2461 $degrees = $degrees % 360;
2462 if ($degrees == 0) {
2463 return $self->copy();
2465 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2466 my $result = Imager->new();
2467 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2471 $self->{ERRSTR} = $self->_error_as_msg();
2476 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2480 elsif (defined $opts{radians} || defined $opts{degrees}) {
2481 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2483 my $back = $opts{back};
2484 my $result = Imager->new;
2486 $back = _color($back);
2488 $self->_set_error(Imager->errstr);
2492 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2495 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2497 if ($result->{IMG}) {
2501 $self->{ERRSTR} = $self->_error_as_msg();
2506 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2511 sub matrix_transform {
2515 unless (defined wantarray) {
2516 my @caller = caller;
2517 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2521 if ($opts{matrix}) {
2522 my $xsize = $opts{xsize} || $self->getwidth;
2523 my $ysize = $opts{ysize} || $self->getheight;
2525 my $result = Imager->new;
2527 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2528 $opts{matrix}, $opts{back})
2532 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2540 $self->{ERRSTR} = "matrix parameter required";
2546 *yatf = \&matrix_transform;
2548 # These two are supported for legacy code only
2551 return Imager::Color->new(@_);
2555 return Imager::Color::set(@_);
2558 # Draws a box between the specified corner points.
2561 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2562 my $dflcl=i_color_new(255,255,255,255);
2563 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2565 if (exists $opts{'box'}) {
2566 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2567 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2568 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2569 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2572 if ($opts{filled}) {
2573 my $color = _color($opts{'color'});
2575 $self->{ERRSTR} = $Imager::ERRSTR;
2578 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2579 $opts{ymax}, $color);
2581 elsif ($opts{fill}) {
2582 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2583 # assume it's a hash ref
2584 require 'Imager/Fill.pm';
2585 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2586 $self->{ERRSTR} = $Imager::ERRSTR;
2590 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2591 $opts{ymax},$opts{fill}{fill});
2594 my $color = _color($opts{'color'});
2596 $self->{ERRSTR} = $Imager::ERRSTR;
2599 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2607 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2608 my $dflcl=i_color_new(255,255,255,255);
2609 my %opts=(color=>$dflcl,
2610 'r'=>_min($self->getwidth(),$self->getheight())/3,
2611 'x'=>$self->getwidth()/2,
2612 'y'=>$self->getheight()/2,
2613 'd1'=>0, 'd2'=>361, @_);
2616 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2617 # assume it's a hash ref
2618 require 'Imager/Fill.pm';
2619 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2620 $self->{ERRSTR} = $Imager::ERRSTR;
2624 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2625 $opts{'d2'}, $opts{fill}{fill});
2628 my $color = _color($opts{'color'});
2630 $self->{ERRSTR} = $Imager::ERRSTR;
2633 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2634 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2638 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2639 $opts{'d1'}, $opts{'d2'}, $color);
2645 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2646 # assume it's a hash ref
2647 require 'Imager/Fill.pm';
2648 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2649 $self->{ERRSTR} = $Imager::ERRSTR;
2653 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2654 $opts{'d2'}, $opts{fill}{fill});
2657 my $color = _color($opts{'color'});
2659 $self->{ERRSTR} = $Imager::ERRSTR;
2662 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2663 $opts{'d1'}, $opts{'d2'}, $color);
2670 # Draws a line from one point to the other
2671 # the endpoint is set if the endp parameter is set which it is by default.
2672 # to turn of the endpoint being set use endp=>0 when calling line.
2676 my $dflcl=i_color_new(0,0,0,0);
2677 my %opts=(color=>$dflcl,
2680 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2682 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2683 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2685 my $color = _color($opts{'color'});
2687 $self->{ERRSTR} = $Imager::ERRSTR;
2691 $opts{antialias} = $opts{aa} if defined $opts{aa};
2692 if ($opts{antialias}) {
2693 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2694 $color, $opts{endp});
2696 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2697 $color, $opts{endp});
2702 # Draws a line between an ordered set of points - It more or less just transforms this
2703 # into a list of lines.
2707 my ($pt,$ls,@points);
2708 my $dflcl=i_color_new(0,0,0,0);
2709 my %opts=(color=>$dflcl,@_);
2711 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2713 if (exists($opts{points})) { @points=@{$opts{points}}; }
2714 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2715 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2718 # print Dumper(\@points);
2720 my $color = _color($opts{'color'});
2722 $self->{ERRSTR} = $Imager::ERRSTR;
2725 $opts{antialias} = $opts{aa} if defined $opts{aa};
2726 if ($opts{antialias}) {
2729 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2736 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2746 my ($pt,$ls,@points);
2747 my $dflcl = i_color_new(0,0,0,0);
2748 my %opts = (color=>$dflcl, @_);
2750 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2752 if (exists($opts{points})) {
2753 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2754 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2757 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2758 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2761 if ($opts{'fill'}) {
2762 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2763 # assume it's a hash ref
2764 require 'Imager/Fill.pm';
2765 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2766 $self->{ERRSTR} = $Imager::ERRSTR;
2770 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2771 $opts{'fill'}{'fill'});
2774 my $color = _color($opts{'color'});
2776 $self->{ERRSTR} = $Imager::ERRSTR;
2779 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2786 # this the multipoint bezier curve
2787 # this is here more for testing that actual usage since
2788 # this is not a good algorithm. Usually the curve would be
2789 # broken into smaller segments and each done individually.
2793 my ($pt,$ls,@points);
2794 my $dflcl=i_color_new(0,0,0,0);
2795 my %opts=(color=>$dflcl,@_);
2797 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2799 if (exists $opts{points}) {
2800 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2801 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2804 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2805 $self->{ERRSTR}='Missing or invalid points.';
2809 my $color = _color($opts{'color'});
2811 $self->{ERRSTR} = $Imager::ERRSTR;
2814 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2820 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2823 unless (exists $opts{'x'} && exists $opts{'y'}) {
2824 $self->{ERRSTR} = "missing seed x and y parameters";
2828 if ($opts{border}) {
2829 my $border = _color($opts{border});
2831 $self->_set_error($Imager::ERRSTR);
2835 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2836 # assume it's a hash ref
2837 require Imager::Fill;
2838 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2839 $self->{ERRSTR} = $Imager::ERRSTR;
2843 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2844 $opts{fill}{fill}, $border);
2847 my $color = _color($opts{'color'});
2849 $self->{ERRSTR} = $Imager::ERRSTR;
2852 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2859 $self->{ERRSTR} = $self->_error_as_msg();
2865 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2866 # assume it's a hash ref
2867 require 'Imager/Fill.pm';
2868 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2869 $self->{ERRSTR} = $Imager::ERRSTR;
2873 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2876 my $color = _color($opts{'color'});
2878 $self->{ERRSTR} = $Imager::ERRSTR;
2881 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2887 $self->{ERRSTR} = $self->_error_as_msg();
2896 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2898 unless (exists $opts{'x'} && exists $opts{'y'}) {
2899 $self->{ERRSTR} = 'missing x and y parameters';
2905 my $color = _color($opts{color})
2907 if (ref $x && ref $y) {
2908 unless (@$x == @$y) {
2909 $self->{ERRSTR} = 'length of x and y mismatch';
2913 if ($color->isa('Imager::Color')) {
2914 for my $i (0..$#{$opts{'x'}}) {
2915 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
2920 for my $i (0..$#{$opts{'x'}}) {
2921 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
2929 if ($color->isa('Imager::Color')) {
2930 i_ppix($self->{IMG}, $x, $y, $color)
2934 i_ppixf($self->{IMG}, $x, $y, $color)
2945 my %opts = ( "type"=>'8bit', @_);
2947 unless (exists $opts{'x'} && exists $opts{'y'}) {
2948 $self->{ERRSTR} = 'missing x and y parameters';
2954 if (ref $x && ref $y) {
2955 unless (@$x == @$y) {
2956 $self->{ERRSTR} = 'length of x and y mismatch';
2960 if ($opts{"type"} eq '8bit') {
2961 for my $i (0..$#{$opts{'x'}}) {
2962 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2966 for my $i (0..$#{$opts{'x'}}) {
2967 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2970 return wantarray ? @result : \@result;
2973 if ($opts{"type"} eq '8bit') {
2974 return i_get_pixel($self->{IMG}, $x, $y);
2977 return i_gpixf($self->{IMG}, $x, $y);
2986 my %opts = ( type => '8bit', x=>0, @_);
2988 $self->_valid_image or return;
2990 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2992 unless (defined $opts{'y'}) {
2993 $self->_set_error("missing y parameter");
2997 if ($opts{type} eq '8bit') {
2998 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3001 elsif ($opts{type} eq 'float') {
3002 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3005 elsif ($opts{type} eq 'index') {
3006 unless (i_img_type($self->{IMG})) {
3007 $self->_set_error("type => index only valid on paletted images");
3010 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3014 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3021 my %opts = ( x=>0, @_);
3023 $self->_valid_image or return;
3025 unless (defined $opts{'y'}) {
3026 $self->_set_error("missing y parameter");
3031 if (ref $opts{pixels} && @{$opts{pixels}}) {
3032 # try to guess the type
3033 if ($opts{pixels}[0]->isa('Imager::Color')) {
3034 $opts{type} = '8bit';
3036 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3037 $opts{type} = 'float';
3040 $self->_set_error("missing type parameter and could not guess from pixels");
3046 $opts{type} = '8bit';
3050 if ($opts{type} eq '8bit') {
3051 if (ref $opts{pixels}) {
3052 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3055 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3058 elsif ($opts{type} eq 'float') {
3059 if (ref $opts{pixels}) {
3060 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3063 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3066 elsif ($opts{type} eq 'index') {
3067 if (ref $opts{pixels}) {
3068 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3071 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3075 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3082 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3084 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3086 unless (defined $opts{'y'}) {
3087 $self->_set_error("missing y parameter");
3091 unless ($opts{channels}) {
3092 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3095 if ($opts{target}) {
3096 my $target = $opts{target};
3097 my $offset = $opts{offset};
3098 if ($opts{type} eq '8bit') {
3099 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3100 $opts{y}, @{$opts{channels}})
3102 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3103 return scalar(@samples);
3105 elsif ($opts{type} eq 'float') {
3106 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3107 $opts{y}, @{$opts{channels}});
3108 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3109 return scalar(@samples);
3111 elsif ($opts{type} =~ /^(\d+)bit$/) {
3115 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3116 $opts{y}, $bits, $target,
3117 $offset, @{$opts{channels}});
3118 unless (defined $count) {
3119 $self->_set_error(Imager->_error_as_msg);
3126 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3131 if ($opts{type} eq '8bit') {
3132 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3133 $opts{y}, @{$opts{channels}});
3135 elsif ($opts{type} eq 'float') {
3136 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3137 $opts{y}, @{$opts{channels}});
3139 elsif ($opts{type} =~ /^(\d+)bit$/) {
3143 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3144 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3149 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3157 my %opts = ( x => 0, offset => 0, @_ );
3159 unless ($self->{IMG}) {
3160 $self->_set_error('setsamples: empty input image');
3164 unless(defined $opts{data} && ref $opts{data}) {
3165 $self->_set_error('setsamples: data parameter missing or invalid');
3169 unless ($opts{channels}) {
3170 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3173 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3174 $self->_set_error('setsamples: type parameter missing or invalid');
3179 unless (defined $opts{width}) {
3180 $opts{width} = $self->getwidth() - $opts{x};
3183 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3184 $opts{channels}, $opts{data}, $opts{offset},
3186 unless (defined $count) {
3187 $self->_set_error(Imager->_error_as_msg);
3194 # make an identity matrix of the given size
3198 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3199 for my $c (0 .. ($size-1)) {
3200 $matrix->[$c][$c] = 1;
3205 # general function to convert an image
3207 my ($self, %opts) = @_;
3210 unless (defined wantarray) {
3211 my @caller = caller;
3212 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3216 # the user can either specify a matrix or preset
3217 # the matrix overrides the preset
3218 if (!exists($opts{matrix})) {
3219 unless (exists($opts{preset})) {
3220 $self->{ERRSTR} = "convert() needs a matrix or preset";
3224 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3225 # convert to greyscale, keeping the alpha channel if any
3226 if ($self->getchannels == 3) {
3227 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3229 elsif ($self->getchannels == 4) {
3230 # preserve the alpha channel
3231 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3236 $matrix = _identity($self->getchannels);
3239 elsif ($opts{preset} eq 'noalpha') {
3240 # strip the alpha channel
3241 if ($self->getchannels == 2 or $self->getchannels == 4) {
3242 $matrix = _identity($self->getchannels);
3243 pop(@$matrix); # lose the alpha entry
3246 $matrix = _identity($self->getchannels);
3249 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3251 $matrix = [ [ 1 ] ];
3253 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3254 $matrix = [ [ 0, 1 ] ];
3256 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3257 $matrix = [ [ 0, 0, 1 ] ];
3259 elsif ($opts{preset} eq 'alpha') {
3260 if ($self->getchannels == 2 or $self->getchannels == 4) {
3261 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3264 # the alpha is just 1 <shrug>
3265 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3268 elsif ($opts{preset} eq 'rgb') {
3269 if ($self->getchannels == 1) {
3270 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3272 elsif ($self->getchannels == 2) {
3273 # preserve the alpha channel
3274 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3277 $matrix = _identity($self->getchannels);
3280 elsif ($opts{preset} eq 'addalpha') {
3281 if ($self->getchannels == 1) {
3282 $matrix = _identity(2);
3284 elsif ($self->getchannels == 3) {
3285 $matrix = _identity(4);
3288 $matrix = _identity($self->getchannels);
3292 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3298 $matrix = $opts{matrix};
3301 my $new = Imager->new;
3302 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3303 unless ($new->{IMG}) {
3304 # most likely a bad matrix
3305 $self->{ERRSTR} = _error_as_msg();
3312 # general function to map an image through lookup tables
3315 my ($self, %opts) = @_;
3316 my @chlist = qw( red green blue alpha );
3318 if (!exists($opts{'maps'})) {
3319 # make maps from channel maps
3321 for $chnum (0..$#chlist) {
3322 if (exists $opts{$chlist[$chnum]}) {
3323 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3324 } elsif (exists $opts{'all'}) {
3325 $opts{'maps'}[$chnum] = $opts{'all'};
3329 if ($opts{'maps'} and $self->{IMG}) {
3330 i_map($self->{IMG}, $opts{'maps'} );
3336 my ($self, %opts) = @_;
3338 defined $opts{mindist} or $opts{mindist} = 0;
3340 defined $opts{other}
3341 or return $self->_set_error("No 'other' parameter supplied");
3342 defined $opts{other}{IMG}
3343 or return $self->_set_error("No image data in 'other' image");
3346 or return $self->_set_error("No image data");
3348 my $result = Imager->new;
3349 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3351 or return $self->_set_error($self->_error_as_msg());
3356 # destructive border - image is shrunk by one pixel all around
3359 my ($self,%opts)=@_;
3360 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3361 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3365 # Get the width of an image
3369 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3370 return (i_img_info($self->{IMG}))[0];
3373 # Get the height of an image
3377 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3378 return (i_img_info($self->{IMG}))[1];
3381 # Get number of channels in an image
3385 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3386 return i_img_getchannels($self->{IMG});
3393 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3394 return i_img_getmask($self->{IMG});
3402 if (!defined($self->{IMG})) {
3403 $self->{ERRSTR} = 'image is empty';
3406 unless (defined $opts{mask}) {
3407 $self->_set_error("mask parameter required");
3410 i_img_setmask( $self->{IMG} , $opts{mask} );
3415 # Get number of colors in an image
3419 my %opts=('maxcolors'=>2**30,@_);
3420 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3421 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3422 return ($rc==-1? undef : $rc);
3425 # Returns a reference to a hash. The keys are colour named (packed) and the
3426 # values are the number of pixels in this colour.
3427 sub getcolorusagehash {
3430 my %opts = ( maxcolors => 2**30, @_ );
3431 my $max_colors = $opts{maxcolors};
3432 unless (defined $max_colors && $max_colors > 0) {
3433 $self->_set_error('maxcolors must be a positive integer');
3437 unless (defined $self->{IMG}) {
3438 $self->_set_error('empty input image');
3442 my $channels= $self->getchannels;
3443 # We don't want to look at the alpha channel, because some gifs using it
3444 # doesn't define it for every colour (but only for some)
3445 $channels -= 1 if $channels == 2 or $channels == 4;
3447 my $height = $self->getheight;
3448 for my $y (0 .. $height - 1) {
3449 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3450 while (length $colors) {
3451 $color_use{ substr($colors, 0, $channels, '') }++;
3453 keys %color_use > $max_colors
3459 # This will return a ordered array of the colour usage. Kind of the sorted
3460 # version of the values of the hash returned by getcolorusagehash.
3461 # You might want to add safety checks and change the names, etc...
3465 my %opts = ( maxcolors => 2**30, @_ );
3466 my $max_colors = $opts{maxcolors};
3467 unless (defined $max_colors && $max_colors > 0) {
3468 $self->_set_error('maxcolors must be a positive integer');
3472 unless (defined $self->{IMG}) {
3473 $self->_set_error('empty input image');
3477 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3480 # draw string to an image
3484 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3486 my %input=('x'=>0, 'y'=>0, @_);
3487 defined($input{string}) or $input{string} = $input{text};
3489 unless(defined $input{string}) {
3490 $self->{ERRSTR}="missing required parameter 'string'";
3494 unless($input{font}) {
3495 $self->{ERRSTR}="missing required parameter 'font'";
3499 unless ($input{font}->draw(image=>$self, %input)) {
3511 unless ($self->{IMG}) {
3512 $self->{ERRSTR}='empty input image';
3521 my %input=('x'=>0, 'y'=>0, @_);
3522 $input{string}||=$input{text};
3524 unless(exists $input{string}) {
3525 $self->_set_error("missing required parameter 'string'");
3529 unless($input{font}) {
3530 $self->_set_error("missing required parameter 'font'");
3535 unless (@result = $input{font}->align(image=>$img, %input)) {
3539 return wantarray ? @result : $result[0];
3542 my @file_limit_names = qw/width height bytes/;
3544 sub set_file_limits {
3551 @values{@file_limit_names} = (0) x @file_limit_names;
3554 @values{@file_limit_names} = i_get_image_file_limits();
3557 for my $key (keys %values) {
3558 defined $opts{$key} and $values{$key} = $opts{$key};
3561 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3564 sub get_file_limits {
3565 i_get_image_file_limits();
3568 # Shortcuts that can be exported
3570 sub newcolor { Imager::Color->new(@_); }
3571 sub newfont { Imager::Font->new(@_); }
3572 sub NCF { Imager::Color::Float->new(@_) }
3574 *NC=*newcolour=*newcolor;
3581 #### Utility routines
3584 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3588 my ($self, $msg) = @_;
3591 $self->{ERRSTR} = $msg;
3599 # Default guess for the type of an image from extension
3601 sub def_guess_type {
3604 $ext=($name =~ m/\.([^\.]+)$/)[0];
3605 return 'tiff' if ($ext =~ m/^tiff?$/);
3606 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3607 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3608 return 'png' if ($ext eq "png");
3609 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3610 return 'tga' if ($ext eq "tga");
3611 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3612 return 'gif' if ($ext eq "gif");
3613 return 'raw' if ($ext eq "raw");
3614 return lc $ext; # best guess
3618 # get the minimum of a list
3622 for(@_) { if ($_<$mx) { $mx=$_; }}
3626 # get the maximum of a list
3630 for(@_) { if ($_>$mx) { $mx=$_; }}
3634 # string stuff for iptc headers
3638 $str = substr($str,3);
3639 $str =~ s/[\n\r]//g;
3646 # A little hack to parse iptc headers.
3651 my($caption,$photogr,$headln,$credit);
3653 my $str=$self->{IPTCRAW};
3658 @ar=split(/8BIM/,$str);
3663 @sar=split(/\034\002/);
3664 foreach $item (@sar) {
3665 if ($item =~ m/^x/) {
3666 $caption = _clean($item);
3669 if ($item =~ m/^P/) {
3670 $photogr = _clean($item);
3673 if ($item =~ m/^i/) {
3674 $headln = _clean($item);
3677 if ($item =~ m/^n/) {
3678 $credit = _clean($item);
3684 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3691 or die "Only C language supported";
3693 require Imager::ExtUtils;
3694 return Imager::ExtUtils->inline_config;
3699 # Below is the stub of documentation for your module. You better edit it!
3703 Imager - Perl extension for Generating 24 bit Images
3713 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3718 my $img = Imager->new();
3719 # see Imager::Files for information on the read() method
3720 $img->read(file=>$file) or die $img->errstr();
3722 $file =~ s/\.[^.]*$//;
3724 # Create smaller version
3725 # documented in Imager::Transformations
3726 my $thumb = $img->scale(scalefactor=>.3);
3728 # Autostretch individual channels
3729 $thumb->filter(type=>'autolevels');
3731 # try to save in one of these formats
3734 for $format ( qw( png gif jpg tiff ppm ) ) {
3735 # Check if given format is supported
3736 if ($Imager::formats{$format}) {
3737 $file.="_low.$format";
3738 print "Storing image as: $file\n";
3739 # documented in Imager::Files
3740 $thumb->write(file=>$file) or
3748 Imager is a module for creating and altering images. It can read and
3749 write various image formats, draw primitive shapes like lines,and
3750 polygons, blend multiple images together in various ways, scale, crop,
3751 render text and more.
3753 =head2 Overview of documentation
3759 Imager - This document - Synopsis, Example, Table of Contents and
3764 L<Imager::Tutorial> - a brief introduction to Imager.
3768 L<Imager::Cookbook> - how to do various things with Imager.
3772 L<Imager::ImageTypes> - Basics of constructing image objects with
3773 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3774 8/16/double bits/channel, color maps, channel masks, image tags, color
3775 quantization. Also discusses basic image information methods.
3779 L<Imager::Files> - IO interaction, reading/writing images, format
3784 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3789 L<Imager::Color> - Color specification.
3793 L<Imager::Fill> - Fill pattern specification.
3797 L<Imager::Font> - General font rendering, bounding boxes and font
3802 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3803 blending, pasting, convert and map.
3807 L<Imager::Engines> - Programmable transformations through
3808 C<transform()>, C<transform2()> and C<matrix_transform()>.
3812 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3817 L<Imager::Expr> - Expressions for evaluation engine used by
3822 L<Imager::Matrix2d> - Helper class for affine transformations.
3826 L<Imager::Fountain> - Helper for making gradient profiles.
3830 L<Imager::API> - using Imager's C API
3834 L<Imager::APIRef> - API function reference
3838 L<Imager::Inline> - using Imager's C API from Inline::C
3842 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3846 =head2 Basic Overview
3848 An Image object is created with C<$img = Imager-E<gt>new()>.
3851 $img=Imager->new(); # create empty image
3852 $img->read(file=>'lena.png',type=>'png') or # read image from file
3853 die $img->errstr(); # give an explanation
3854 # if something failed
3856 or if you want to create an empty image:
3858 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3860 This example creates a completely black image of width 400 and height
3863 =head1 ERROR HANDLING
3865 In general a method will return false when it fails, if it does use the errstr() method to find out why:
3871 Returns the last error message in that context.
3873 If the last error you received was from calling an object method, such
3874 as read, call errstr() as an object method to find out why:
3876 my $image = Imager->new;
3877 $image->read(file => 'somefile.gif')
3878 or die $image->errstr;
3880 If it was a class method then call errstr() as a class method:
3882 my @imgs = Imager->read_multi(file => 'somefile.gif')
3883 or die Imager->errstr;
3885 Note that in some cases object methods are implemented in terms of
3886 class methods so a failing object method may set both.
3890 The C<Imager-E<gt>new> method is described in detail in
3891 L<Imager::ImageTypes>.
3895 Where to find information on methods for Imager class objects.
3897 addcolors() - L<Imager::ImageTypes/addcolors>
3899 addtag() - L<Imager::ImageTypes/addtag> - add image tags
3901 align_string() - L<Imager::Draw/align_string>
3903 arc() - L<Imager::Draw/arc>
3905 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
3908 box() - L<Imager::Draw/box>
3910 circle() - L<Imager::Draw/circle>
3912 colorcount() - L<Imager::Draw/colorcount>
3914 convert() - L<Imager::Transformations/"Color transformations"> -
3915 transform the color space
3917 copy() - L<Imager::Transformations/copy>
3919 crop() - L<Imager::Transformations/crop> - extract part of an image
3921 def_guess_type() - L<Imager::Files/def_guess_type>
3923 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
3925 difference() - L<Imager::Filters/"Image Difference">
3927 errstr() - L<"Basic Overview">
3929 filter() - L<Imager::Filters>
3931 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
3934 flip() - L<Imager::Transformations/flip>
3936 flood_fill() - L<Imager::Draw/flood_fill>
3938 getchannels() - L<Imager::ImageTypes/getchannels>
3940 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
3942 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
3943 palette, if it has one
3945 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
3947 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
3949 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3951 getheight() - L<Imager::ImageTypes/getwidth>
3953 getmask() - L<Imager::ImageTypes/getmask>
3955 getpixel() - L<Imager::Draw/getpixel>
3957 getsamples() - L<Imager::Draw/getsamples>
3959 getscanline() - L<Imager::Draw/getscanline>
3961 getwidth() - L<Imager::ImageTypes/getwidth>
3963 img_set() - L<Imager::ImageTypes/img_set>
3965 init() - L<Imager::ImageTypes/init>
3967 is_bilevel() - L<Imager::ImageTypes/is_bilevel>
3969 line() - L<Imager::Draw/line>
3971 load_plugin() - L<Imager::Filters/load_plugin>
3973 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3976 masked() - L<Imager::ImageTypes/masked> - make a masked image
3978 matrix_transform() - L<Imager::Engines/matrix_transform>
3980 maxcolors() - L<Imager::ImageTypes/maxcolors>
3982 NC() - L<Imager::Handy/NC>
3984 NCF() - L<Imager::Handy/NCF>
3986 new() - L<Imager::ImageTypes/new>
3988 newcolor() - L<Imager::Handy/newcolor>
3990 newcolour() - L<Imager::Handy/newcolour>
3992 newfont() - L<Imager::Handy/newfont>
3994 NF() - L<Imager::Handy/NF>
3996 open() - L<Imager::Files> - an alias for read()
3998 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4001 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4003 polygon() - L<Imager::Draw/polygon>
4005 polyline() - L<Imager::Draw/polyline>
4007 read() - L<Imager::Files> - read a single image from an image file
4009 read_multi() - L<Imager::Files> - read multiple images from an image
4012 read_types() - L<Imager::Files/read_types> - list image types Imager
4015 register_filter() - L<Imager::Filters/register_filter>
4017 register_reader() - L<Imager::Filters/register_reader>
4019 register_writer() - L<Imager::Filters/register_writer>
4021 rotate() - L<Imager::Transformations/rotate>
4023 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4024 image and use the alpha channel
4026 scale() - L<Imager::Transformations/scale>
4028 scale_calculate() - L<Imager::Transformations/scale_calculate>
4030 scaleX() - L<Imager::Transformations/scaleX>
4032 scaleY() - L<Imager::Transformations/scaleY>
4034 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4037 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4039 setmask() - L<Imager::ImageTypes/setmask>
4041 setpixel() - L<Imager::Draw/setpixel>
4043 setsamples() - L<Imager::Draw/setsamples>
4045 setscanline() - L<Imager::Draw/setscanline>
4047 settag() - L<Imager::ImageTypes/settag>
4049 string() - L<Imager::Draw/string> - draw text on an image
4051 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4053 to_paletted() - L<Imager::ImageTypes/to_paletted>
4055 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4057 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4059 transform() - L<Imager::Engines/"transform">
4061 transform2() - L<Imager::Engines/"transform2">
4063 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4065 unload_plugin() - L<Imager::Filters/unload_plugin>
4067 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4070 write() - L<Imager::Files> - write an image to a file
4072 write_multi() - L<Imager::Files> - write multiple image to an image
4075 write_types() - L<Imager::Files/read_types> - list image types Imager
4078 =head1 CONCEPT INDEX
4080 animated GIF - L<Imager::Files/"Writing an animated GIF">
4082 aspect ratio - L<Imager::ImageTypes/i_xres>,
4083 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4085 blend - alpha blending one image onto another
4086 L<Imager::Transformations/rubthrough>
4088 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4090 boxes, drawing - L<Imager::Draw/box>
4092 changes between image - L<Imager::Filter/"Image Difference">
4094 color - L<Imager::Color>
4096 color names - L<Imager::Color>, L<Imager::Color::Table>
4098 combine modes - L<Imager::Fill/combine>
4100 compare images - L<Imager::Filter/"Image Difference">
4102 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
4104 convolution - L<Imager::Filter/conv>
4106 cropping - L<Imager::Transformations/crop>
4108 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4110 C<diff> images - L<Imager::Filter/"Image Difference">
4112 dpi - L<Imager::ImageTypes/i_xres>,
4113 L<Imager::Cookbook/"Image spatial resolution">
4115 drawing boxes - L<Imager::Draw/box>
4117 drawing lines - L<Imager::Draw/line>
4119 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4121 error message - L<"Basic Overview">
4123 files, font - L<Imager::Font>
4125 files, image - L<Imager::Files>
4127 filling, types of fill - L<Imager::Fill>
4129 filling, boxes - L<Imager::Draw/box>
4131 filling, flood fill - L<Imager::Draw/flood_fill>
4133 flood fill - L<Imager::Draw/flood_fill>
4135 fonts - L<Imager::Font>
4137 fonts, drawing with - L<Imager::Draw/string>,
4138 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4140 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4142 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4144 fountain fill - L<Imager::Fill/"Fountain fills">,
4145 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4146 L<Imager::Filters/gradgen>
4148 GIF files - L<Imager::Files/"GIF">
4150 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4152 gradient fill - L<Imager::Fill/"Fountain fills">,
4153 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4154 L<Imager::Filters/gradgen>
4156 grayscale, convert image to - L<Imager::Transformations/convert>
4158 guassian blur - L<Imager::Filter/guassian>
4160 hatch fills - L<Imager::Fill/"Hatched fills">
4162 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4164 invert image - L<Imager::Filter/hardinvert>
4166 JPEG - L<Imager::Files/"JPEG">
4168 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4170 lines, drawing - L<Imager::Draw/line>
4172 matrix - L<Imager::Matrix2d>,
4173 L<Imager::Transformations/"Matrix Transformations">,
4174 L<Imager::Font/transform>
4176 metadata, image - L<Imager::ImageTypes/"Tags">
4178 mosaic - L<Imager::Filter/mosaic>
4180 noise, filter - L<Imager::Filter/noise>
4182 noise, rendered - L<Imager::Filter/turbnoise>,
4183 L<Imager::Filter/radnoise>
4185 paste - L<Imager::Transformations/paste>,
4186 L<Imager::Transformations/rubthrough>
4188 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4189 L<Imager::ImageTypes/new>
4191 posterize - L<Imager::Filter/postlevels>
4193 png files - L<Imager::Files>, L<Imager::Files/"PNG">
4195 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
4197 rectangles, drawing - L<Imager::Draw/box>
4199 resizing an image - L<Imager::Transformations/scale>,
4200 L<Imager::Transformations/crop>
4202 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4204 saving an image - L<Imager::Files>
4206 scaling - L<Imager::Transformations/scale>
4208 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4210 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4212 size, image - L<Imager::ImageTypes/getwidth>,
4213 L<Imager::ImageTypes/getheight>
4215 size, text - L<Imager::Font/bounding_box>
4217 tags, image metadata - L<Imager::ImageTypes/"Tags">
4219 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4220 L<Imager::Font::Wrap>
4222 text, wrapping text in an area - L<Imager::Font::Wrap>
4224 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4226 tiles, color - L<Imager::Filter/mosaic>
4228 unsharp mask - L<Imager::Filter/unsharpmask>
4230 watermark - L<Imager::Filter/watermark>
4232 writing an image to a file - L<Imager::Files>
4236 The best place to get help with Imager is the mailing list.
4238 To subscribe send a message with C<subscribe> in the body to:
4240 imager-devel+request@molar.is
4246 L<http://www.molar.is/en/lists/imager-devel/>
4250 where you can also find the mailing list archive.
4252 You can report bugs by pointing your browser at:
4256 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4260 or by sending an email to:
4264 bug-Imager@rt.cpan.org
4268 Please remember to include the versions of Imager, perl, supporting
4269 libraries, and any relevant code. If you have specific images that
4270 cause the problems, please include those too.
4272 If you don't want to publish your email address on a mailing list you
4273 can use CPAN::Forum:
4275 http://www.cpanforum.com/dist/Imager
4277 You will need to register to post.
4279 =head1 CONTRIBUTING TO IMAGER
4285 If you like or dislike Imager, you can add a public review of Imager
4288 http://cpanratings.perl.org/dist/Imager
4290 This requires a Bitcard Account (http://www.bitcard.org).
4292 You can also send email to the maintainer below.
4294 If you send me a bug report via email, it will be copied to RT.
4298 I accept patches, preferably against the main branch in subversion.
4299 You should include an explanation of the reason for why the patch is
4302 Your patch should include regression tests where possible, otherwise
4303 it will be delayed until I get a chance to write them.
4307 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4309 Arnar M. Hrafnkelsson is the original author of Imager.
4311 Many others have contributed to Imager, please see the README for a
4316 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4317 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4318 L<Imager::Font>(3), L<Imager::Transformations>(3),
4319 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4320 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4322 L<http://imager.perl.org/>
4324 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4326 Other perl imaging modules include:
4328 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).