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',
1597 my ($self, $opts, $prefix, @imgs) = @_;
1599 for my $opt (keys %$opts) {
1601 if ($obsolete_opts{$opt}) {
1602 my $new = $obsolete_opts{$opt};
1603 my $msg = "Obsolete option $opt ";
1605 $new->($opts, $opt, \$msg, @imgs);
1608 $msg .= "replaced with the $new tag ";
1611 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1612 warn $msg if $warn_obsolete && $^W;
1614 next unless $tagname =~ /^\Q$prefix/;
1615 my $value = $opts->{$opt};
1617 if (UNIVERSAL::isa($value, "Imager::Color")) {
1618 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1619 for my $img (@imgs) {
1620 $img->settag(name=>$tagname, value=>$tag);
1623 elsif (ref($value) eq 'ARRAY') {
1624 for my $i (0..$#$value) {
1625 my $val = $value->[$i];
1627 if (UNIVERSAL::isa($val, "Imager::Color")) {
1628 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1630 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1633 $self->_set_error("Unknown reference type " . ref($value) .
1634 " supplied in array for $opt");
1640 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1645 $self->_set_error("Unknown reference type " . ref($value) .
1646 " supplied for $opt");
1651 # set it as a tag for every image
1652 for my $img (@imgs) {
1653 $img->settag(name=>$tagname, value=>$value);
1661 # Write an image to file
1664 my %input=(jpegquality=>75,
1674 $self->_set_opts(\%input, "i_", $self)
1677 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1679 if (!$input{'type'} and $input{file}) {
1680 $input{'type'}=$FORMATGUESS->($input{file});
1682 if (!$input{'type'}) {
1683 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1687 _writer_autoload($input{type});
1690 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1691 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1694 $writers{$input{type}}{single}->($self, $IO, %input)
1698 if (!$formats{$input{'type'}}) {
1699 my $write_types = join ', ', sort Imager->write_types();
1700 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1704 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1707 if ($input{'type'} eq 'tiff') {
1708 $self->_set_opts(\%input, "tiff_", $self)
1710 $self->_set_opts(\%input, "exif_", $self)
1713 if (defined $input{class} && $input{class} eq 'fax') {
1714 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1715 $self->{ERRSTR} = $self->_error_as_msg();
1719 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1720 $self->{ERRSTR} = $self->_error_as_msg();
1724 } elsif ( $input{'type'} eq 'pnm' ) {
1725 $self->_set_opts(\%input, "pnm_", $self)
1727 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1728 $self->{ERRSTR} = $self->_error_as_msg();
1731 $self->{DEBUG} && print "writing a pnm file\n";
1732 } elsif ( $input{'type'} eq 'raw' ) {
1733 $self->_set_opts(\%input, "raw_", $self)
1735 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1736 $self->{ERRSTR} = $self->_error_as_msg();
1739 $self->{DEBUG} && print "writing a raw file\n";
1740 } elsif ( $input{'type'} eq 'png' ) {
1741 $self->_set_opts(\%input, "png_", $self)
1743 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1744 $self->{ERRSTR}='unable to write png image';
1747 $self->{DEBUG} && print "writing a png file\n";
1748 } elsif ( $input{'type'} eq 'jpeg' ) {
1749 $self->_set_opts(\%input, "jpeg_", $self)
1751 $self->_set_opts(\%input, "exif_", $self)
1753 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1754 $self->{ERRSTR} = $self->_error_as_msg();
1757 $self->{DEBUG} && print "writing a jpeg file\n";
1758 } elsif ( $input{'type'} eq 'bmp' ) {
1759 $self->_set_opts(\%input, "bmp_", $self)
1761 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1762 $self->{ERRSTR} = $self->_error_as_msg;
1765 $self->{DEBUG} && print "writing a bmp file\n";
1766 } elsif ( $input{'type'} eq 'tga' ) {
1767 $self->_set_opts(\%input, "tga_", $self)
1770 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1771 $self->{ERRSTR}=$self->_error_as_msg();
1774 $self->{DEBUG} && print "writing a tga file\n";
1775 } elsif ( $input{'type'} eq 'gif' ) {
1776 $self->_set_opts(\%input, "gif_", $self)
1778 # compatibility with the old interfaces
1779 if ($input{gifquant} eq 'lm') {
1780 $input{make_colors} = 'addi';
1781 $input{translate} = 'perturb';
1782 $input{perturb} = $input{lmdither};
1783 } elsif ($input{gifquant} eq 'gen') {
1784 # just pass options through
1786 $input{make_colors} = 'webmap'; # ignored
1787 $input{translate} = 'giflib';
1789 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1790 $self->{ERRSTR} = $self->_error_as_msg;
1796 if (exists $input{'data'}) {
1797 my $data = io_slurp($IO);
1799 $self->{ERRSTR}='Could not slurp from buffer';
1802 ${$input{data}} = $data;
1808 my ($class, $opts, @images) = @_;
1810 my $type = $opts->{type};
1812 if (!$type && $opts->{'file'}) {
1813 $type = $FORMATGUESS->($opts->{'file'});
1816 $class->_set_error('type parameter missing and not possible to guess from extension');
1819 # translate to ImgRaw
1820 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1821 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1824 $class->_set_opts($opts, "i_", @images)
1826 my @work = map $_->{IMG}, @images;
1828 _writer_autoload($type);
1831 if ($writers{$type} && $writers{$type}{multiple}) {
1832 ($IO, $file) = $class->_get_writer_io($opts, $type)
1835 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1839 if (!$formats{$type}) {
1840 my $write_types = join ', ', sort Imager->write_types();
1841 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1845 ($IO, $file) = $class->_get_writer_io($opts, $type)
1848 if ($type eq 'gif') {
1849 $class->_set_opts($opts, "gif_", @images)
1851 my $gif_delays = $opts->{gif_delays};
1852 local $opts->{gif_delays} = $gif_delays;
1853 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1854 # assume the caller wants the same delay for each frame
1855 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1857 unless (i_writegif_wiol($IO, $opts, @work)) {
1858 $class->_set_error($class->_error_as_msg());
1862 elsif ($type eq 'tiff') {
1863 $class->_set_opts($opts, "tiff_", @images)
1865 $class->_set_opts($opts, "exif_", @images)
1868 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1869 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1870 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1873 $res = i_writetiff_multi_wiol($IO, @work);
1876 $class->_set_error($class->_error_as_msg());
1882 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1887 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1893 if (exists $opts->{'data'}) {
1894 my $data = io_slurp($IO);
1896 Imager->_set_error('Could not slurp from buffer');
1899 ${$opts->{data}} = $data;
1904 # read multiple images from a file
1906 my ($class, %opts) = @_;
1908 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1911 my $type = $opts{'type'};
1913 $type = i_test_format_probe($IO, -1);
1916 if ($opts{file} && !$type) {
1918 $type = $FORMATGUESS->($opts{file});
1922 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1926 _reader_autoload($type);
1928 if ($readers{$type} && $readers{$type}{multiple}) {
1929 return $readers{$type}{multiple}->($IO, %opts);
1932 if ($type eq 'gif') {
1934 @imgs = i_readgif_multi_wiol($IO);
1937 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1941 $ERRSTR = _error_as_msg();
1945 elsif ($type eq 'tiff') {
1946 my @imgs = i_readtiff_multi_wiol($IO, -1);
1949 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1953 $ERRSTR = _error_as_msg();
1958 my $img = Imager->new;
1959 if ($img->read(%opts, io => $IO, type => $type)) {
1962 Imager->_set_error($img->errstr);
1968 # Destroy an Imager object
1972 # delete $instances{$self};
1973 if (defined($self->{IMG})) {
1974 # the following is now handled by the XS DESTROY method for
1975 # Imager::ImgRaw object
1976 # Re-enabling this will break virtual images
1977 # tested for in t/t020masked.t
1978 # i_img_destroy($self->{IMG});
1979 undef($self->{IMG});
1981 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1985 # Perform an inplace filter of an image
1986 # that is the image will be overwritten with the data
1992 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1994 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1996 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1997 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2000 if ($filters{$input{'type'}}{names}) {
2001 my $names = $filters{$input{'type'}}{names};
2002 for my $name (keys %$names) {
2003 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2004 $input{$name} = $names->{$name}{$input{$name}};
2008 if (defined($filters{$input{'type'}}{defaults})) {
2009 %hsh=( image => $self->{IMG},
2011 %{$filters{$input{'type'}}{defaults}},
2014 %hsh=( image => $self->{IMG},
2019 my @cs=@{$filters{$input{'type'}}{callseq}};
2022 if (!defined($hsh{$_})) {
2023 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2028 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2029 &{$filters{$input{'type'}}{callsub}}(%hsh);
2032 chomp($self->{ERRSTR} = $@);
2038 $self->{DEBUG} && print "callseq is: @cs\n";
2039 $self->{DEBUG} && print "matching callseq is: @b\n";
2044 sub register_filter {
2046 my %hsh = ( defaults => {}, @_ );
2049 or die "register_filter() with no type\n";
2050 defined $hsh{callsub}
2051 or die "register_filter() with no callsub\n";
2052 defined $hsh{callseq}
2053 or die "register_filter() with no callseq\n";
2055 exists $filters{$hsh{type}}
2058 $filters{$hsh{type}} = \%hsh;
2063 sub scale_calculate {
2066 my %opts = ('type'=>'max', @_);
2068 my ($x_scale, $y_scale);
2069 my $width = $opts{width};
2070 my $height = $opts{height};
2072 defined $width or $width = $self->getwidth;
2073 defined $height or $height = $self->getheight;
2076 unless (defined $width && defined $height) {
2077 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2082 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2083 $x_scale = $opts{'xscalefactor'};
2084 $y_scale = $opts{'yscalefactor'};
2086 elsif ($opts{'xscalefactor'}) {
2087 $x_scale = $opts{'xscalefactor'};
2088 $y_scale = $opts{'scalefactor'} || $x_scale;
2090 elsif ($opts{'yscalefactor'}) {
2091 $y_scale = $opts{'yscalefactor'};
2092 $x_scale = $opts{'scalefactor'} || $y_scale;
2095 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2098 # work out the scaling
2099 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2100 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2101 $opts{ypixels} / $height );
2102 if ($opts{'type'} eq 'min') {
2103 $x_scale = $y_scale = _min($xpix,$ypix);
2105 elsif ($opts{'type'} eq 'max') {
2106 $x_scale = $y_scale = _max($xpix,$ypix);
2108 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2113 $self->_set_error('invalid value for type parameter');
2116 } elsif ($opts{xpixels}) {
2117 $x_scale = $y_scale = $opts{xpixels} / $width;
2119 elsif ($opts{ypixels}) {
2120 $x_scale = $y_scale = $opts{ypixels}/$height;
2122 elsif ($opts{constrain} && ref $opts{constrain}
2123 && $opts{constrain}->can('constrain')) {
2124 # we've been passed an Image::Math::Constrain object or something
2125 # that looks like one
2127 (undef, undef, $scalefactor)
2128 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2129 unless ($scalefactor) {
2130 $self->_set_error('constrain method failed on constrain parameter');
2133 $x_scale = $y_scale = $scalefactor;
2136 my $new_width = int($x_scale * $width + 0.5);
2137 $new_width > 0 or $new_width = 1;
2138 my $new_height = int($y_scale * $height + 0.5);
2139 $new_height > 0 or $new_height = 1;
2141 return ($x_scale, $y_scale, $new_width, $new_height);
2145 # Scale an image to requested size and return the scaled version
2149 my %opts = (qtype=>'normal' ,@_);
2150 my $img = Imager->new();
2151 my $tmp = Imager->new();
2153 unless (defined wantarray) {
2154 my @caller = caller;
2155 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2159 unless ($self->{IMG}) {
2160 $self->_set_error('empty input image');
2164 my ($x_scale, $y_scale, $new_width, $new_height) =
2165 $self->scale_calculate(%opts)
2168 if ($opts{qtype} eq 'normal') {
2169 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2170 if ( !defined($tmp->{IMG}) ) {
2171 $self->{ERRSTR} = 'unable to scale image';
2174 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2175 if ( !defined($img->{IMG}) ) {
2176 $self->{ERRSTR}='unable to scale image';
2182 elsif ($opts{'qtype'} eq 'preview') {
2183 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2184 if ( !defined($img->{IMG}) ) {
2185 $self->{ERRSTR}='unable to scale image';
2190 elsif ($opts{'qtype'} eq 'mixing') {
2191 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2192 unless ($img->{IMG}) {
2193 $self->_set_error(Imager->_error_as_meg);
2199 $self->_set_error('invalid value for qtype parameter');
2204 # Scales only along the X axis
2208 my %opts = ( scalefactor=>0.5, @_ );
2210 unless (defined wantarray) {
2211 my @caller = caller;
2212 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2216 unless ($self->{IMG}) {
2217 $self->{ERRSTR} = 'empty input image';
2221 my $img = Imager->new();
2223 my $scalefactor = $opts{scalefactor};
2225 if ($opts{pixels}) {
2226 $scalefactor = $opts{pixels} / $self->getwidth();
2229 unless ($self->{IMG}) {
2230 $self->{ERRSTR}='empty input image';
2234 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2236 if ( !defined($img->{IMG}) ) {
2237 $self->{ERRSTR} = 'unable to scale image';
2244 # Scales only along the Y axis
2248 my %opts = ( scalefactor => 0.5, @_ );
2250 unless (defined wantarray) {
2251 my @caller = caller;
2252 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2256 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2258 my $img = Imager->new();
2260 my $scalefactor = $opts{scalefactor};
2262 if ($opts{pixels}) {
2263 $scalefactor = $opts{pixels} / $self->getheight();
2266 unless ($self->{IMG}) {
2267 $self->{ERRSTR} = 'empty input image';
2270 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2272 if ( !defined($img->{IMG}) ) {
2273 $self->{ERRSTR} = 'unable to scale image';
2280 # Transform returns a spatial transformation of the input image
2281 # this moves pixels to a new location in the returned image.
2282 # NOTE - should make a utility function to check transforms for
2287 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2289 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2291 # print Dumper(\%opts);
2294 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2296 eval ("use Affix::Infix2Postfix;");
2299 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2302 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2303 {op=>'-',trans=>'Sub'},
2304 {op=>'*',trans=>'Mult'},
2305 {op=>'/',trans=>'Div'},
2306 {op=>'-','type'=>'unary',trans=>'u-'},
2308 {op=>'func','type'=>'unary'}],
2309 'grouping'=>[qw( \( \) )],
2310 'func'=>[qw( sin cos )],
2315 @xt=$I2P->translate($opts{'xexpr'});
2316 @yt=$I2P->translate($opts{'yexpr'});
2318 $numre=$I2P->{'numre'};
2321 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2322 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2323 @{$opts{'parm'}}=@pt;
2326 # print Dumper(\%opts);
2328 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2329 $self->{ERRSTR}='transform: no xopcodes given.';
2333 @op=@{$opts{'xopcodes'}};
2335 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2336 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2339 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2345 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2346 $self->{ERRSTR}='transform: no yopcodes given.';
2350 @op=@{$opts{'yopcodes'}};
2352 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2353 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2356 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2361 if ( !exists $opts{'parm'}) {
2362 $self->{ERRSTR}='transform: no parameter arg given.';
2366 # print Dumper(\@ropx);
2367 # print Dumper(\@ropy);
2368 # print Dumper(\@ropy);
2370 my $img = Imager->new();
2371 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2372 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2378 my ($opts, @imgs) = @_;
2380 require "Imager/Expr.pm";
2382 $opts->{variables} = [ qw(x y) ];
2383 my ($width, $height) = @{$opts}{qw(width height)};
2385 $width ||= $imgs[0]->getwidth();
2386 $height ||= $imgs[0]->getheight();
2388 for my $img (@imgs) {
2389 $opts->{constants}{"w$img_num"} = $img->getwidth();
2390 $opts->{constants}{"h$img_num"} = $img->getheight();
2391 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2392 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2397 $opts->{constants}{w} = $width;
2398 $opts->{constants}{cx} = $width/2;
2401 $Imager::ERRSTR = "No width supplied";
2405 $opts->{constants}{h} = $height;
2406 $opts->{constants}{cy} = $height/2;
2409 $Imager::ERRSTR = "No height supplied";
2412 my $code = Imager::Expr->new($opts);
2414 $Imager::ERRSTR = Imager::Expr::error();
2417 my $channels = $opts->{channels} || 3;
2418 unless ($channels >= 1 && $channels <= 4) {
2419 return Imager->_set_error("channels must be an integer between 1 and 4");
2422 my $img = Imager->new();
2423 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2424 $channels, $code->code(),
2425 $code->nregs(), $code->cregs(),
2426 [ map { $_->{IMG} } @imgs ]);
2427 if (!defined $img->{IMG}) {
2428 $Imager::ERRSTR = Imager->_error_as_msg();
2439 unless ($self->{IMG}) {
2440 $self->{ERRSTR}='empty input image';
2443 unless ($opts{src} && $opts{src}->{IMG}) {
2444 $self->{ERRSTR}='empty input image for src';
2448 %opts = (src_minx => 0,
2450 src_maxx => $opts{src}->getwidth(),
2451 src_maxy => $opts{src}->getheight(),
2455 defined $tx or $tx = $opts{left};
2456 defined $tx or $tx = 0;
2459 defined $ty or $ty = $opts{top};
2460 defined $ty or $ty = 0;
2462 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2463 $opts{src_minx}, $opts{src_miny},
2464 $opts{src_maxx}, $opts{src_maxy})) {
2465 $self->_set_error($self->_error_as_msg());
2482 unless ($self->{IMG}) {
2483 $self->_set_error("compose: empty input image");
2487 unless ($opts{src}) {
2488 $self->_set_error("compose: src parameter missing");
2492 unless ($opts{src}{IMG}) {
2493 $self->_set_error("compose: src parameter empty image");
2496 my $src = $opts{src};
2498 my $left = $opts{left};
2499 defined $left or $left = $opts{tx};
2500 defined $left or $left = 0;
2502 my $top = $opts{top};
2503 defined $top or $top = $opts{ty};
2504 defined $top or $top = 0;
2506 my $src_left = $opts{src_left};
2507 defined $src_left or $src_left = $opts{src_minx};
2508 defined $src_left or $src_left = 0;
2510 my $src_top = $opts{src_top};
2511 defined $src_top or $src_top = $opts{src_miny};
2512 defined $src_top or $src_top = 0;
2514 my $width = $opts{width};
2515 if (!defined $width && defined $opts{src_maxx}) {
2516 $width = $opts{src_maxx} - $src_left;
2518 defined $width or $width = $src->getwidth() - $src_left;
2520 my $height = $opts{height};
2521 if (!defined $height && defined $opts{src_maxy}) {
2522 $height = $opts{src_maxy} - $src_top;
2524 defined $height or $height = $src->getheight() - $src_top;
2526 my $combine = $self->_combine($opts{combine}, 'normal');
2529 unless ($opts{mask}{IMG}) {
2530 $self->_set_error("compose: mask parameter empty image");
2534 my $mask_left = $opts{mask_left};
2535 defined $mask_left or $mask_left = $opts{mask_minx};
2536 defined $mask_left or $mask_left = 0;
2538 my $mask_top = $opts{mask_top};
2539 defined $mask_top or $mask_top = $opts{mask_miny};
2540 defined $mask_top or $mask_top = 0;
2542 i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2543 $left, $top, $src_left, $src_top,
2544 $mask_left, $mask_top, $width, $height,
2545 $combine, $opts{opacity})
2549 i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2550 $width, $height, $combine, $opts{opacity})
2560 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2562 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2563 $dir = $xlate{$opts{'dir'}};
2564 return $self if i_flipxy($self->{IMG}, $dir);
2572 unless (defined wantarray) {
2573 my @caller = caller;
2574 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2578 if (defined $opts{right}) {
2579 my $degrees = $opts{right};
2581 $degrees += 360 * int(((-$degrees)+360)/360);
2583 $degrees = $degrees % 360;
2584 if ($degrees == 0) {
2585 return $self->copy();
2587 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2588 my $result = Imager->new();
2589 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2593 $self->{ERRSTR} = $self->_error_as_msg();
2598 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2602 elsif (defined $opts{radians} || defined $opts{degrees}) {
2603 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2605 my $back = $opts{back};
2606 my $result = Imager->new;
2608 $back = _color($back);
2610 $self->_set_error(Imager->errstr);
2614 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2617 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2619 if ($result->{IMG}) {
2623 $self->{ERRSTR} = $self->_error_as_msg();
2628 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2633 sub matrix_transform {
2637 unless (defined wantarray) {
2638 my @caller = caller;
2639 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2643 if ($opts{matrix}) {
2644 my $xsize = $opts{xsize} || $self->getwidth;
2645 my $ysize = $opts{ysize} || $self->getheight;
2647 my $result = Imager->new;
2649 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2650 $opts{matrix}, $opts{back})
2654 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2662 $self->{ERRSTR} = "matrix parameter required";
2668 *yatf = \&matrix_transform;
2670 # These two are supported for legacy code only
2673 return Imager::Color->new(@_);
2677 return Imager::Color::set(@_);
2680 # Draws a box between the specified corner points.
2683 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2684 my $dflcl=i_color_new(255,255,255,255);
2685 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2687 if (exists $opts{'box'}) {
2688 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2689 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2690 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2691 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2694 if ($opts{filled}) {
2695 my $color = _color($opts{'color'});
2697 $self->{ERRSTR} = $Imager::ERRSTR;
2700 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2701 $opts{ymax}, $color);
2703 elsif ($opts{fill}) {
2704 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2705 # assume it's a hash ref
2706 require 'Imager/Fill.pm';
2707 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2708 $self->{ERRSTR} = $Imager::ERRSTR;
2712 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2713 $opts{ymax},$opts{fill}{fill});
2716 my $color = _color($opts{'color'});
2718 $self->{ERRSTR} = $Imager::ERRSTR;
2721 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2729 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2730 my $dflcl=i_color_new(255,255,255,255);
2731 my %opts=(color=>$dflcl,
2732 'r'=>_min($self->getwidth(),$self->getheight())/3,
2733 'x'=>$self->getwidth()/2,
2734 'y'=>$self->getheight()/2,
2735 'd1'=>0, 'd2'=>361, @_);
2738 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2739 # assume it's a hash ref
2740 require 'Imager/Fill.pm';
2741 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2742 $self->{ERRSTR} = $Imager::ERRSTR;
2746 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2747 $opts{'d2'}, $opts{fill}{fill});
2750 my $color = _color($opts{'color'});
2752 $self->{ERRSTR} = $Imager::ERRSTR;
2755 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2756 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2760 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2761 $opts{'d1'}, $opts{'d2'}, $color);
2767 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2768 # assume it's a hash ref
2769 require 'Imager/Fill.pm';
2770 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2771 $self->{ERRSTR} = $Imager::ERRSTR;
2775 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2776 $opts{'d2'}, $opts{fill}{fill});
2779 my $color = _color($opts{'color'});
2781 $self->{ERRSTR} = $Imager::ERRSTR;
2784 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2785 $opts{'d1'}, $opts{'d2'}, $color);
2792 # Draws a line from one point to the other
2793 # the endpoint is set if the endp parameter is set which it is by default.
2794 # to turn of the endpoint being set use endp=>0 when calling line.
2798 my $dflcl=i_color_new(0,0,0,0);
2799 my %opts=(color=>$dflcl,
2802 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2804 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2805 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2807 my $color = _color($opts{'color'});
2809 $self->{ERRSTR} = $Imager::ERRSTR;
2813 $opts{antialias} = $opts{aa} if defined $opts{aa};
2814 if ($opts{antialias}) {
2815 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2816 $color, $opts{endp});
2818 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2819 $color, $opts{endp});
2824 # Draws a line between an ordered set of points - It more or less just transforms this
2825 # into a list of lines.
2829 my ($pt,$ls,@points);
2830 my $dflcl=i_color_new(0,0,0,0);
2831 my %opts=(color=>$dflcl,@_);
2833 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2835 if (exists($opts{points})) { @points=@{$opts{points}}; }
2836 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2837 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2840 # print Dumper(\@points);
2842 my $color = _color($opts{'color'});
2844 $self->{ERRSTR} = $Imager::ERRSTR;
2847 $opts{antialias} = $opts{aa} if defined $opts{aa};
2848 if ($opts{antialias}) {
2851 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2858 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2868 my ($pt,$ls,@points);
2869 my $dflcl = i_color_new(0,0,0,0);
2870 my %opts = (color=>$dflcl, @_);
2872 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2874 if (exists($opts{points})) {
2875 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2876 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2879 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2880 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2883 if ($opts{'fill'}) {
2884 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2885 # assume it's a hash ref
2886 require 'Imager/Fill.pm';
2887 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2888 $self->{ERRSTR} = $Imager::ERRSTR;
2892 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2893 $opts{'fill'}{'fill'});
2896 my $color = _color($opts{'color'});
2898 $self->{ERRSTR} = $Imager::ERRSTR;
2901 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2908 # this the multipoint bezier curve
2909 # this is here more for testing that actual usage since
2910 # this is not a good algorithm. Usually the curve would be
2911 # broken into smaller segments and each done individually.
2915 my ($pt,$ls,@points);
2916 my $dflcl=i_color_new(0,0,0,0);
2917 my %opts=(color=>$dflcl,@_);
2919 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2921 if (exists $opts{points}) {
2922 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2923 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2926 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2927 $self->{ERRSTR}='Missing or invalid points.';
2931 my $color = _color($opts{'color'});
2933 $self->{ERRSTR} = $Imager::ERRSTR;
2936 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2942 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2945 unless (exists $opts{'x'} && exists $opts{'y'}) {
2946 $self->{ERRSTR} = "missing seed x and y parameters";
2950 if ($opts{border}) {
2951 my $border = _color($opts{border});
2953 $self->_set_error($Imager::ERRSTR);
2957 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2958 # assume it's a hash ref
2959 require Imager::Fill;
2960 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2961 $self->{ERRSTR} = $Imager::ERRSTR;
2965 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2966 $opts{fill}{fill}, $border);
2969 my $color = _color($opts{'color'});
2971 $self->{ERRSTR} = $Imager::ERRSTR;
2974 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2981 $self->{ERRSTR} = $self->_error_as_msg();
2987 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2988 # assume it's a hash ref
2989 require 'Imager/Fill.pm';
2990 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2991 $self->{ERRSTR} = $Imager::ERRSTR;
2995 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2998 my $color = _color($opts{'color'});
3000 $self->{ERRSTR} = $Imager::ERRSTR;
3003 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3009 $self->{ERRSTR} = $self->_error_as_msg();
3018 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
3020 unless (exists $opts{'x'} && exists $opts{'y'}) {
3021 $self->{ERRSTR} = 'missing x and y parameters';
3027 my $color = _color($opts{color})
3029 if (ref $x && ref $y) {
3030 unless (@$x == @$y) {
3031 $self->{ERRSTR} = 'length of x and y mismatch';
3035 if ($color->isa('Imager::Color')) {
3036 for my $i (0..$#{$opts{'x'}}) {
3037 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3042 for my $i (0..$#{$opts{'x'}}) {
3043 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3051 if ($color->isa('Imager::Color')) {
3052 i_ppix($self->{IMG}, $x, $y, $color)
3056 i_ppixf($self->{IMG}, $x, $y, $color)
3067 my %opts = ( "type"=>'8bit', @_);
3069 unless (exists $opts{'x'} && exists $opts{'y'}) {
3070 $self->{ERRSTR} = 'missing x and y parameters';
3076 if (ref $x && ref $y) {
3077 unless (@$x == @$y) {
3078 $self->{ERRSTR} = 'length of x and y mismatch';
3082 if ($opts{"type"} eq '8bit') {
3083 for my $i (0..$#{$opts{'x'}}) {
3084 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3088 for my $i (0..$#{$opts{'x'}}) {
3089 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3092 return wantarray ? @result : \@result;
3095 if ($opts{"type"} eq '8bit') {
3096 return i_get_pixel($self->{IMG}, $x, $y);
3099 return i_gpixf($self->{IMG}, $x, $y);
3108 my %opts = ( type => '8bit', x=>0, @_);
3110 $self->_valid_image or return;
3112 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3114 unless (defined $opts{'y'}) {
3115 $self->_set_error("missing y parameter");
3119 if ($opts{type} eq '8bit') {
3120 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3123 elsif ($opts{type} eq 'float') {
3124 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3127 elsif ($opts{type} eq 'index') {
3128 unless (i_img_type($self->{IMG})) {
3129 $self->_set_error("type => index only valid on paletted images");
3132 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3136 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3143 my %opts = ( x=>0, @_);
3145 $self->_valid_image or return;
3147 unless (defined $opts{'y'}) {
3148 $self->_set_error("missing y parameter");
3153 if (ref $opts{pixels} && @{$opts{pixels}}) {
3154 # try to guess the type
3155 if ($opts{pixels}[0]->isa('Imager::Color')) {
3156 $opts{type} = '8bit';
3158 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3159 $opts{type} = 'float';
3162 $self->_set_error("missing type parameter and could not guess from pixels");
3168 $opts{type} = '8bit';
3172 if ($opts{type} eq '8bit') {
3173 if (ref $opts{pixels}) {
3174 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3177 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3180 elsif ($opts{type} eq 'float') {
3181 if (ref $opts{pixels}) {
3182 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3185 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3188 elsif ($opts{type} eq 'index') {
3189 if (ref $opts{pixels}) {
3190 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3193 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3197 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3204 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3206 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3208 unless (defined $opts{'y'}) {
3209 $self->_set_error("missing y parameter");
3213 unless ($opts{channels}) {
3214 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3217 if ($opts{target}) {
3218 my $target = $opts{target};
3219 my $offset = $opts{offset};
3220 if ($opts{type} eq '8bit') {
3221 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3222 $opts{y}, @{$opts{channels}})
3224 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3225 return scalar(@samples);
3227 elsif ($opts{type} eq 'float') {
3228 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3229 $opts{y}, @{$opts{channels}});
3230 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3231 return scalar(@samples);
3233 elsif ($opts{type} =~ /^(\d+)bit$/) {
3237 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3238 $opts{y}, $bits, $target,
3239 $offset, @{$opts{channels}});
3240 unless (defined $count) {
3241 $self->_set_error(Imager->_error_as_msg);
3248 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3253 if ($opts{type} eq '8bit') {
3254 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3255 $opts{y}, @{$opts{channels}});
3257 elsif ($opts{type} eq 'float') {
3258 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3259 $opts{y}, @{$opts{channels}});
3261 elsif ($opts{type} =~ /^(\d+)bit$/) {
3265 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3266 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3271 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3279 my %opts = ( x => 0, offset => 0, @_ );
3281 unless ($self->{IMG}) {
3282 $self->_set_error('setsamples: empty input image');
3286 unless(defined $opts{data} && ref $opts{data}) {
3287 $self->_set_error('setsamples: data parameter missing or invalid');
3291 unless ($opts{channels}) {
3292 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3295 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3296 $self->_set_error('setsamples: type parameter missing or invalid');
3301 unless (defined $opts{width}) {
3302 $opts{width} = $self->getwidth() - $opts{x};
3305 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3306 $opts{channels}, $opts{data}, $opts{offset},
3308 unless (defined $count) {
3309 $self->_set_error(Imager->_error_as_msg);
3316 # make an identity matrix of the given size
3320 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3321 for my $c (0 .. ($size-1)) {
3322 $matrix->[$c][$c] = 1;
3327 # general function to convert an image
3329 my ($self, %opts) = @_;
3332 unless (defined wantarray) {
3333 my @caller = caller;
3334 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3338 # the user can either specify a matrix or preset
3339 # the matrix overrides the preset
3340 if (!exists($opts{matrix})) {
3341 unless (exists($opts{preset})) {
3342 $self->{ERRSTR} = "convert() needs a matrix or preset";
3346 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3347 # convert to greyscale, keeping the alpha channel if any
3348 if ($self->getchannels == 3) {
3349 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3351 elsif ($self->getchannels == 4) {
3352 # preserve the alpha channel
3353 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3358 $matrix = _identity($self->getchannels);
3361 elsif ($opts{preset} eq 'noalpha') {
3362 # strip the alpha channel
3363 if ($self->getchannels == 2 or $self->getchannels == 4) {
3364 $matrix = _identity($self->getchannels);
3365 pop(@$matrix); # lose the alpha entry
3368 $matrix = _identity($self->getchannels);
3371 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3373 $matrix = [ [ 1 ] ];
3375 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3376 $matrix = [ [ 0, 1 ] ];
3378 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3379 $matrix = [ [ 0, 0, 1 ] ];
3381 elsif ($opts{preset} eq 'alpha') {
3382 if ($self->getchannels == 2 or $self->getchannels == 4) {
3383 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3386 # the alpha is just 1 <shrug>
3387 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3390 elsif ($opts{preset} eq 'rgb') {
3391 if ($self->getchannels == 1) {
3392 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3394 elsif ($self->getchannels == 2) {
3395 # preserve the alpha channel
3396 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3399 $matrix = _identity($self->getchannels);
3402 elsif ($opts{preset} eq 'addalpha') {
3403 if ($self->getchannels == 1) {
3404 $matrix = _identity(2);
3406 elsif ($self->getchannels == 3) {
3407 $matrix = _identity(4);
3410 $matrix = _identity($self->getchannels);
3414 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3420 $matrix = $opts{matrix};
3423 my $new = Imager->new;
3424 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3425 unless ($new->{IMG}) {
3426 # most likely a bad matrix
3427 $self->{ERRSTR} = _error_as_msg();
3434 # general function to map an image through lookup tables
3437 my ($self, %opts) = @_;
3438 my @chlist = qw( red green blue alpha );
3440 if (!exists($opts{'maps'})) {
3441 # make maps from channel maps
3443 for $chnum (0..$#chlist) {
3444 if (exists $opts{$chlist[$chnum]}) {
3445 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3446 } elsif (exists $opts{'all'}) {
3447 $opts{'maps'}[$chnum] = $opts{'all'};
3451 if ($opts{'maps'} and $self->{IMG}) {
3452 i_map($self->{IMG}, $opts{'maps'} );
3458 my ($self, %opts) = @_;
3460 defined $opts{mindist} or $opts{mindist} = 0;
3462 defined $opts{other}
3463 or return $self->_set_error("No 'other' parameter supplied");
3464 defined $opts{other}{IMG}
3465 or return $self->_set_error("No image data in 'other' image");
3468 or return $self->_set_error("No image data");
3470 my $result = Imager->new;
3471 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3473 or return $self->_set_error($self->_error_as_msg());
3478 # destructive border - image is shrunk by one pixel all around
3481 my ($self,%opts)=@_;
3482 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3483 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3487 # Get the width of an image
3491 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3492 return (i_img_info($self->{IMG}))[0];
3495 # Get the height of an image
3499 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3500 return (i_img_info($self->{IMG}))[1];
3503 # Get number of channels in an image
3507 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3508 return i_img_getchannels($self->{IMG});
3515 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3516 return i_img_getmask($self->{IMG});
3524 if (!defined($self->{IMG})) {
3525 $self->{ERRSTR} = 'image is empty';
3528 unless (defined $opts{mask}) {
3529 $self->_set_error("mask parameter required");
3532 i_img_setmask( $self->{IMG} , $opts{mask} );
3537 # Get number of colors in an image
3541 my %opts=('maxcolors'=>2**30,@_);
3542 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3543 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3544 return ($rc==-1? undef : $rc);
3547 # Returns a reference to a hash. The keys are colour named (packed) and the
3548 # values are the number of pixels in this colour.
3549 sub getcolorusagehash {
3552 my %opts = ( maxcolors => 2**30, @_ );
3553 my $max_colors = $opts{maxcolors};
3554 unless (defined $max_colors && $max_colors > 0) {
3555 $self->_set_error('maxcolors must be a positive integer');
3559 unless (defined $self->{IMG}) {
3560 $self->_set_error('empty input image');
3564 my $channels= $self->getchannels;
3565 # We don't want to look at the alpha channel, because some gifs using it
3566 # doesn't define it for every colour (but only for some)
3567 $channels -= 1 if $channels == 2 or $channels == 4;
3569 my $height = $self->getheight;
3570 for my $y (0 .. $height - 1) {
3571 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3572 while (length $colors) {
3573 $color_use{ substr($colors, 0, $channels, '') }++;
3575 keys %color_use > $max_colors
3581 # This will return a ordered array of the colour usage. Kind of the sorted
3582 # version of the values of the hash returned by getcolorusagehash.
3583 # You might want to add safety checks and change the names, etc...
3587 my %opts = ( maxcolors => 2**30, @_ );
3588 my $max_colors = $opts{maxcolors};
3589 unless (defined $max_colors && $max_colors > 0) {
3590 $self->_set_error('maxcolors must be a positive integer');
3594 unless (defined $self->{IMG}) {
3595 $self->_set_error('empty input image');
3599 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3602 # draw string to an image
3606 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3608 my %input=('x'=>0, 'y'=>0, @_);
3609 defined($input{string}) or $input{string} = $input{text};
3611 unless(defined $input{string}) {
3612 $self->{ERRSTR}="missing required parameter 'string'";
3616 unless($input{font}) {
3617 $self->{ERRSTR}="missing required parameter 'font'";
3621 unless ($input{font}->draw(image=>$self, %input)) {
3633 unless ($self->{IMG}) {
3634 $self->{ERRSTR}='empty input image';
3643 my %input=('x'=>0, 'y'=>0, @_);
3644 $input{string}||=$input{text};
3646 unless(exists $input{string}) {
3647 $self->_set_error("missing required parameter 'string'");
3651 unless($input{font}) {
3652 $self->_set_error("missing required parameter 'font'");
3657 unless (@result = $input{font}->align(image=>$img, %input)) {
3661 return wantarray ? @result : $result[0];
3664 my @file_limit_names = qw/width height bytes/;
3666 sub set_file_limits {
3673 @values{@file_limit_names} = (0) x @file_limit_names;
3676 @values{@file_limit_names} = i_get_image_file_limits();
3679 for my $key (keys %values) {
3680 defined $opts{$key} and $values{$key} = $opts{$key};
3683 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3686 sub get_file_limits {
3687 i_get_image_file_limits();
3690 # Shortcuts that can be exported
3692 sub newcolor { Imager::Color->new(@_); }
3693 sub newfont { Imager::Font->new(@_); }
3694 sub NCF { Imager::Color::Float->new(@_) }
3696 *NC=*newcolour=*newcolor;
3703 #### Utility routines
3706 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3710 my ($self, $msg) = @_;
3713 $self->{ERRSTR} = $msg;
3721 # Default guess for the type of an image from extension
3723 sub def_guess_type {
3726 $ext=($name =~ m/\.([^\.]+)$/)[0];
3727 return 'tiff' if ($ext =~ m/^tiff?$/);
3728 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3729 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3730 return 'png' if ($ext eq "png");
3731 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3732 return 'tga' if ($ext eq "tga");
3733 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3734 return 'gif' if ($ext eq "gif");
3735 return 'raw' if ($ext eq "raw");
3736 return lc $ext; # best guess
3741 return @combine_types;
3744 # get the minimum of a list
3748 for(@_) { if ($_<$mx) { $mx=$_; }}
3752 # get the maximum of a list
3756 for(@_) { if ($_>$mx) { $mx=$_; }}
3760 # string stuff for iptc headers
3764 $str = substr($str,3);
3765 $str =~ s/[\n\r]//g;
3772 # A little hack to parse iptc headers.
3777 my($caption,$photogr,$headln,$credit);
3779 my $str=$self->{IPTCRAW};
3784 @ar=split(/8BIM/,$str);
3789 @sar=split(/\034\002/);
3790 foreach $item (@sar) {
3791 if ($item =~ m/^x/) {
3792 $caption = _clean($item);
3795 if ($item =~ m/^P/) {
3796 $photogr = _clean($item);
3799 if ($item =~ m/^i/) {
3800 $headln = _clean($item);
3803 if ($item =~ m/^n/) {
3804 $credit = _clean($item);
3810 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3817 or die "Only C language supported";
3819 require Imager::ExtUtils;
3820 return Imager::ExtUtils->inline_config;
3825 # Below is the stub of documentation for your module. You better edit it!
3829 Imager - Perl extension for Generating 24 bit Images
3839 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3844 my $img = Imager->new();
3845 # see Imager::Files for information on the read() method
3846 $img->read(file=>$file) or die $img->errstr();
3848 $file =~ s/\.[^.]*$//;
3850 # Create smaller version
3851 # documented in Imager::Transformations
3852 my $thumb = $img->scale(scalefactor=>.3);
3854 # Autostretch individual channels
3855 $thumb->filter(type=>'autolevels');
3857 # try to save in one of these formats
3860 for $format ( qw( png gif jpg tiff ppm ) ) {
3861 # Check if given format is supported
3862 if ($Imager::formats{$format}) {
3863 $file.="_low.$format";
3864 print "Storing image as: $file\n";
3865 # documented in Imager::Files
3866 $thumb->write(file=>$file) or
3874 Imager is a module for creating and altering images. It can read and
3875 write various image formats, draw primitive shapes like lines,and
3876 polygons, blend multiple images together in various ways, scale, crop,
3877 render text and more.
3879 =head2 Overview of documentation
3885 Imager - This document - Synopsis, Example, Table of Contents and
3890 L<Imager::Tutorial> - a brief introduction to Imager.
3894 L<Imager::Cookbook> - how to do various things with Imager.
3898 L<Imager::ImageTypes> - Basics of constructing image objects with
3899 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3900 8/16/double bits/channel, color maps, channel masks, image tags, color
3901 quantization. Also discusses basic image information methods.
3905 L<Imager::Files> - IO interaction, reading/writing images, format
3910 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3915 L<Imager::Color> - Color specification.
3919 L<Imager::Fill> - Fill pattern specification.
3923 L<Imager::Font> - General font rendering, bounding boxes and font
3928 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3929 blending, pasting, convert and map.
3933 L<Imager::Engines> - Programmable transformations through
3934 C<transform()>, C<transform2()> and C<matrix_transform()>.
3938 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3943 L<Imager::Expr> - Expressions for evaluation engine used by
3948 L<Imager::Matrix2d> - Helper class for affine transformations.
3952 L<Imager::Fountain> - Helper for making gradient profiles.
3956 L<Imager::API> - using Imager's C API
3960 L<Imager::APIRef> - API function reference
3964 L<Imager::Inline> - using Imager's C API from Inline::C
3968 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3972 =head2 Basic Overview
3974 An Image object is created with C<$img = Imager-E<gt>new()>.
3977 $img=Imager->new(); # create empty image
3978 $img->read(file=>'lena.png',type=>'png') or # read image from file
3979 die $img->errstr(); # give an explanation
3980 # if something failed
3982 or if you want to create an empty image:
3984 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3986 This example creates a completely black image of width 400 and height
3989 =head1 ERROR HANDLING
3991 In general a method will return false when it fails, if it does use
3992 the errstr() method to find out why:
3998 Returns the last error message in that context.
4000 If the last error you received was from calling an object method, such
4001 as read, call errstr() as an object method to find out why:
4003 my $image = Imager->new;
4004 $image->read(file => 'somefile.gif')
4005 or die $image->errstr;
4007 If it was a class method then call errstr() as a class method:
4009 my @imgs = Imager->read_multi(file => 'somefile.gif')
4010 or die Imager->errstr;
4012 Note that in some cases object methods are implemented in terms of
4013 class methods so a failing object method may set both.
4017 The C<Imager-E<gt>new> method is described in detail in
4018 L<Imager::ImageTypes>.
4022 Where to find information on methods for Imager class objects.
4024 addcolors() - L<Imager::ImageTypes/addcolors>
4026 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4028 align_string() - L<Imager::Draw/align_string>
4030 arc() - L<Imager::Draw/arc>
4032 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4035 box() - L<Imager::Draw/box>
4037 circle() - L<Imager::Draw/circle>
4039 colorcount() - L<Imager::Draw/colorcount>
4041 combines() - L<Imager::Draw/combines>
4043 compose() - L<Imager::Transformations/compose>
4045 convert() - L<Imager::Transformations/"Color transformations"> -
4046 transform the color space
4048 copy() - L<Imager::Transformations/copy>
4050 crop() - L<Imager::Transformations/crop> - extract part of an image
4052 def_guess_type() - L<Imager::Files/def_guess_type>
4054 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4056 difference() - L<Imager::Filters/"Image Difference">
4058 errstr() - L<"Basic Overview">
4060 filter() - L<Imager::Filters>
4062 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
4065 flip() - L<Imager::Transformations/flip>
4067 flood_fill() - L<Imager::Draw/flood_fill>
4069 getchannels() - L<Imager::ImageTypes/getchannels>
4071 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
4073 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4074 palette, if it has one
4076 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4078 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4080 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4082 getheight() - L<Imager::ImageTypes/getwidth>
4084 getmask() - L<Imager::ImageTypes/getmask>
4086 getpixel() - L<Imager::Draw/getpixel>
4088 getsamples() - L<Imager::Draw/getsamples>
4090 getscanline() - L<Imager::Draw/getscanline>
4092 getwidth() - L<Imager::ImageTypes/getwidth>
4094 img_set() - L<Imager::ImageTypes/img_set>
4096 init() - L<Imager::ImageTypes/init>
4098 is_bilevel() - L<Imager::ImageTypes/is_bilevel>
4100 line() - L<Imager::Draw/line>
4102 load_plugin() - L<Imager::Filters/load_plugin>
4104 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4107 masked() - L<Imager::ImageTypes/masked> - make a masked image
4109 matrix_transform() - L<Imager::Engines/matrix_transform>
4111 maxcolors() - L<Imager::ImageTypes/maxcolors>
4113 NC() - L<Imager::Handy/NC>
4115 NCF() - L<Imager::Handy/NCF>
4117 new() - L<Imager::ImageTypes/new>
4119 newcolor() - L<Imager::Handy/newcolor>
4121 newcolour() - L<Imager::Handy/newcolour>
4123 newfont() - L<Imager::Handy/newfont>
4125 NF() - L<Imager::Handy/NF>
4127 open() - L<Imager::Files> - an alias for read()
4129 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4132 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4134 polygon() - L<Imager::Draw/polygon>
4136 polyline() - L<Imager::Draw/polyline>
4138 read() - L<Imager::Files> - read a single image from an image file
4140 read_multi() - L<Imager::Files> - read multiple images from an image
4143 read_types() - L<Imager::Files/read_types> - list image types Imager
4146 register_filter() - L<Imager::Filters/register_filter>
4148 register_reader() - L<Imager::Filters/register_reader>
4150 register_writer() - L<Imager::Filters/register_writer>
4152 rotate() - L<Imager::Transformations/rotate>
4154 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4155 image and use the alpha channel
4157 scale() - L<Imager::Transformations/scale>
4159 scale_calculate() - L<Imager::Transformations/scale_calculate>
4161 scaleX() - L<Imager::Transformations/scaleX>
4163 scaleY() - L<Imager::Transformations/scaleY>
4165 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4168 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4170 setmask() - L<Imager::ImageTypes/setmask>
4172 setpixel() - L<Imager::Draw/setpixel>
4174 setsamples() - L<Imager::Draw/setsamples>
4176 setscanline() - L<Imager::Draw/setscanline>
4178 settag() - L<Imager::ImageTypes/settag>
4180 string() - L<Imager::Draw/string> - draw text on an image
4182 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4184 to_paletted() - L<Imager::ImageTypes/to_paletted>
4186 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4188 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4190 transform() - L<Imager::Engines/"transform">
4192 transform2() - L<Imager::Engines/"transform2">
4194 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4196 unload_plugin() - L<Imager::Filters/unload_plugin>
4198 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4201 write() - L<Imager::Files> - write an image to a file
4203 write_multi() - L<Imager::Files> - write multiple image to an image
4206 write_types() - L<Imager::Files/read_types> - list image types Imager
4209 =head1 CONCEPT INDEX
4211 animated GIF - L<Imager::Files/"Writing an animated GIF">
4213 aspect ratio - L<Imager::ImageTypes/i_xres>,
4214 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4216 blend - alpha blending one image onto another
4217 L<Imager::Transformations/rubthrough>
4219 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4221 boxes, drawing - L<Imager::Draw/box>
4223 changes between image - L<Imager::Filter/"Image Difference">
4225 color - L<Imager::Color>
4227 color names - L<Imager::Color>, L<Imager::Color::Table>
4229 combine modes - L<Imager::Fill/combine>
4231 compare images - L<Imager::Filter/"Image Difference">
4233 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
4235 convolution - L<Imager::Filter/conv>
4237 cropping - L<Imager::Transformations/crop>
4239 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4241 C<diff> images - L<Imager::Filter/"Image Difference">
4243 dpi - L<Imager::ImageTypes/i_xres>,
4244 L<Imager::Cookbook/"Image spatial resolution">
4246 drawing boxes - L<Imager::Draw/box>
4248 drawing lines - L<Imager::Draw/line>
4250 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4252 error message - L<"Basic Overview">
4254 files, font - L<Imager::Font>
4256 files, image - L<Imager::Files>
4258 filling, types of fill - L<Imager::Fill>
4260 filling, boxes - L<Imager::Draw/box>
4262 filling, flood fill - L<Imager::Draw/flood_fill>
4264 flood fill - L<Imager::Draw/flood_fill>
4266 fonts - L<Imager::Font>
4268 fonts, drawing with - L<Imager::Draw/string>,
4269 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4271 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4273 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4275 fountain fill - L<Imager::Fill/"Fountain fills">,
4276 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4277 L<Imager::Filters/gradgen>
4279 GIF files - L<Imager::Files/"GIF">
4281 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4283 gradient fill - L<Imager::Fill/"Fountain fills">,
4284 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4285 L<Imager::Filters/gradgen>
4287 grayscale, convert image to - L<Imager::Transformations/convert>
4289 guassian blur - L<Imager::Filter/guassian>
4291 hatch fills - L<Imager::Fill/"Hatched fills">
4293 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4295 invert image - L<Imager::Filter/hardinvert>
4297 JPEG - L<Imager::Files/"JPEG">
4299 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4301 lines, drawing - L<Imager::Draw/line>
4303 matrix - L<Imager::Matrix2d>,
4304 L<Imager::Transformations/"Matrix Transformations">,
4305 L<Imager::Font/transform>
4307 metadata, image - L<Imager::ImageTypes/"Tags">
4309 mosaic - L<Imager::Filter/mosaic>
4311 noise, filter - L<Imager::Filter/noise>
4313 noise, rendered - L<Imager::Filter/turbnoise>,
4314 L<Imager::Filter/radnoise>
4316 paste - L<Imager::Transformations/paste>,
4317 L<Imager::Transformations/rubthrough>
4319 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4320 L<Imager::ImageTypes/new>
4322 posterize - L<Imager::Filter/postlevels>
4324 png files - L<Imager::Files>, L<Imager::Files/"PNG">
4326 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
4328 rectangles, drawing - L<Imager::Draw/box>
4330 resizing an image - L<Imager::Transformations/scale>,
4331 L<Imager::Transformations/crop>
4333 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4335 saving an image - L<Imager::Files>
4337 scaling - L<Imager::Transformations/scale>
4339 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4341 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4343 size, image - L<Imager::ImageTypes/getwidth>,
4344 L<Imager::ImageTypes/getheight>
4346 size, text - L<Imager::Font/bounding_box>
4348 tags, image metadata - L<Imager::ImageTypes/"Tags">
4350 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4351 L<Imager::Font::Wrap>
4353 text, wrapping text in an area - L<Imager::Font::Wrap>
4355 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4357 tiles, color - L<Imager::Filter/mosaic>
4359 unsharp mask - L<Imager::Filter/unsharpmask>
4361 watermark - L<Imager::Filter/watermark>
4363 writing an image to a file - L<Imager::Files>
4367 The best place to get help with Imager is the mailing list.
4369 To subscribe send a message with C<subscribe> in the body to:
4371 imager-devel+request@molar.is
4377 L<http://www.molar.is/en/lists/imager-devel/>
4381 where you can also find the mailing list archive.
4383 You can report bugs by pointing your browser at:
4387 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4391 or by sending an email to:
4395 bug-Imager@rt.cpan.org
4399 Please remember to include the versions of Imager, perl, supporting
4400 libraries, and any relevant code. If you have specific images that
4401 cause the problems, please include those too.
4403 If you don't want to publish your email address on a mailing list you
4404 can use CPAN::Forum:
4406 http://www.cpanforum.com/dist/Imager
4408 You will need to register to post.
4410 =head1 CONTRIBUTING TO IMAGER
4416 If you like or dislike Imager, you can add a public review of Imager
4419 http://cpanratings.perl.org/dist/Imager
4421 This requires a Bitcard Account (http://www.bitcard.org).
4423 You can also send email to the maintainer below.
4425 If you send me a bug report via email, it will be copied to RT.
4429 I accept patches, preferably against the main branch in subversion.
4430 You should include an explanation of the reason for why the patch is
4433 Your patch should include regression tests where possible, otherwise
4434 it will be delayed until I get a chance to write them.
4438 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4440 Arnar M. Hrafnkelsson is the original author of Imager.
4442 Many others have contributed to Imager, please see the README for a
4447 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4448 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4449 L<Imager::Font>(3), L<Imager::Transformations>(3),
4450 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4451 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4453 L<http://imager.perl.org/>
4455 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4457 Other perl imaging modules include:
4459 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).