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}); }
247 callseq => ['image', 'coef'],
249 callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
254 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
255 defaults => { dist => 0 },
259 my @colors = @{$hsh{colors}};
262 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
266 $filters{nearest_color} =
268 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
273 # make sure the segments are specified with colors
275 for my $color (@{$hsh{colors}}) {
276 my $new_color = _color($color)
277 or die $Imager::ERRSTR."\n";
278 push @colors, $new_color;
281 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
283 or die Imager->_error_as_msg() . "\n";
286 $filters{gaussian} = {
287 callseq => [ 'image', 'stddev' ],
289 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
293 callseq => [ qw(image size) ],
294 defaults => { size => 20 },
295 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
299 callseq => [ qw(image bump elevation lightx lighty st) ],
300 defaults => { elevation=>0, st=> 2 },
303 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
304 $hsh{lightx}, $hsh{lighty}, $hsh{st});
307 $filters{bumpmap_complex} =
309 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
320 Ia => Imager::Color->new(rgb=>[0,0,0]),
321 Il => Imager::Color->new(rgb=>[255,255,255]),
322 Is => Imager::Color->new(rgb=>[255,255,255]),
326 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
327 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
328 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
332 $filters{postlevels} =
334 callseq => [ qw(image levels) ],
335 defaults => { levels => 10 },
336 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
338 $filters{watermark} =
340 callseq => [ qw(image wmark tx ty pixdiff) ],
341 defaults => { pixdiff=>10, tx=>0, ty=>0 },
345 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
351 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
353 ftype => { linear => 0,
359 repeat => { none => 0,
374 multiply => 2, mult => 2,
377 subtract => 5, 'sub' => 5,
387 defaults => { ftype => 0, repeat => 0, combine => 0,
388 super_sample => 0, ssample_param => 4,
391 Imager::Color->new(0,0,0),
392 Imager::Color->new(255, 255, 255),
401 # make sure the segments are specified with colors
403 for my $segment (@{$hsh{segments}}) {
404 my @new_segment = @$segment;
406 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
407 push @segments, \@new_segment;
410 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
411 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
412 $hsh{ssample_param}, \@segments)
413 or die Imager->_error_as_msg() . "\n";
416 $filters{unsharpmask} =
418 callseq => [ qw(image stddev scale) ],
419 defaults => { stddev=>2.0, scale=>1.0 },
423 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
427 $FORMATGUESS=\&def_guess_type;
437 # NOTE: this might be moved to an import override later on
442 if ($_[$i] eq '-log-stderr') {
450 goto &Exporter::import;
454 i_init_log($_[0],$_[1]);
455 i_log_entry("Imager $VERSION starting\n", 1);
460 my %parms=(loglevel=>1,@_);
462 init_log($parms{'log'},$parms{'loglevel'});
465 if (exists $parms{'warn_obsolete'}) {
466 $warn_obsolete = $parms{'warn_obsolete'};
469 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
470 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
474 if (exists $parms{'t1log'}) {
475 i_init_fonts($parms{'t1log'});
481 print "shutdown code\n";
482 # for(keys %instances) { $instances{$_}->DESTROY(); }
483 malloc_state(); # how do decide if this should be used? -- store something from the import
484 print "Imager exiting\n";
488 # Load a filter plugin
493 my ($DSO_handle,$str)=DSO_open($filename);
494 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
495 my %funcs=DSO_funclist($DSO_handle);
496 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
498 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
500 $DSOs{$filename}=[$DSO_handle,\%funcs];
503 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
504 $DEBUG && print "eval string:\n",$evstr,"\n";
516 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
517 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
518 for(keys %{$funcref}) {
520 $DEBUG && print "unloading: $_\n";
522 my $rc=DSO_close($DSO_handle);
523 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
527 # take the results of i_error() and make a message out of it
529 return join(": ", map $_->[0], i_errors());
532 # this function tries to DWIM for color parameters
533 # color objects are used as is
534 # simple scalars are simply treated as single parameters to Imager::Color->new
535 # hashrefs are treated as named argument lists to Imager::Color->new
536 # arrayrefs are treated as list arguments to Imager::Color->new iff any
538 # other arrayrefs are treated as list arguments to Imager::Color::Float
542 # perl 5.6.0 seems to do weird things to $arg if we don't make an
543 # explicitly stringified copy
544 # I vaguely remember a bug on this on p5p, but couldn't find it
545 # through bugs.perl.org (I had trouble getting it to find any bugs)
546 my $copy = $arg . "";
550 if (UNIVERSAL::isa($arg, "Imager::Color")
551 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
555 if ($copy =~ /^HASH\(/) {
556 $result = Imager::Color->new(%$arg);
558 elsif ($copy =~ /^ARRAY\(/) {
559 $result = Imager::Color->new(@$arg);
562 $Imager::ERRSTR = "Not a color";
567 # assume Imager::Color::new knows how to handle it
568 $result = Imager::Color->new($arg);
575 my ($self, $combine, $default) = @_;
577 if (!defined $combine && ref $self) {
578 $combine = $self->{combine};
580 defined $combine or $combine = $defaults{combine};
581 defined $combine or $combine = $default;
583 if (exists $combine_types{$combine}) {
584 $combine = $combine_types{$combine};
593 $self->{IMG} and return 1;
595 $self->_set_error('empty input image');
601 # Methods to be called on objects.
604 # Create a new Imager object takes very few parameters.
605 # usually you call this method and then call open from
606 # the resulting object
613 $self->{IMG}=undef; # Just to indicate what exists
614 $self->{ERRSTR}=undef; #
615 $self->{DEBUG}=$DEBUG;
616 $self->{DEBUG} && print "Initialized Imager\n";
617 if (defined $hsh{xsize} && defined $hsh{ysize}) {
618 unless ($self->img_set(%hsh)) {
619 $Imager::ERRSTR = $self->{ERRSTR};
626 # Copy an entire image with no changes
627 # - if an image has magic the copy of it will not be magical
631 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
633 unless (defined wantarray) {
635 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
639 my $newcopy=Imager->new();
640 $newcopy->{IMG} = i_copy($self->{IMG});
649 unless ($self->{IMG}) {
650 $self->_set_error('empty input image');
653 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
654 my $src = $input{img} || $input{src};
656 $self->_set_error("no source image");
659 $input{left}=0 if $input{left} <= 0;
660 $input{top}=0 if $input{top} <= 0;
662 my($r,$b)=i_img_info($src->{IMG});
663 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
664 my ($src_right, $src_bottom);
665 if ($input{src_coords}) {
666 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
669 if (defined $input{src_maxx}) {
670 $src_right = $input{src_maxx};
672 elsif (defined $input{width}) {
673 if ($input{width} <= 0) {
674 $self->_set_error("paste: width must me positive");
677 $src_right = $src_left + $input{width};
682 if (defined $input{src_maxy}) {
683 $src_bottom = $input{src_maxy};
685 elsif (defined $input{height}) {
686 if ($input{height} < 0) {
687 $self->_set_error("paste: height must be positive");
690 $src_bottom = $src_top + $input{height};
697 $src_right > $r and $src_right = $r;
698 $src_bottom > $b and $src_bottom = $b;
700 if ($src_right <= $src_left
701 || $src_bottom < $src_top) {
702 $self->_set_error("nothing to paste");
706 i_copyto($self->{IMG}, $src->{IMG},
707 $src_left, $src_top, $src_right, $src_bottom,
708 $input{left}, $input{top});
710 return $self; # What should go here??
713 # Crop an image - i.e. return a new image that is smaller
717 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
719 unless (defined wantarray) {
721 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
727 my ($w, $h, $l, $r, $b, $t) =
728 @hsh{qw(width height left right bottom top)};
730 # work through the various possibilities
735 elsif (!defined $r) {
736 $r = $self->getwidth;
748 $l = int(0.5+($self->getwidth()-$w)/2);
753 $r = $self->getwidth;
759 elsif (!defined $b) {
760 $b = $self->getheight;
772 $t=int(0.5+($self->getheight()-$h)/2);
777 $b = $self->getheight;
780 ($l,$r)=($r,$l) if $l>$r;
781 ($t,$b)=($b,$t) if $t>$b;
784 $r > $self->getwidth and $r = $self->getwidth;
786 $b > $self->getheight and $b = $self->getheight;
788 if ($l == $r || $t == $b) {
789 $self->_set_error("resulting image would have no content");
792 if( $r < $l or $b < $t ) {
793 $self->_set_error("attempting to crop outside of the image");
796 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
798 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
803 my ($self, %opts) = @_;
805 $self->{IMG} or return $self->_set_error("Not a valid image");
807 my $x = $opts{xsize} || $self->getwidth;
808 my $y = $opts{ysize} || $self->getheight;
809 my $channels = $opts{channels} || $self->getchannels;
811 my $out = Imager->new;
812 if ($channels == $self->getchannels) {
813 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
816 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
818 unless ($out->{IMG}) {
819 $self->{ERRSTR} = $self->_error_as_msg;
826 # Sets an image to a certain size and channel number
827 # if there was previously data in the image it is discarded
832 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
834 if (defined($self->{IMG})) {
835 # let IIM_DESTROY destroy it, it's possible this image is
836 # referenced from a virtual image (like masked)
837 #i_img_destroy($self->{IMG});
841 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
842 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
843 $hsh{maxcolors} || 256);
845 elsif ($hsh{bits} eq 'double') {
846 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
848 elsif ($hsh{bits} == 16) {
849 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
852 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
856 unless ($self->{IMG}) {
857 $self->{ERRSTR} = Imager->_error_as_msg();
864 # created a masked version of the current image
868 $self or return undef;
869 my %opts = (left => 0,
871 right => $self->getwidth,
872 bottom => $self->getheight,
874 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
876 my $result = Imager->new;
877 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
878 $opts{top}, $opts{right} - $opts{left},
879 $opts{bottom} - $opts{top});
880 # keep references to the mask and base images so they don't
882 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
887 # convert an RGB image into a paletted image
891 if (@_ != 1 && !ref $_[0]) {
898 unless (defined wantarray) {
900 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
904 my $result = Imager->new;
905 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
907 #print "Type ", i_img_type($result->{IMG}), "\n";
909 if ($result->{IMG}) {
913 $self->{ERRSTR} = $self->_error_as_msg;
918 # convert a paletted (or any image) to an 8-bit/channel RGB images
923 unless (defined wantarray) {
925 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
930 $result = Imager->new;
931 $result->{IMG} = i_img_to_rgb($self->{IMG})
938 # convert a paletted (or any image) to an 8-bit/channel RGB images
943 unless (defined wantarray) {
945 warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
950 $result = Imager->new;
951 $result->{IMG} = i_img_to_rgb16($self->{IMG})
960 my %opts = (colors=>[], @_);
962 unless ($self->{IMG}) {
963 $self->_set_error("empty input image");
967 my @colors = @{$opts{colors}}
970 for my $color (@colors) {
971 $color = _color($color);
973 $self->_set_error($Imager::ERRSTR);
978 return i_addcolors($self->{IMG}, @colors);
983 my %opts = (start=>0, colors=>[], @_);
985 unless ($self->{IMG}) {
986 $self->_set_error("empty input image");
990 my @colors = @{$opts{colors}}
993 for my $color (@colors) {
994 $color = _color($color);
996 $self->_set_error($Imager::ERRSTR);
1001 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1007 if (!exists $opts{start} && !exists $opts{count}) {
1010 $opts{count} = $self->colorcount;
1012 elsif (!exists $opts{count}) {
1015 elsif (!exists $opts{start}) {
1020 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1024 i_colorcount($_[0]{IMG});
1028 i_maxcolors($_[0]{IMG});
1034 $opts{color} or return undef;
1036 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1041 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1042 if ($bits && $bits == length(pack("d", 1)) * 8) {
1051 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1057 $self->{IMG} and i_img_virtual($self->{IMG});
1063 $self->{IMG} or return;
1065 return i_img_is_monochrome($self->{IMG});
1069 my ($self, %opts) = @_;
1071 $self->{IMG} or return;
1073 if (defined $opts{name}) {
1077 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1078 push @result, (i_tags_get($self->{IMG}, $found))[1];
1081 return wantarray ? @result : $result[0];
1083 elsif (defined $opts{code}) {
1087 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1088 push @result, (i_tags_get($self->{IMG}, $found))[1];
1095 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1098 return i_tags_count($self->{IMG});
1107 return -1 unless $self->{IMG};
1109 if (defined $opts{value}) {
1110 if ($opts{value} =~ /^\d+$/) {
1112 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1115 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1118 elsif (defined $opts{data}) {
1119 # force addition as a string
1120 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1123 $self->{ERRSTR} = "No value supplied";
1127 elsif ($opts{code}) {
1128 if (defined $opts{value}) {
1129 if ($opts{value} =~ /^\d+$/) {
1131 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1134 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1137 elsif (defined $opts{data}) {
1138 # force addition as a string
1139 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1142 $self->{ERRSTR} = "No value supplied";
1155 return 0 unless $self->{IMG};
1157 if (defined $opts{'index'}) {
1158 return i_tags_delete($self->{IMG}, $opts{'index'});
1160 elsif (defined $opts{name}) {
1161 return i_tags_delbyname($self->{IMG}, $opts{name});
1163 elsif (defined $opts{code}) {
1164 return i_tags_delbycode($self->{IMG}, $opts{code});
1167 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1173 my ($self, %opts) = @_;
1176 $self->deltag(name=>$opts{name});
1177 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1179 elsif (defined $opts{code}) {
1180 $self->deltag(code=>$opts{code});
1181 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1189 sub _get_reader_io {
1190 my ($self, $input) = @_;
1193 return $input->{io}, undef;
1195 elsif ($input->{fd}) {
1196 return io_new_fd($input->{fd});
1198 elsif ($input->{fh}) {
1199 my $fd = fileno($input->{fh});
1201 $self->_set_error("Handle in fh option not opened");
1204 return io_new_fd($fd);
1206 elsif ($input->{file}) {
1207 my $file = IO::File->new($input->{file}, "r");
1209 $self->_set_error("Could not open $input->{file}: $!");
1213 return (io_new_fd(fileno($file)), $file);
1215 elsif ($input->{data}) {
1216 return io_new_buffer($input->{data});
1218 elsif ($input->{callback} || $input->{readcb}) {
1219 if (!$input->{seekcb}) {
1220 $self->_set_error("Need a seekcb parameter");
1222 if ($input->{maxbuffer}) {
1223 return io_new_cb($input->{writecb},
1224 $input->{callback} || $input->{readcb},
1225 $input->{seekcb}, $input->{closecb},
1226 $input->{maxbuffer});
1229 return io_new_cb($input->{writecb},
1230 $input->{callback} || $input->{readcb},
1231 $input->{seekcb}, $input->{closecb});
1235 $self->_set_error("file/fd/fh/data/callback parameter missing");
1240 sub _get_writer_io {
1241 my ($self, $input, $type) = @_;
1244 return $input->{io};
1246 elsif ($input->{fd}) {
1247 return io_new_fd($input->{fd});
1249 elsif ($input->{fh}) {
1250 my $fd = fileno($input->{fh});
1252 $self->_set_error("Handle in fh option not opened");
1256 my $oldfh = select($input->{fh});
1257 # flush anything that's buffered, and make sure anything else is flushed
1260 return io_new_fd($fd);
1262 elsif ($input->{file}) {
1263 my $fh = new IO::File($input->{file},"w+");
1265 $self->_set_error("Could not open file $input->{file}: $!");
1268 binmode($fh) or die;
1269 return (io_new_fd(fileno($fh)), $fh);
1271 elsif ($input->{data}) {
1272 return io_new_bufchain();
1274 elsif ($input->{callback} || $input->{writecb}) {
1275 if ($input->{maxbuffer}) {
1276 return io_new_cb($input->{callback} || $input->{writecb},
1278 $input->{seekcb}, $input->{closecb},
1279 $input->{maxbuffer});
1282 return io_new_cb($input->{callback} || $input->{writecb},
1284 $input->{seekcb}, $input->{closecb});
1288 $self->_set_error("file/fd/fh/data/callback parameter missing");
1293 # Read an image from file
1299 if (defined($self->{IMG})) {
1300 # let IIM_DESTROY do the destruction, since the image may be
1301 # referenced from elsewhere
1302 #i_img_destroy($self->{IMG});
1303 undef($self->{IMG});
1306 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1308 unless ($input{'type'}) {
1309 $input{'type'} = i_test_format_probe($IO, -1);
1312 unless ($input{'type'}) {
1313 $self->_set_error('type parameter missing and not possible to guess from extension');
1317 _reader_autoload($input{type});
1319 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1320 return $readers{$input{type}}{single}->($self, $IO, %input);
1323 unless ($formats{$input{'type'}}) {
1324 my $read_types = join ', ', sort Imager->read_types();
1325 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1330 if ( $input{'type'} eq 'jpeg' ) {
1331 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1332 if ( !defined($self->{IMG}) ) {
1333 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1335 $self->{DEBUG} && print "loading a jpeg file\n";
1339 my $allow_incomplete = $input{allow_incomplete};
1340 defined $allow_incomplete or $allow_incomplete = 0;
1342 if ( $input{'type'} eq 'tiff' ) {
1343 my $page = $input{'page'};
1344 defined $page or $page = 0;
1345 $self->{IMG}=i_readtiff_wiol( $IO, $allow_incomplete, $page );
1346 if ( !defined($self->{IMG}) ) {
1347 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1349 $self->{DEBUG} && print "loading a tiff file\n";
1353 if ( $input{'type'} eq 'pnm' ) {
1354 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1355 if ( !defined($self->{IMG}) ) {
1356 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1359 $self->{DEBUG} && print "loading a pnm file\n";
1363 if ( $input{'type'} eq 'png' ) {
1364 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1365 if ( !defined($self->{IMG}) ) {
1366 $self->{ERRSTR} = $self->_error_as_msg();
1369 $self->{DEBUG} && print "loading a png file\n";
1372 if ( $input{'type'} eq 'bmp' ) {
1373 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1374 if ( !defined($self->{IMG}) ) {
1375 $self->{ERRSTR}=$self->_error_as_msg();
1378 $self->{DEBUG} && print "loading a bmp file\n";
1381 if ( $input{'type'} eq 'gif' ) {
1382 if ($input{colors} && !ref($input{colors})) {
1383 # must be a reference to a scalar that accepts the colour map
1384 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1387 if ($input{'gif_consolidate'}) {
1388 if ($input{colors}) {
1390 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1392 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1396 $self->{IMG} =i_readgif_wiol( $IO );
1400 my $page = $input{'page'};
1401 defined $page or $page = 0;
1402 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1403 if ($self->{IMG} && $input{colors}) {
1404 ${ $input{colors} } =
1405 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1409 if ( !defined($self->{IMG}) ) {
1410 $self->{ERRSTR}=$self->_error_as_msg();
1413 $self->{DEBUG} && print "loading a gif file\n";
1416 if ( $input{'type'} eq 'tga' ) {
1417 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1418 if ( !defined($self->{IMG}) ) {
1419 $self->{ERRSTR}=$self->_error_as_msg();
1422 $self->{DEBUG} && print "loading a tga file\n";
1425 if ( $input{'type'} eq 'raw' ) {
1426 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1428 if ( !($params{xsize} && $params{ysize}) ) {
1429 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1433 $self->{IMG} = i_readraw_wiol( $IO,
1436 $params{datachannels},
1437 $params{storechannels},
1438 $params{interleave});
1439 if ( !defined($self->{IMG}) ) {
1440 $self->{ERRSTR}=$self->_error_as_msg();
1443 $self->{DEBUG} && print "loading a raw file\n";
1449 sub register_reader {
1450 my ($class, %opts) = @_;
1453 or die "register_reader called with no type parameter\n";
1455 my $type = $opts{type};
1457 defined $opts{single} || defined $opts{multiple}
1458 or die "register_reader called with no single or multiple parameter\n";
1460 $readers{$type} = { };
1461 if ($opts{single}) {
1462 $readers{$type}{single} = $opts{single};
1464 if ($opts{multiple}) {
1465 $readers{$type}{multiple} = $opts{multiple};
1471 sub register_writer {
1472 my ($class, %opts) = @_;
1475 or die "register_writer called with no type parameter\n";
1477 my $type = $opts{type};
1479 defined $opts{single} || defined $opts{multiple}
1480 or die "register_writer called with no single or multiple parameter\n";
1482 $writers{$type} = { };
1483 if ($opts{single}) {
1484 $writers{$type}{single} = $opts{single};
1486 if ($opts{multiple}) {
1487 $writers{$type}{multiple} = $opts{multiple};
1498 grep($file_formats{$_}, keys %formats),
1499 qw(ico sgi), # formats not handled directly, but supplied with Imager
1510 grep($file_formats{$_}, keys %formats),
1511 qw(ico sgi), # formats not handled directly, but supplied with Imager
1517 # probes for an Imager::File::whatever module
1518 sub _reader_autoload {
1521 return if $formats{$type} || $readers{$type};
1523 return unless $type =~ /^\w+$/;
1525 my $file = "Imager/File/\U$type\E.pm";
1527 unless ($attempted_to_load{$file}) {
1529 ++$attempted_to_load{$file};
1533 # try to get a reader specific module
1534 my $file = "Imager/File/\U$type\EReader.pm";
1535 unless ($attempted_to_load{$file}) {
1537 ++$attempted_to_load{$file};
1545 # probes for an Imager::File::whatever module
1546 sub _writer_autoload {
1549 return if $formats{$type} || $readers{$type};
1551 return unless $type =~ /^\w+$/;
1553 my $file = "Imager/File/\U$type\E.pm";
1555 unless ($attempted_to_load{$file}) {
1557 ++$attempted_to_load{$file};
1561 # try to get a writer specific module
1562 my $file = "Imager/File/\U$type\EWriter.pm";
1563 unless ($attempted_to_load{$file}) {
1565 ++$attempted_to_load{$file};
1573 sub _fix_gif_positions {
1574 my ($opts, $opt, $msg, @imgs) = @_;
1576 my $positions = $opts->{'gif_positions'};
1578 for my $pos (@$positions) {
1579 my ($x, $y) = @$pos;
1580 my $img = $imgs[$index++];
1581 $img->settag(name=>'gif_left', value=>$x);
1582 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1584 $$msg .= "replaced with the gif_left and gif_top tags";
1589 gif_each_palette=>'gif_local_map',
1590 interlace => 'gif_interlace',
1591 gif_delays => 'gif_delay',
1592 gif_positions => \&_fix_gif_positions,
1593 gif_loop_count => 'gif_loop',
1596 # options that should be converted to colors
1597 my %color_opts = map { $_ => 1 } qw/i_background/;
1600 my ($self, $opts, $prefix, @imgs) = @_;
1602 for my $opt (keys %$opts) {
1604 if ($obsolete_opts{$opt}) {
1605 my $new = $obsolete_opts{$opt};
1606 my $msg = "Obsolete option $opt ";
1608 $new->($opts, $opt, \$msg, @imgs);
1611 $msg .= "replaced with the $new tag ";
1614 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1615 warn $msg if $warn_obsolete && $^W;
1617 next unless $tagname =~ /^\Q$prefix/;
1618 my $value = $opts->{$opt};
1619 if ($color_opts{$opt}) {
1620 $value = _color($value);
1622 $self->_set_error($Imager::ERRSTR);
1627 if (UNIVERSAL::isa($value, "Imager::Color")) {
1628 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1629 for my $img (@imgs) {
1630 $img->settag(name=>$tagname, value=>$tag);
1633 elsif (ref($value) eq 'ARRAY') {
1634 for my $i (0..$#$value) {
1635 my $val = $value->[$i];
1637 if (UNIVERSAL::isa($val, "Imager::Color")) {
1638 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1640 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1643 $self->_set_error("Unknown reference type " . ref($value) .
1644 " supplied in array for $opt");
1650 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1655 $self->_set_error("Unknown reference type " . ref($value) .
1656 " supplied for $opt");
1661 # set it as a tag for every image
1662 for my $img (@imgs) {
1663 $img->settag(name=>$tagname, value=>$value);
1671 # Write an image to file
1674 my %input=(jpegquality=>75,
1684 $self->_set_opts(\%input, "i_", $self)
1687 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1689 if (!$input{'type'} and $input{file}) {
1690 $input{'type'}=$FORMATGUESS->($input{file});
1692 if (!$input{'type'}) {
1693 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1697 _writer_autoload($input{type});
1700 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1701 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1704 $writers{$input{type}}{single}->($self, $IO, %input)
1708 if (!$formats{$input{'type'}}) {
1709 my $write_types = join ', ', sort Imager->write_types();
1710 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1714 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1717 if ($input{'type'} eq 'tiff') {
1718 $self->_set_opts(\%input, "tiff_", $self)
1720 $self->_set_opts(\%input, "exif_", $self)
1723 if (defined $input{class} && $input{class} eq 'fax') {
1724 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1725 $self->{ERRSTR} = $self->_error_as_msg();
1729 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1730 $self->{ERRSTR} = $self->_error_as_msg();
1734 } elsif ( $input{'type'} eq 'pnm' ) {
1735 $self->_set_opts(\%input, "pnm_", $self)
1737 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1738 $self->{ERRSTR} = $self->_error_as_msg();
1741 $self->{DEBUG} && print "writing a pnm file\n";
1742 } elsif ( $input{'type'} eq 'raw' ) {
1743 $self->_set_opts(\%input, "raw_", $self)
1745 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1746 $self->{ERRSTR} = $self->_error_as_msg();
1749 $self->{DEBUG} && print "writing a raw file\n";
1750 } elsif ( $input{'type'} eq 'png' ) {
1751 $self->_set_opts(\%input, "png_", $self)
1753 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1754 $self->{ERRSTR}='unable to write png image';
1757 $self->{DEBUG} && print "writing a png file\n";
1758 } elsif ( $input{'type'} eq 'jpeg' ) {
1759 $self->_set_opts(\%input, "jpeg_", $self)
1761 $self->_set_opts(\%input, "exif_", $self)
1763 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1764 $self->{ERRSTR} = $self->_error_as_msg();
1767 $self->{DEBUG} && print "writing a jpeg file\n";
1768 } elsif ( $input{'type'} eq 'bmp' ) {
1769 $self->_set_opts(\%input, "bmp_", $self)
1771 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1772 $self->{ERRSTR} = $self->_error_as_msg;
1775 $self->{DEBUG} && print "writing a bmp file\n";
1776 } elsif ( $input{'type'} eq 'tga' ) {
1777 $self->_set_opts(\%input, "tga_", $self)
1780 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1781 $self->{ERRSTR}=$self->_error_as_msg();
1784 $self->{DEBUG} && print "writing a tga file\n";
1785 } elsif ( $input{'type'} eq 'gif' ) {
1786 $self->_set_opts(\%input, "gif_", $self)
1788 # compatibility with the old interfaces
1789 if ($input{gifquant} eq 'lm') {
1790 $input{make_colors} = 'addi';
1791 $input{translate} = 'perturb';
1792 $input{perturb} = $input{lmdither};
1793 } elsif ($input{gifquant} eq 'gen') {
1794 # just pass options through
1796 $input{make_colors} = 'webmap'; # ignored
1797 $input{translate} = 'giflib';
1799 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1800 $self->{ERRSTR} = $self->_error_as_msg;
1806 if (exists $input{'data'}) {
1807 my $data = io_slurp($IO);
1809 $self->{ERRSTR}='Could not slurp from buffer';
1812 ${$input{data}} = $data;
1818 my ($class, $opts, @images) = @_;
1820 my $type = $opts->{type};
1822 if (!$type && $opts->{'file'}) {
1823 $type = $FORMATGUESS->($opts->{'file'});
1826 $class->_set_error('type parameter missing and not possible to guess from extension');
1829 # translate to ImgRaw
1830 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1831 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1834 $class->_set_opts($opts, "i_", @images)
1836 my @work = map $_->{IMG}, @images;
1838 _writer_autoload($type);
1841 if ($writers{$type} && $writers{$type}{multiple}) {
1842 ($IO, $file) = $class->_get_writer_io($opts, $type)
1845 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1849 if (!$formats{$type}) {
1850 my $write_types = join ', ', sort Imager->write_types();
1851 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1855 ($IO, $file) = $class->_get_writer_io($opts, $type)
1858 if ($type eq 'gif') {
1859 $class->_set_opts($opts, "gif_", @images)
1861 my $gif_delays = $opts->{gif_delays};
1862 local $opts->{gif_delays} = $gif_delays;
1863 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1864 # assume the caller wants the same delay for each frame
1865 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1867 unless (i_writegif_wiol($IO, $opts, @work)) {
1868 $class->_set_error($class->_error_as_msg());
1872 elsif ($type eq 'tiff') {
1873 $class->_set_opts($opts, "tiff_", @images)
1875 $class->_set_opts($opts, "exif_", @images)
1878 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1879 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1880 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1883 $res = i_writetiff_multi_wiol($IO, @work);
1886 $class->_set_error($class->_error_as_msg());
1892 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1897 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1903 if (exists $opts->{'data'}) {
1904 my $data = io_slurp($IO);
1906 Imager->_set_error('Could not slurp from buffer');
1909 ${$opts->{data}} = $data;
1914 # read multiple images from a file
1916 my ($class, %opts) = @_;
1918 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1921 my $type = $opts{'type'};
1923 $type = i_test_format_probe($IO, -1);
1926 if ($opts{file} && !$type) {
1928 $type = $FORMATGUESS->($opts{file});
1932 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1936 _reader_autoload($type);
1938 if ($readers{$type} && $readers{$type}{multiple}) {
1939 return $readers{$type}{multiple}->($IO, %opts);
1942 if ($type eq 'gif') {
1944 @imgs = i_readgif_multi_wiol($IO);
1947 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1951 $ERRSTR = _error_as_msg();
1955 elsif ($type eq 'tiff') {
1956 my @imgs = i_readtiff_multi_wiol($IO, -1);
1959 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1963 $ERRSTR = _error_as_msg();
1968 my $img = Imager->new;
1969 if ($img->read(%opts, io => $IO, type => $type)) {
1972 Imager->_set_error($img->errstr);
1978 # Destroy an Imager object
1982 # delete $instances{$self};
1983 if (defined($self->{IMG})) {
1984 # the following is now handled by the XS DESTROY method for
1985 # Imager::ImgRaw object
1986 # Re-enabling this will break virtual images
1987 # tested for in t/t020masked.t
1988 # i_img_destroy($self->{IMG});
1989 undef($self->{IMG});
1991 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1995 # Perform an inplace filter of an image
1996 # that is the image will be overwritten with the data
2002 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2004 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2006 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2007 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2010 if ($filters{$input{'type'}}{names}) {
2011 my $names = $filters{$input{'type'}}{names};
2012 for my $name (keys %$names) {
2013 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2014 $input{$name} = $names->{$name}{$input{$name}};
2018 if (defined($filters{$input{'type'}}{defaults})) {
2019 %hsh=( image => $self->{IMG},
2021 %{$filters{$input{'type'}}{defaults}},
2024 %hsh=( image => $self->{IMG},
2029 my @cs=@{$filters{$input{'type'}}{callseq}};
2032 if (!defined($hsh{$_})) {
2033 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2038 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2039 &{$filters{$input{'type'}}{callsub}}(%hsh);
2042 chomp($self->{ERRSTR} = $@);
2048 $self->{DEBUG} && print "callseq is: @cs\n";
2049 $self->{DEBUG} && print "matching callseq is: @b\n";
2054 sub register_filter {
2056 my %hsh = ( defaults => {}, @_ );
2059 or die "register_filter() with no type\n";
2060 defined $hsh{callsub}
2061 or die "register_filter() with no callsub\n";
2062 defined $hsh{callseq}
2063 or die "register_filter() with no callseq\n";
2065 exists $filters{$hsh{type}}
2068 $filters{$hsh{type}} = \%hsh;
2073 sub scale_calculate {
2076 my %opts = ('type'=>'max', @_);
2078 my ($x_scale, $y_scale);
2079 my $width = $opts{width};
2080 my $height = $opts{height};
2082 defined $width or $width = $self->getwidth;
2083 defined $height or $height = $self->getheight;
2086 unless (defined $width && defined $height) {
2087 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2092 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2093 $x_scale = $opts{'xscalefactor'};
2094 $y_scale = $opts{'yscalefactor'};
2096 elsif ($opts{'xscalefactor'}) {
2097 $x_scale = $opts{'xscalefactor'};
2098 $y_scale = $opts{'scalefactor'} || $x_scale;
2100 elsif ($opts{'yscalefactor'}) {
2101 $y_scale = $opts{'yscalefactor'};
2102 $x_scale = $opts{'scalefactor'} || $y_scale;
2105 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2108 # work out the scaling
2109 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2110 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2111 $opts{ypixels} / $height );
2112 if ($opts{'type'} eq 'min') {
2113 $x_scale = $y_scale = _min($xpix,$ypix);
2115 elsif ($opts{'type'} eq 'max') {
2116 $x_scale = $y_scale = _max($xpix,$ypix);
2118 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2123 $self->_set_error('invalid value for type parameter');
2126 } elsif ($opts{xpixels}) {
2127 $x_scale = $y_scale = $opts{xpixels} / $width;
2129 elsif ($opts{ypixels}) {
2130 $x_scale = $y_scale = $opts{ypixels}/$height;
2132 elsif ($opts{constrain} && ref $opts{constrain}
2133 && $opts{constrain}->can('constrain')) {
2134 # we've been passed an Image::Math::Constrain object or something
2135 # that looks like one
2137 (undef, undef, $scalefactor)
2138 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2139 unless ($scalefactor) {
2140 $self->_set_error('constrain method failed on constrain parameter');
2143 $x_scale = $y_scale = $scalefactor;
2146 my $new_width = int($x_scale * $width + 0.5);
2147 $new_width > 0 or $new_width = 1;
2148 my $new_height = int($y_scale * $height + 0.5);
2149 $new_height > 0 or $new_height = 1;
2151 return ($x_scale, $y_scale, $new_width, $new_height);
2155 # Scale an image to requested size and return the scaled version
2159 my %opts = (qtype=>'normal' ,@_);
2160 my $img = Imager->new();
2161 my $tmp = Imager->new();
2163 unless (defined wantarray) {
2164 my @caller = caller;
2165 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2169 unless ($self->{IMG}) {
2170 $self->_set_error('empty input image');
2174 my ($x_scale, $y_scale, $new_width, $new_height) =
2175 $self->scale_calculate(%opts)
2178 if ($opts{qtype} eq 'normal') {
2179 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2180 if ( !defined($tmp->{IMG}) ) {
2181 $self->{ERRSTR} = 'unable to scale image';
2184 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2185 if ( !defined($img->{IMG}) ) {
2186 $self->{ERRSTR}='unable to scale image';
2192 elsif ($opts{'qtype'} eq 'preview') {
2193 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2194 if ( !defined($img->{IMG}) ) {
2195 $self->{ERRSTR}='unable to scale image';
2200 elsif ($opts{'qtype'} eq 'mixing') {
2201 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2202 unless ($img->{IMG}) {
2203 $self->_set_error(Imager->_error_as_meg);
2209 $self->_set_error('invalid value for qtype parameter');
2214 # Scales only along the X axis
2218 my %opts = ( scalefactor=>0.5, @_ );
2220 unless (defined wantarray) {
2221 my @caller = caller;
2222 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2226 unless ($self->{IMG}) {
2227 $self->{ERRSTR} = 'empty input image';
2231 my $img = Imager->new();
2233 my $scalefactor = $opts{scalefactor};
2235 if ($opts{pixels}) {
2236 $scalefactor = $opts{pixels} / $self->getwidth();
2239 unless ($self->{IMG}) {
2240 $self->{ERRSTR}='empty input image';
2244 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2246 if ( !defined($img->{IMG}) ) {
2247 $self->{ERRSTR} = 'unable to scale image';
2254 # Scales only along the Y axis
2258 my %opts = ( scalefactor => 0.5, @_ );
2260 unless (defined wantarray) {
2261 my @caller = caller;
2262 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2266 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2268 my $img = Imager->new();
2270 my $scalefactor = $opts{scalefactor};
2272 if ($opts{pixels}) {
2273 $scalefactor = $opts{pixels} / $self->getheight();
2276 unless ($self->{IMG}) {
2277 $self->{ERRSTR} = 'empty input image';
2280 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2282 if ( !defined($img->{IMG}) ) {
2283 $self->{ERRSTR} = 'unable to scale image';
2290 # Transform returns a spatial transformation of the input image
2291 # this moves pixels to a new location in the returned image.
2292 # NOTE - should make a utility function to check transforms for
2297 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2299 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2301 # print Dumper(\%opts);
2304 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2306 eval ("use Affix::Infix2Postfix;");
2309 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2312 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2313 {op=>'-',trans=>'Sub'},
2314 {op=>'*',trans=>'Mult'},
2315 {op=>'/',trans=>'Div'},
2316 {op=>'-','type'=>'unary',trans=>'u-'},
2318 {op=>'func','type'=>'unary'}],
2319 'grouping'=>[qw( \( \) )],
2320 'func'=>[qw( sin cos )],
2325 @xt=$I2P->translate($opts{'xexpr'});
2326 @yt=$I2P->translate($opts{'yexpr'});
2328 $numre=$I2P->{'numre'};
2331 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2332 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2333 @{$opts{'parm'}}=@pt;
2336 # print Dumper(\%opts);
2338 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2339 $self->{ERRSTR}='transform: no xopcodes given.';
2343 @op=@{$opts{'xopcodes'}};
2345 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2346 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2349 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2355 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2356 $self->{ERRSTR}='transform: no yopcodes given.';
2360 @op=@{$opts{'yopcodes'}};
2362 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2363 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2366 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2371 if ( !exists $opts{'parm'}) {
2372 $self->{ERRSTR}='transform: no parameter arg given.';
2376 # print Dumper(\@ropx);
2377 # print Dumper(\@ropy);
2378 # print Dumper(\@ropy);
2380 my $img = Imager->new();
2381 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2382 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2388 my ($opts, @imgs) = @_;
2390 require "Imager/Expr.pm";
2392 $opts->{variables} = [ qw(x y) ];
2393 my ($width, $height) = @{$opts}{qw(width height)};
2395 $width ||= $imgs[0]->getwidth();
2396 $height ||= $imgs[0]->getheight();
2398 for my $img (@imgs) {
2399 $opts->{constants}{"w$img_num"} = $img->getwidth();
2400 $opts->{constants}{"h$img_num"} = $img->getheight();
2401 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2402 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2407 $opts->{constants}{w} = $width;
2408 $opts->{constants}{cx} = $width/2;
2411 $Imager::ERRSTR = "No width supplied";
2415 $opts->{constants}{h} = $height;
2416 $opts->{constants}{cy} = $height/2;
2419 $Imager::ERRSTR = "No height supplied";
2422 my $code = Imager::Expr->new($opts);
2424 $Imager::ERRSTR = Imager::Expr::error();
2427 my $channels = $opts->{channels} || 3;
2428 unless ($channels >= 1 && $channels <= 4) {
2429 return Imager->_set_error("channels must be an integer between 1 and 4");
2432 my $img = Imager->new();
2433 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2434 $channels, $code->code(),
2435 $code->nregs(), $code->cregs(),
2436 [ map { $_->{IMG} } @imgs ]);
2437 if (!defined $img->{IMG}) {
2438 $Imager::ERRSTR = Imager->_error_as_msg();
2449 unless ($self->{IMG}) {
2450 $self->{ERRSTR}='empty input image';
2453 unless ($opts{src} && $opts{src}->{IMG}) {
2454 $self->{ERRSTR}='empty input image for src';
2458 %opts = (src_minx => 0,
2460 src_maxx => $opts{src}->getwidth(),
2461 src_maxy => $opts{src}->getheight(),
2465 defined $tx or $tx = $opts{left};
2466 defined $tx or $tx = 0;
2469 defined $ty or $ty = $opts{top};
2470 defined $ty or $ty = 0;
2472 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2473 $opts{src_minx}, $opts{src_miny},
2474 $opts{src_maxx}, $opts{src_maxy})) {
2475 $self->_set_error($self->_error_as_msg());
2492 unless ($self->{IMG}) {
2493 $self->_set_error("compose: empty input image");
2497 unless ($opts{src}) {
2498 $self->_set_error("compose: src parameter missing");
2502 unless ($opts{src}{IMG}) {
2503 $self->_set_error("compose: src parameter empty image");
2506 my $src = $opts{src};
2508 my $left = $opts{left};
2509 defined $left or $left = $opts{tx};
2510 defined $left or $left = 0;
2512 my $top = $opts{top};
2513 defined $top or $top = $opts{ty};
2514 defined $top or $top = 0;
2516 my $src_left = $opts{src_left};
2517 defined $src_left or $src_left = $opts{src_minx};
2518 defined $src_left or $src_left = 0;
2520 my $src_top = $opts{src_top};
2521 defined $src_top or $src_top = $opts{src_miny};
2522 defined $src_top or $src_top = 0;
2524 my $width = $opts{width};
2525 if (!defined $width && defined $opts{src_maxx}) {
2526 $width = $opts{src_maxx} - $src_left;
2528 defined $width or $width = $src->getwidth() - $src_left;
2530 my $height = $opts{height};
2531 if (!defined $height && defined $opts{src_maxy}) {
2532 $height = $opts{src_maxy} - $src_top;
2534 defined $height or $height = $src->getheight() - $src_top;
2536 my $combine = $self->_combine($opts{combine}, 'normal');
2539 unless ($opts{mask}{IMG}) {
2540 $self->_set_error("compose: mask parameter empty image");
2544 my $mask_left = $opts{mask_left};
2545 defined $mask_left or $mask_left = $opts{mask_minx};
2546 defined $mask_left or $mask_left = 0;
2548 my $mask_top = $opts{mask_top};
2549 defined $mask_top or $mask_top = $opts{mask_miny};
2550 defined $mask_top or $mask_top = 0;
2552 i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2553 $left, $top, $src_left, $src_top,
2554 $mask_left, $mask_top, $width, $height,
2555 $combine, $opts{opacity})
2559 i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2560 $width, $height, $combine, $opts{opacity})
2570 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2572 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2573 $dir = $xlate{$opts{'dir'}};
2574 return $self if i_flipxy($self->{IMG}, $dir);
2582 unless (defined wantarray) {
2583 my @caller = caller;
2584 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2588 if (defined $opts{right}) {
2589 my $degrees = $opts{right};
2591 $degrees += 360 * int(((-$degrees)+360)/360);
2593 $degrees = $degrees % 360;
2594 if ($degrees == 0) {
2595 return $self->copy();
2597 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2598 my $result = Imager->new();
2599 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2603 $self->{ERRSTR} = $self->_error_as_msg();
2608 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2612 elsif (defined $opts{radians} || defined $opts{degrees}) {
2613 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2615 my $back = $opts{back};
2616 my $result = Imager->new;
2618 $back = _color($back);
2620 $self->_set_error(Imager->errstr);
2624 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2627 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2629 if ($result->{IMG}) {
2633 $self->{ERRSTR} = $self->_error_as_msg();
2638 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2643 sub matrix_transform {
2647 unless (defined wantarray) {
2648 my @caller = caller;
2649 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2653 if ($opts{matrix}) {
2654 my $xsize = $opts{xsize} || $self->getwidth;
2655 my $ysize = $opts{ysize} || $self->getheight;
2657 my $result = Imager->new;
2659 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2660 $opts{matrix}, $opts{back})
2664 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2672 $self->{ERRSTR} = "matrix parameter required";
2678 *yatf = \&matrix_transform;
2680 # These two are supported for legacy code only
2683 return Imager::Color->new(@_);
2687 return Imager::Color::set(@_);
2690 # Draws a box between the specified corner points.
2693 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2694 my $dflcl=i_color_new(255,255,255,255);
2695 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2697 if (exists $opts{'box'}) {
2698 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2699 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2700 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2701 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2704 if ($opts{filled}) {
2705 my $color = _color($opts{'color'});
2707 $self->{ERRSTR} = $Imager::ERRSTR;
2710 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2711 $opts{ymax}, $color);
2713 elsif ($opts{fill}) {
2714 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2715 # assume it's a hash ref
2716 require 'Imager/Fill.pm';
2717 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2718 $self->{ERRSTR} = $Imager::ERRSTR;
2722 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2723 $opts{ymax},$opts{fill}{fill});
2726 my $color = _color($opts{'color'});
2728 $self->{ERRSTR} = $Imager::ERRSTR;
2731 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2739 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2740 my $dflcl=i_color_new(255,255,255,255);
2741 my %opts=(color=>$dflcl,
2742 'r'=>_min($self->getwidth(),$self->getheight())/3,
2743 'x'=>$self->getwidth()/2,
2744 'y'=>$self->getheight()/2,
2745 'd1'=>0, 'd2'=>361, @_);
2748 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2749 # assume it's a hash ref
2750 require 'Imager/Fill.pm';
2751 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2752 $self->{ERRSTR} = $Imager::ERRSTR;
2756 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2757 $opts{'d2'}, $opts{fill}{fill});
2760 my $color = _color($opts{'color'});
2762 $self->{ERRSTR} = $Imager::ERRSTR;
2765 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2766 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2770 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2771 $opts{'d1'}, $opts{'d2'}, $color);
2777 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2778 # assume it's a hash ref
2779 require 'Imager/Fill.pm';
2780 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2781 $self->{ERRSTR} = $Imager::ERRSTR;
2785 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2786 $opts{'d2'}, $opts{fill}{fill});
2789 my $color = _color($opts{'color'});
2791 $self->{ERRSTR} = $Imager::ERRSTR;
2794 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2795 $opts{'d1'}, $opts{'d2'}, $color);
2802 # Draws a line from one point to the other
2803 # the endpoint is set if the endp parameter is set which it is by default.
2804 # to turn of the endpoint being set use endp=>0 when calling line.
2808 my $dflcl=i_color_new(0,0,0,0);
2809 my %opts=(color=>$dflcl,
2812 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2814 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2815 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2817 my $color = _color($opts{'color'});
2819 $self->{ERRSTR} = $Imager::ERRSTR;
2823 $opts{antialias} = $opts{aa} if defined $opts{aa};
2824 if ($opts{antialias}) {
2825 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2826 $color, $opts{endp});
2828 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2829 $color, $opts{endp});
2834 # Draws a line between an ordered set of points - It more or less just transforms this
2835 # into a list of lines.
2839 my ($pt,$ls,@points);
2840 my $dflcl=i_color_new(0,0,0,0);
2841 my %opts=(color=>$dflcl,@_);
2843 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2845 if (exists($opts{points})) { @points=@{$opts{points}}; }
2846 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2847 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2850 # print Dumper(\@points);
2852 my $color = _color($opts{'color'});
2854 $self->{ERRSTR} = $Imager::ERRSTR;
2857 $opts{antialias} = $opts{aa} if defined $opts{aa};
2858 if ($opts{antialias}) {
2861 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2868 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2878 my ($pt,$ls,@points);
2879 my $dflcl = i_color_new(0,0,0,0);
2880 my %opts = (color=>$dflcl, @_);
2882 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2884 if (exists($opts{points})) {
2885 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2886 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2889 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2890 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2893 if ($opts{'fill'}) {
2894 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2895 # assume it's a hash ref
2896 require 'Imager/Fill.pm';
2897 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2898 $self->{ERRSTR} = $Imager::ERRSTR;
2902 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2903 $opts{'fill'}{'fill'});
2906 my $color = _color($opts{'color'});
2908 $self->{ERRSTR} = $Imager::ERRSTR;
2911 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2918 # this the multipoint bezier curve
2919 # this is here more for testing that actual usage since
2920 # this is not a good algorithm. Usually the curve would be
2921 # broken into smaller segments and each done individually.
2925 my ($pt,$ls,@points);
2926 my $dflcl=i_color_new(0,0,0,0);
2927 my %opts=(color=>$dflcl,@_);
2929 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2931 if (exists $opts{points}) {
2932 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2933 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2936 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2937 $self->{ERRSTR}='Missing or invalid points.';
2941 my $color = _color($opts{'color'});
2943 $self->{ERRSTR} = $Imager::ERRSTR;
2946 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2952 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2955 unless (exists $opts{'x'} && exists $opts{'y'}) {
2956 $self->{ERRSTR} = "missing seed x and y parameters";
2960 if ($opts{border}) {
2961 my $border = _color($opts{border});
2963 $self->_set_error($Imager::ERRSTR);
2967 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2968 # assume it's a hash ref
2969 require Imager::Fill;
2970 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2971 $self->{ERRSTR} = $Imager::ERRSTR;
2975 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2976 $opts{fill}{fill}, $border);
2979 my $color = _color($opts{'color'});
2981 $self->{ERRSTR} = $Imager::ERRSTR;
2984 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2991 $self->{ERRSTR} = $self->_error_as_msg();
2997 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2998 # assume it's a hash ref
2999 require 'Imager/Fill.pm';
3000 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3001 $self->{ERRSTR} = $Imager::ERRSTR;
3005 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3008 my $color = _color($opts{'color'});
3010 $self->{ERRSTR} = $Imager::ERRSTR;
3013 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3019 $self->{ERRSTR} = $self->_error_as_msg();
3028 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
3030 unless (exists $opts{'x'} && exists $opts{'y'}) {
3031 $self->{ERRSTR} = 'missing x and y parameters';
3037 my $color = _color($opts{color})
3039 if (ref $x && ref $y) {
3040 unless (@$x == @$y) {
3041 $self->{ERRSTR} = 'length of x and y mismatch';
3045 if ($color->isa('Imager::Color')) {
3046 for my $i (0..$#{$opts{'x'}}) {
3047 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3052 for my $i (0..$#{$opts{'x'}}) {
3053 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3061 if ($color->isa('Imager::Color')) {
3062 i_ppix($self->{IMG}, $x, $y, $color)
3066 i_ppixf($self->{IMG}, $x, $y, $color)
3077 my %opts = ( "type"=>'8bit', @_);
3079 unless (exists $opts{'x'} && exists $opts{'y'}) {
3080 $self->{ERRSTR} = 'missing x and y parameters';
3086 if (ref $x && ref $y) {
3087 unless (@$x == @$y) {
3088 $self->{ERRSTR} = 'length of x and y mismatch';
3092 if ($opts{"type"} eq '8bit') {
3093 for my $i (0..$#{$opts{'x'}}) {
3094 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3098 for my $i (0..$#{$opts{'x'}}) {
3099 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3102 return wantarray ? @result : \@result;
3105 if ($opts{"type"} eq '8bit') {
3106 return i_get_pixel($self->{IMG}, $x, $y);
3109 return i_gpixf($self->{IMG}, $x, $y);
3118 my %opts = ( type => '8bit', x=>0, @_);
3120 $self->_valid_image or return;
3122 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3124 unless (defined $opts{'y'}) {
3125 $self->_set_error("missing y parameter");
3129 if ($opts{type} eq '8bit') {
3130 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3133 elsif ($opts{type} eq 'float') {
3134 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3137 elsif ($opts{type} eq 'index') {
3138 unless (i_img_type($self->{IMG})) {
3139 $self->_set_error("type => index only valid on paletted images");
3142 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3146 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3153 my %opts = ( x=>0, @_);
3155 $self->_valid_image or return;
3157 unless (defined $opts{'y'}) {
3158 $self->_set_error("missing y parameter");
3163 if (ref $opts{pixels} && @{$opts{pixels}}) {
3164 # try to guess the type
3165 if ($opts{pixels}[0]->isa('Imager::Color')) {
3166 $opts{type} = '8bit';
3168 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3169 $opts{type} = 'float';
3172 $self->_set_error("missing type parameter and could not guess from pixels");
3178 $opts{type} = '8bit';
3182 if ($opts{type} eq '8bit') {
3183 if (ref $opts{pixels}) {
3184 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3187 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3190 elsif ($opts{type} eq 'float') {
3191 if (ref $opts{pixels}) {
3192 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3195 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3198 elsif ($opts{type} eq 'index') {
3199 if (ref $opts{pixels}) {
3200 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3203 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3207 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3214 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3216 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3218 unless (defined $opts{'y'}) {
3219 $self->_set_error("missing y parameter");
3223 unless ($opts{channels}) {
3224 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3227 if ($opts{target}) {
3228 my $target = $opts{target};
3229 my $offset = $opts{offset};
3230 if ($opts{type} eq '8bit') {
3231 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3232 $opts{y}, @{$opts{channels}})
3234 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3235 return scalar(@samples);
3237 elsif ($opts{type} eq 'float') {
3238 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3239 $opts{y}, @{$opts{channels}});
3240 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3241 return scalar(@samples);
3243 elsif ($opts{type} =~ /^(\d+)bit$/) {
3247 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3248 $opts{y}, $bits, $target,
3249 $offset, @{$opts{channels}});
3250 unless (defined $count) {
3251 $self->_set_error(Imager->_error_as_msg);
3258 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3263 if ($opts{type} eq '8bit') {
3264 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3265 $opts{y}, @{$opts{channels}});
3267 elsif ($opts{type} eq 'float') {
3268 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3269 $opts{y}, @{$opts{channels}});
3271 elsif ($opts{type} =~ /^(\d+)bit$/) {
3275 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3276 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3281 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3289 my %opts = ( x => 0, offset => 0, @_ );
3291 unless ($self->{IMG}) {
3292 $self->_set_error('setsamples: empty input image');
3296 unless(defined $opts{data} && ref $opts{data}) {
3297 $self->_set_error('setsamples: data parameter missing or invalid');
3301 unless ($opts{channels}) {
3302 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3305 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3306 $self->_set_error('setsamples: type parameter missing or invalid');
3311 unless (defined $opts{width}) {
3312 $opts{width} = $self->getwidth() - $opts{x};
3315 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3316 $opts{channels}, $opts{data}, $opts{offset},
3318 unless (defined $count) {
3319 $self->_set_error(Imager->_error_as_msg);
3326 # make an identity matrix of the given size
3330 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3331 for my $c (0 .. ($size-1)) {
3332 $matrix->[$c][$c] = 1;
3337 # general function to convert an image
3339 my ($self, %opts) = @_;
3342 unless (defined wantarray) {
3343 my @caller = caller;
3344 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3348 # the user can either specify a matrix or preset
3349 # the matrix overrides the preset
3350 if (!exists($opts{matrix})) {
3351 unless (exists($opts{preset})) {
3352 $self->{ERRSTR} = "convert() needs a matrix or preset";
3356 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3357 # convert to greyscale, keeping the alpha channel if any
3358 if ($self->getchannels == 3) {
3359 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3361 elsif ($self->getchannels == 4) {
3362 # preserve the alpha channel
3363 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3368 $matrix = _identity($self->getchannels);
3371 elsif ($opts{preset} eq 'noalpha') {
3372 # strip the alpha channel
3373 if ($self->getchannels == 2 or $self->getchannels == 4) {
3374 $matrix = _identity($self->getchannels);
3375 pop(@$matrix); # lose the alpha entry
3378 $matrix = _identity($self->getchannels);
3381 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3383 $matrix = [ [ 1 ] ];
3385 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3386 $matrix = [ [ 0, 1 ] ];
3388 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3389 $matrix = [ [ 0, 0, 1 ] ];
3391 elsif ($opts{preset} eq 'alpha') {
3392 if ($self->getchannels == 2 or $self->getchannels == 4) {
3393 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3396 # the alpha is just 1 <shrug>
3397 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3400 elsif ($opts{preset} eq 'rgb') {
3401 if ($self->getchannels == 1) {
3402 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3404 elsif ($self->getchannels == 2) {
3405 # preserve the alpha channel
3406 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3409 $matrix = _identity($self->getchannels);
3412 elsif ($opts{preset} eq 'addalpha') {
3413 if ($self->getchannels == 1) {
3414 $matrix = _identity(2);
3416 elsif ($self->getchannels == 3) {
3417 $matrix = _identity(4);
3420 $matrix = _identity($self->getchannels);
3424 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3430 $matrix = $opts{matrix};
3433 my $new = Imager->new;
3434 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3435 unless ($new->{IMG}) {
3436 # most likely a bad matrix
3437 $self->{ERRSTR} = _error_as_msg();
3444 # general function to map an image through lookup tables
3447 my ($self, %opts) = @_;
3448 my @chlist = qw( red green blue alpha );
3450 if (!exists($opts{'maps'})) {
3451 # make maps from channel maps
3453 for $chnum (0..$#chlist) {
3454 if (exists $opts{$chlist[$chnum]}) {
3455 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3456 } elsif (exists $opts{'all'}) {
3457 $opts{'maps'}[$chnum] = $opts{'all'};
3461 if ($opts{'maps'} and $self->{IMG}) {
3462 i_map($self->{IMG}, $opts{'maps'} );
3468 my ($self, %opts) = @_;
3470 defined $opts{mindist} or $opts{mindist} = 0;
3472 defined $opts{other}
3473 or return $self->_set_error("No 'other' parameter supplied");
3474 defined $opts{other}{IMG}
3475 or return $self->_set_error("No image data in 'other' image");
3478 or return $self->_set_error("No image data");
3480 my $result = Imager->new;
3481 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3483 or return $self->_set_error($self->_error_as_msg());
3488 # destructive border - image is shrunk by one pixel all around
3491 my ($self,%opts)=@_;
3492 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3493 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3497 # Get the width of an image
3501 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3502 return (i_img_info($self->{IMG}))[0];
3505 # Get the height of an image
3509 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3510 return (i_img_info($self->{IMG}))[1];
3513 # Get number of channels in an image
3517 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3518 return i_img_getchannels($self->{IMG});
3525 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3526 return i_img_getmask($self->{IMG});
3534 if (!defined($self->{IMG})) {
3535 $self->{ERRSTR} = 'image is empty';
3538 unless (defined $opts{mask}) {
3539 $self->_set_error("mask parameter required");
3542 i_img_setmask( $self->{IMG} , $opts{mask} );
3547 # Get number of colors in an image
3551 my %opts=('maxcolors'=>2**30,@_);
3552 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3553 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3554 return ($rc==-1? undef : $rc);
3557 # Returns a reference to a hash. The keys are colour named (packed) and the
3558 # values are the number of pixels in this colour.
3559 sub getcolorusagehash {
3562 my %opts = ( maxcolors => 2**30, @_ );
3563 my $max_colors = $opts{maxcolors};
3564 unless (defined $max_colors && $max_colors > 0) {
3565 $self->_set_error('maxcolors must be a positive integer');
3569 unless (defined $self->{IMG}) {
3570 $self->_set_error('empty input image');
3574 my $channels= $self->getchannels;
3575 # We don't want to look at the alpha channel, because some gifs using it
3576 # doesn't define it for every colour (but only for some)
3577 $channels -= 1 if $channels == 2 or $channels == 4;
3579 my $height = $self->getheight;
3580 for my $y (0 .. $height - 1) {
3581 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3582 while (length $colors) {
3583 $color_use{ substr($colors, 0, $channels, '') }++;
3585 keys %color_use > $max_colors
3591 # This will return a ordered array of the colour usage. Kind of the sorted
3592 # version of the values of the hash returned by getcolorusagehash.
3593 # You might want to add safety checks and change the names, etc...
3597 my %opts = ( maxcolors => 2**30, @_ );
3598 my $max_colors = $opts{maxcolors};
3599 unless (defined $max_colors && $max_colors > 0) {
3600 $self->_set_error('maxcolors must be a positive integer');
3604 unless (defined $self->{IMG}) {
3605 $self->_set_error('empty input image');
3609 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3612 # draw string to an image
3616 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3618 my %input=('x'=>0, 'y'=>0, @_);
3619 defined($input{string}) or $input{string} = $input{text};
3621 unless(defined $input{string}) {
3622 $self->{ERRSTR}="missing required parameter 'string'";
3626 unless($input{font}) {
3627 $self->{ERRSTR}="missing required parameter 'font'";
3631 unless ($input{font}->draw(image=>$self, %input)) {
3643 unless ($self->{IMG}) {
3644 $self->{ERRSTR}='empty input image';
3653 my %input=('x'=>0, 'y'=>0, @_);
3654 $input{string}||=$input{text};
3656 unless(exists $input{string}) {
3657 $self->_set_error("missing required parameter 'string'");
3661 unless($input{font}) {
3662 $self->_set_error("missing required parameter 'font'");
3667 unless (@result = $input{font}->align(image=>$img, %input)) {
3671 return wantarray ? @result : $result[0];
3674 my @file_limit_names = qw/width height bytes/;
3676 sub set_file_limits {
3683 @values{@file_limit_names} = (0) x @file_limit_names;
3686 @values{@file_limit_names} = i_get_image_file_limits();
3689 for my $key (keys %values) {
3690 defined $opts{$key} and $values{$key} = $opts{$key};
3693 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3696 sub get_file_limits {
3697 i_get_image_file_limits();
3700 # Shortcuts that can be exported
3702 sub newcolor { Imager::Color->new(@_); }
3703 sub newfont { Imager::Font->new(@_); }
3704 sub NCF { Imager::Color::Float->new(@_) }
3706 *NC=*newcolour=*newcolor;
3713 #### Utility routines
3716 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3720 my ($self, $msg) = @_;
3723 $self->{ERRSTR} = $msg;
3731 # Default guess for the type of an image from extension
3733 sub def_guess_type {
3736 $ext=($name =~ m/\.([^\.]+)$/)[0];
3737 return 'tiff' if ($ext =~ m/^tiff?$/);
3738 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3739 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3740 return 'png' if ($ext eq "png");
3741 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3742 return 'tga' if ($ext eq "tga");
3743 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3744 return 'gif' if ($ext eq "gif");
3745 return 'raw' if ($ext eq "raw");
3746 return lc $ext; # best guess
3751 return @combine_types;
3754 # get the minimum of a list
3758 for(@_) { if ($_<$mx) { $mx=$_; }}
3762 # get the maximum of a list
3766 for(@_) { if ($_>$mx) { $mx=$_; }}
3770 # string stuff for iptc headers
3774 $str = substr($str,3);
3775 $str =~ s/[\n\r]//g;
3782 # A little hack to parse iptc headers.
3787 my($caption,$photogr,$headln,$credit);
3789 my $str=$self->{IPTCRAW};
3794 @ar=split(/8BIM/,$str);
3799 @sar=split(/\034\002/);
3800 foreach $item (@sar) {
3801 if ($item =~ m/^x/) {
3802 $caption = _clean($item);
3805 if ($item =~ m/^P/) {
3806 $photogr = _clean($item);
3809 if ($item =~ m/^i/) {
3810 $headln = _clean($item);
3813 if ($item =~ m/^n/) {
3814 $credit = _clean($item);
3820 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3827 or die "Only C language supported";
3829 require Imager::ExtUtils;
3830 return Imager::ExtUtils->inline_config;
3835 # Below is the stub of documentation for your module. You better edit it!
3839 Imager - Perl extension for Generating 24 bit Images
3849 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3854 my $img = Imager->new();
3855 # see Imager::Files for information on the read() method
3856 $img->read(file=>$file) or die $img->errstr();
3858 $file =~ s/\.[^.]*$//;
3860 # Create smaller version
3861 # documented in Imager::Transformations
3862 my $thumb = $img->scale(scalefactor=>.3);
3864 # Autostretch individual channels
3865 $thumb->filter(type=>'autolevels');
3867 # try to save in one of these formats
3870 for $format ( qw( png gif jpg tiff ppm ) ) {
3871 # Check if given format is supported
3872 if ($Imager::formats{$format}) {
3873 $file.="_low.$format";
3874 print "Storing image as: $file\n";
3875 # documented in Imager::Files
3876 $thumb->write(file=>$file) or
3884 Imager is a module for creating and altering images. It can read and
3885 write various image formats, draw primitive shapes like lines,and
3886 polygons, blend multiple images together in various ways, scale, crop,
3887 render text and more.
3889 =head2 Overview of documentation
3895 Imager - This document - Synopsis, Example, Table of Contents and
3900 L<Imager::Tutorial> - a brief introduction to Imager.
3904 L<Imager::Cookbook> - how to do various things with Imager.
3908 L<Imager::ImageTypes> - Basics of constructing image objects with
3909 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3910 8/16/double bits/channel, color maps, channel masks, image tags, color
3911 quantization. Also discusses basic image information methods.
3915 L<Imager::Files> - IO interaction, reading/writing images, format
3920 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3925 L<Imager::Color> - Color specification.
3929 L<Imager::Fill> - Fill pattern specification.
3933 L<Imager::Font> - General font rendering, bounding boxes and font
3938 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3939 blending, pasting, convert and map.
3943 L<Imager::Engines> - Programmable transformations through
3944 C<transform()>, C<transform2()> and C<matrix_transform()>.
3948 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3953 L<Imager::Expr> - Expressions for evaluation engine used by
3958 L<Imager::Matrix2d> - Helper class for affine transformations.
3962 L<Imager::Fountain> - Helper for making gradient profiles.
3966 L<Imager::API> - using Imager's C API
3970 L<Imager::APIRef> - API function reference
3974 L<Imager::Inline> - using Imager's C API from Inline::C
3978 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3982 =head2 Basic Overview
3984 An Image object is created with C<$img = Imager-E<gt>new()>.
3987 $img=Imager->new(); # create empty image
3988 $img->read(file=>'lena.png',type=>'png') or # read image from file
3989 die $img->errstr(); # give an explanation
3990 # if something failed
3992 or if you want to create an empty image:
3994 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3996 This example creates a completely black image of width 400 and height
3999 =head1 ERROR HANDLING
4001 In general a method will return false when it fails, if it does use
4002 the errstr() method to find out why:
4008 Returns the last error message in that context.
4010 If the last error you received was from calling an object method, such
4011 as read, call errstr() as an object method to find out why:
4013 my $image = Imager->new;
4014 $image->read(file => 'somefile.gif')
4015 or die $image->errstr;
4017 If it was a class method then call errstr() as a class method:
4019 my @imgs = Imager->read_multi(file => 'somefile.gif')
4020 or die Imager->errstr;
4022 Note that in some cases object methods are implemented in terms of
4023 class methods so a failing object method may set both.
4027 The C<Imager-E<gt>new> method is described in detail in
4028 L<Imager::ImageTypes>.
4032 Where to find information on methods for Imager class objects.
4034 addcolors() - L<Imager::ImageTypes/addcolors>
4036 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4038 align_string() - L<Imager::Draw/align_string>
4040 arc() - L<Imager::Draw/arc>
4042 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4045 box() - L<Imager::Draw/box>
4047 circle() - L<Imager::Draw/circle>
4049 colorcount() - L<Imager::Draw/colorcount>
4051 combines() - L<Imager::Draw/combines>
4053 compose() - L<Imager::Transformations/compose>
4055 convert() - L<Imager::Transformations/"Color transformations"> -
4056 transform the color space
4058 copy() - L<Imager::Transformations/copy>
4060 crop() - L<Imager::Transformations/crop> - extract part of an image
4062 def_guess_type() - L<Imager::Files/def_guess_type>
4064 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4066 difference() - L<Imager::Filters/"Image Difference">
4068 errstr() - L<"Basic Overview">
4070 filter() - L<Imager::Filters>
4072 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
4075 flip() - L<Imager::Transformations/flip>
4077 flood_fill() - L<Imager::Draw/flood_fill>
4079 getchannels() - L<Imager::ImageTypes/getchannels>
4081 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
4083 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4084 palette, if it has one
4086 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4088 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4090 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4092 getheight() - L<Imager::ImageTypes/getwidth>
4094 getmask() - L<Imager::ImageTypes/getmask>
4096 getpixel() - L<Imager::Draw/getpixel>
4098 getsamples() - L<Imager::Draw/getsamples>
4100 getscanline() - L<Imager::Draw/getscanline>
4102 getwidth() - L<Imager::ImageTypes/getwidth>
4104 img_set() - L<Imager::ImageTypes/img_set>
4106 init() - L<Imager::ImageTypes/init>
4108 is_bilevel() - L<Imager::ImageTypes/is_bilevel>
4110 line() - L<Imager::Draw/line>
4112 load_plugin() - L<Imager::Filters/load_plugin>
4114 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4117 masked() - L<Imager::ImageTypes/masked> - make a masked image
4119 matrix_transform() - L<Imager::Engines/matrix_transform>
4121 maxcolors() - L<Imager::ImageTypes/maxcolors>
4123 NC() - L<Imager::Handy/NC>
4125 NCF() - L<Imager::Handy/NCF>
4127 new() - L<Imager::ImageTypes/new>
4129 newcolor() - L<Imager::Handy/newcolor>
4131 newcolour() - L<Imager::Handy/newcolour>
4133 newfont() - L<Imager::Handy/newfont>
4135 NF() - L<Imager::Handy/NF>
4137 open() - L<Imager::Files> - an alias for read()
4139 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4142 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4144 polygon() - L<Imager::Draw/polygon>
4146 polyline() - L<Imager::Draw/polyline>
4148 read() - L<Imager::Files> - read a single image from an image file
4150 read_multi() - L<Imager::Files> - read multiple images from an image
4153 read_types() - L<Imager::Files/read_types> - list image types Imager
4156 register_filter() - L<Imager::Filters/register_filter>
4158 register_reader() - L<Imager::Filters/register_reader>
4160 register_writer() - L<Imager::Filters/register_writer>
4162 rotate() - L<Imager::Transformations/rotate>
4164 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4165 image and use the alpha channel
4167 scale() - L<Imager::Transformations/scale>
4169 scale_calculate() - L<Imager::Transformations/scale_calculate>
4171 scaleX() - L<Imager::Transformations/scaleX>
4173 scaleY() - L<Imager::Transformations/scaleY>
4175 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4178 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4180 setmask() - L<Imager::ImageTypes/setmask>
4182 setpixel() - L<Imager::Draw/setpixel>
4184 setsamples() - L<Imager::Draw/setsamples>
4186 setscanline() - L<Imager::Draw/setscanline>
4188 settag() - L<Imager::ImageTypes/settag>
4190 string() - L<Imager::Draw/string> - draw text on an image
4192 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4194 to_paletted() - L<Imager::ImageTypes/to_paletted>
4196 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4198 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4200 transform() - L<Imager::Engines/"transform">
4202 transform2() - L<Imager::Engines/"transform2">
4204 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4206 unload_plugin() - L<Imager::Filters/unload_plugin>
4208 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4211 write() - L<Imager::Files> - write an image to a file
4213 write_multi() - L<Imager::Files> - write multiple image to an image
4216 write_types() - L<Imager::Files/read_types> - list image types Imager
4219 =head1 CONCEPT INDEX
4221 animated GIF - L<Imager::Files/"Writing an animated GIF">
4223 aspect ratio - L<Imager::ImageTypes/i_xres>,
4224 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4226 blend - alpha blending one image onto another
4227 L<Imager::Transformations/rubthrough>
4229 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4231 boxes, drawing - L<Imager::Draw/box>
4233 changes between image - L<Imager::Filter/"Image Difference">
4235 color - L<Imager::Color>
4237 color names - L<Imager::Color>, L<Imager::Color::Table>
4239 combine modes - L<Imager::Fill/combine>
4241 compare images - L<Imager::Filter/"Image Difference">
4243 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
4245 convolution - L<Imager::Filter/conv>
4247 cropping - L<Imager::Transformations/crop>
4249 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4251 C<diff> images - L<Imager::Filter/"Image Difference">
4253 dpi - L<Imager::ImageTypes/i_xres>,
4254 L<Imager::Cookbook/"Image spatial resolution">
4256 drawing boxes - L<Imager::Draw/box>
4258 drawing lines - L<Imager::Draw/line>
4260 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4262 error message - L<"Basic Overview">
4264 files, font - L<Imager::Font>
4266 files, image - L<Imager::Files>
4268 filling, types of fill - L<Imager::Fill>
4270 filling, boxes - L<Imager::Draw/box>
4272 filling, flood fill - L<Imager::Draw/flood_fill>
4274 flood fill - L<Imager::Draw/flood_fill>
4276 fonts - L<Imager::Font>
4278 fonts, drawing with - L<Imager::Draw/string>,
4279 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4281 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4283 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4285 fountain fill - L<Imager::Fill/"Fountain fills">,
4286 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4287 L<Imager::Filters/gradgen>
4289 GIF files - L<Imager::Files/"GIF">
4291 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4293 gradient fill - L<Imager::Fill/"Fountain fills">,
4294 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4295 L<Imager::Filters/gradgen>
4297 grayscale, convert image to - L<Imager::Transformations/convert>
4299 guassian blur - L<Imager::Filter/guassian>
4301 hatch fills - L<Imager::Fill/"Hatched fills">
4303 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4305 invert image - L<Imager::Filter/hardinvert>
4307 JPEG - L<Imager::Files/"JPEG">
4309 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4311 lines, drawing - L<Imager::Draw/line>
4313 matrix - L<Imager::Matrix2d>,
4314 L<Imager::Transformations/"Matrix Transformations">,
4315 L<Imager::Font/transform>
4317 metadata, image - L<Imager::ImageTypes/"Tags">
4319 mosaic - L<Imager::Filter/mosaic>
4321 noise, filter - L<Imager::Filter/noise>
4323 noise, rendered - L<Imager::Filter/turbnoise>,
4324 L<Imager::Filter/radnoise>
4326 paste - L<Imager::Transformations/paste>,
4327 L<Imager::Transformations/rubthrough>
4329 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4330 L<Imager::ImageTypes/new>
4332 posterize - L<Imager::Filter/postlevels>
4334 png files - L<Imager::Files>, L<Imager::Files/"PNG">
4336 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
4338 rectangles, drawing - L<Imager::Draw/box>
4340 resizing an image - L<Imager::Transformations/scale>,
4341 L<Imager::Transformations/crop>
4343 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4345 saving an image - L<Imager::Files>
4347 scaling - L<Imager::Transformations/scale>
4349 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4351 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4353 size, image - L<Imager::ImageTypes/getwidth>,
4354 L<Imager::ImageTypes/getheight>
4356 size, text - L<Imager::Font/bounding_box>
4358 tags, image metadata - L<Imager::ImageTypes/"Tags">
4360 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4361 L<Imager::Font::Wrap>
4363 text, wrapping text in an area - L<Imager::Font::Wrap>
4365 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4367 tiles, color - L<Imager::Filter/mosaic>
4369 unsharp mask - L<Imager::Filter/unsharpmask>
4371 watermark - L<Imager::Filter/watermark>
4373 writing an image to a file - L<Imager::Files>
4377 The best place to get help with Imager is the mailing list.
4379 To subscribe send a message with C<subscribe> in the body to:
4381 imager-devel+request@molar.is
4387 L<http://www.molar.is/en/lists/imager-devel/>
4391 where you can also find the mailing list archive.
4393 You can report bugs by pointing your browser at:
4397 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4401 or by sending an email to:
4405 bug-Imager@rt.cpan.org
4409 Please remember to include the versions of Imager, perl, supporting
4410 libraries, and any relevant code. If you have specific images that
4411 cause the problems, please include those too.
4413 If you don't want to publish your email address on a mailing list you
4414 can use CPAN::Forum:
4416 http://www.cpanforum.com/dist/Imager
4418 You will need to register to post.
4420 =head1 CONTRIBUTING TO IMAGER
4426 If you like or dislike Imager, you can add a public review of Imager
4429 http://cpanratings.perl.org/dist/Imager
4431 This requires a Bitcard Account (http://www.bitcard.org).
4433 You can also send email to the maintainer below.
4435 If you send me a bug report via email, it will be copied to RT.
4439 I accept patches, preferably against the main branch in subversion.
4440 You should include an explanation of the reason for why the patch is
4443 Your patch should include regression tests where possible, otherwise
4444 it will be delayed until I get a chance to write them.
4448 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4450 Arnar M. Hrafnkelsson is the original author of Imager.
4452 Many others have contributed to Imager, please see the README for a
4457 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4458 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4459 L<Imager::Font>(3), L<Imager::Transformations>(3),
4460 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4461 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4463 L<http://imager.perl.org/>
4465 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4467 Other perl imaging modules include:
4469 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).