4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
130 # registered file readers
133 # registered file writers
136 # modules we attempted to autoload
137 my %attempted_to_load;
139 # library keys that are image file formats
140 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
142 # image pixel combine types
144 qw/none normal multiply dissolve add subtract diff lighten darken
145 hue saturation value color/;
147 @combine_types{@combine_types} = 0 .. $#combine_types;
148 $combine_types{mult} = $combine_types{multiply};
149 $combine_types{'sub'} = $combine_types{subtract};
150 $combine_types{sat} = $combine_types{saturation};
152 # this will be used to store global defaults at some point
161 XSLoader::load(Imager => $VERSION);
165 push @ISA, 'DynaLoader';
166 bootstrap Imager $VERSION;
173 png => "Imager::File::PNG",
174 gif => "Imager::File::GIF",
175 tiff => "Imager::File::TIFF",
176 jpeg => "Imager::File::JPEG",
177 w32 => "Imager::Font::W32",
178 ft2 => "Imager::Font::FT2",
181 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
184 for(i_list_formats()) { $formats_low{$_}++; }
186 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
190 # the members of the subhashes under %filters are:
191 # callseq - a list of the parameters to the underlying filter in the
192 # order they are passed
193 # callsub - a code ref that takes a named parameter list and calls the
195 # defaults - a hash of default values
196 # names - defines names for value of given parameters so if the names
197 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
198 # foo parameter, the filter will receive 1 for the foo
201 callseq => ['image','intensity'],
202 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
206 callseq => ['image', 'amount', 'subtype'],
207 defaults => { amount=>3,subtype=>0 },
208 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
211 $filters{hardinvert} ={
212 callseq => ['image'],
214 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
217 $filters{hardinvertall} =
219 callseq => ['image'],
221 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
224 $filters{autolevels} ={
225 callseq => ['image','lsat','usat','skew'],
226 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
227 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
230 $filters{turbnoise} ={
231 callseq => ['image'],
232 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
233 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
236 $filters{radnoise} ={
237 callseq => ['image'],
238 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
239 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
244 callseq => ['image', 'coef'],
249 i_conv($hsh{image},$hsh{coef})
250 or die Imager->_error_as_msg() . "\n";
256 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
257 defaults => { dist => 0 },
261 my @colors = @{$hsh{colors}};
264 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
268 $filters{nearest_color} =
270 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
275 # make sure the segments are specified with colors
277 for my $color (@{$hsh{colors}}) {
278 my $new_color = _color($color)
279 or die $Imager::ERRSTR."\n";
280 push @colors, $new_color;
283 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
285 or die Imager->_error_as_msg() . "\n";
288 $filters{gaussian} = {
289 callseq => [ 'image', 'stddev' ],
291 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
295 callseq => [ qw(image size) ],
296 defaults => { size => 20 },
297 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
301 callseq => [ qw(image bump elevation lightx lighty st) ],
302 defaults => { elevation=>0, st=> 2 },
305 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
306 $hsh{lightx}, $hsh{lighty}, $hsh{st});
309 $filters{bumpmap_complex} =
311 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
328 for my $cname (qw/Ia Il Is/) {
329 my $old = $hsh{$cname};
330 my $new_color = _color($old)
331 or die $Imager::ERRSTR, "\n";
332 $hsh{$cname} = $new_color;
334 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
335 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
336 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
340 $filters{postlevels} =
342 callseq => [ qw(image levels) ],
343 defaults => { levels => 10 },
344 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
346 $filters{watermark} =
348 callseq => [ qw(image wmark tx ty pixdiff) ],
349 defaults => { pixdiff=>10, tx=>0, ty=>0 },
353 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
359 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
361 ftype => { linear => 0,
367 repeat => { none => 0,
382 multiply => 2, mult => 2,
385 subtract => 5, 'sub' => 5,
395 defaults => { ftype => 0, repeat => 0, combine => 0,
396 super_sample => 0, ssample_param => 4,
409 # make sure the segments are specified with colors
411 for my $segment (@{$hsh{segments}}) {
412 my @new_segment = @$segment;
414 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
415 push @segments, \@new_segment;
418 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
419 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
420 $hsh{ssample_param}, \@segments)
421 or die Imager->_error_as_msg() . "\n";
424 $filters{unsharpmask} =
426 callseq => [ qw(image stddev scale) ],
427 defaults => { stddev=>2.0, scale=>1.0 },
431 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
435 $FORMATGUESS=\&def_guess_type;
445 # NOTE: this might be moved to an import override later on
450 if ($_[$i] eq '-log-stderr') {
458 goto &Exporter::import;
462 i_init_log($_[0],$_[1]);
463 i_log_entry("Imager $VERSION starting\n", 1);
468 my %parms=(loglevel=>1,@_);
470 init_log($parms{'log'},$parms{'loglevel'});
473 if (exists $parms{'warn_obsolete'}) {
474 $warn_obsolete = $parms{'warn_obsolete'};
477 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
478 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
482 if (exists $parms{'t1log'}) {
483 i_init_fonts($parms{'t1log'});
489 print "shutdown code\n";
490 # for(keys %instances) { $instances{$_}->DESTROY(); }
491 malloc_state(); # how do decide if this should be used? -- store something from the import
492 print "Imager exiting\n";
496 # Load a filter plugin
501 my ($DSO_handle,$str)=DSO_open($filename);
502 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
503 my %funcs=DSO_funclist($DSO_handle);
504 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
506 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
508 $DSOs{$filename}=[$DSO_handle,\%funcs];
511 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
512 $DEBUG && print "eval string:\n",$evstr,"\n";
524 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
525 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
526 for(keys %{$funcref}) {
528 $DEBUG && print "unloading: $_\n";
530 my $rc=DSO_close($DSO_handle);
531 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
535 # take the results of i_error() and make a message out of it
537 return join(": ", map $_->[0], i_errors());
540 # this function tries to DWIM for color parameters
541 # color objects are used as is
542 # simple scalars are simply treated as single parameters to Imager::Color->new
543 # hashrefs are treated as named argument lists to Imager::Color->new
544 # arrayrefs are treated as list arguments to Imager::Color->new iff any
546 # other arrayrefs are treated as list arguments to Imager::Color::Float
550 # perl 5.6.0 seems to do weird things to $arg if we don't make an
551 # explicitly stringified copy
552 # I vaguely remember a bug on this on p5p, but couldn't find it
553 # through bugs.perl.org (I had trouble getting it to find any bugs)
554 my $copy = $arg . "";
558 if (UNIVERSAL::isa($arg, "Imager::Color")
559 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
563 if ($copy =~ /^HASH\(/) {
564 $result = Imager::Color->new(%$arg);
566 elsif ($copy =~ /^ARRAY\(/) {
567 $result = Imager::Color->new(@$arg);
570 $Imager::ERRSTR = "Not a color";
575 # assume Imager::Color::new knows how to handle it
576 $result = Imager::Color->new($arg);
583 my ($self, $combine, $default) = @_;
585 if (!defined $combine && ref $self) {
586 $combine = $self->{combine};
588 defined $combine or $combine = $defaults{combine};
589 defined $combine or $combine = $default;
591 if (exists $combine_types{$combine}) {
592 $combine = $combine_types{$combine};
601 $self->{IMG} and return 1;
603 $self->_set_error('empty input image');
608 # returns first defined parameter
611 return $_ if defined $_;
617 # Methods to be called on objects.
620 # Create a new Imager object takes very few parameters.
621 # usually you call this method and then call open from
622 # the resulting object
629 $self->{IMG}=undef; # Just to indicate what exists
630 $self->{ERRSTR}=undef; #
631 $self->{DEBUG}=$DEBUG;
632 $self->{DEBUG} and print "Initialized Imager\n";
633 if (defined $hsh{xsize} || defined $hsh{ysize}) {
634 unless ($self->img_set(%hsh)) {
635 $Imager::ERRSTR = $self->{ERRSTR};
639 elsif (defined $hsh{file} ||
642 defined $hsh{callback} ||
643 defined $hsh{readcb} ||
644 defined $hsh{data}) {
645 # allow $img = Imager->new(file => $filename)
648 # type is already used as a parameter to new(), rename it for the
650 if ($hsh{filetype}) {
651 $extras{type} = $hsh{filetype};
653 unless ($self->read(%hsh, %extras)) {
654 $Imager::ERRSTR = $self->{ERRSTR};
662 # Copy an entire image with no changes
663 # - if an image has magic the copy of it will not be magical
667 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
669 unless (defined wantarray) {
671 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
675 my $newcopy=Imager->new();
676 $newcopy->{IMG} = i_copy($self->{IMG});
685 unless ($self->{IMG}) {
686 $self->_set_error('empty input image');
689 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
690 my $src = $input{img} || $input{src};
692 $self->_set_error("no source image");
695 $input{left}=0 if $input{left} <= 0;
696 $input{top}=0 if $input{top} <= 0;
698 my($r,$b)=i_img_info($src->{IMG});
699 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
700 my ($src_right, $src_bottom);
701 if ($input{src_coords}) {
702 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
705 if (defined $input{src_maxx}) {
706 $src_right = $input{src_maxx};
708 elsif (defined $input{width}) {
709 if ($input{width} <= 0) {
710 $self->_set_error("paste: width must me positive");
713 $src_right = $src_left + $input{width};
718 if (defined $input{src_maxy}) {
719 $src_bottom = $input{src_maxy};
721 elsif (defined $input{height}) {
722 if ($input{height} < 0) {
723 $self->_set_error("paste: height must be positive");
726 $src_bottom = $src_top + $input{height};
733 $src_right > $r and $src_right = $r;
734 $src_bottom > $b and $src_bottom = $b;
736 if ($src_right <= $src_left
737 || $src_bottom < $src_top) {
738 $self->_set_error("nothing to paste");
742 i_copyto($self->{IMG}, $src->{IMG},
743 $src_left, $src_top, $src_right, $src_bottom,
744 $input{left}, $input{top});
746 return $self; # What should go here??
749 # Crop an image - i.e. return a new image that is smaller
753 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
755 unless (defined wantarray) {
757 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
763 my ($w, $h, $l, $r, $b, $t) =
764 @hsh{qw(width height left right bottom top)};
766 # work through the various possibilities
771 elsif (!defined $r) {
772 $r = $self->getwidth;
784 $l = int(0.5+($self->getwidth()-$w)/2);
789 $r = $self->getwidth;
795 elsif (!defined $b) {
796 $b = $self->getheight;
808 $t=int(0.5+($self->getheight()-$h)/2);
813 $b = $self->getheight;
816 ($l,$r)=($r,$l) if $l>$r;
817 ($t,$b)=($b,$t) if $t>$b;
820 $r > $self->getwidth and $r = $self->getwidth;
822 $b > $self->getheight and $b = $self->getheight;
824 if ($l == $r || $t == $b) {
825 $self->_set_error("resulting image would have no content");
828 if( $r < $l or $b < $t ) {
829 $self->_set_error("attempting to crop outside of the image");
832 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
834 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
839 my ($self, %opts) = @_;
841 $self->{IMG} or return $self->_set_error("Not a valid image");
843 my $x = $opts{xsize} || $self->getwidth;
844 my $y = $opts{ysize} || $self->getheight;
845 my $channels = $opts{channels} || $self->getchannels;
847 my $out = Imager->new;
848 if ($channels == $self->getchannels) {
849 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
852 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
854 unless ($out->{IMG}) {
855 $self->{ERRSTR} = $self->_error_as_msg;
862 # Sets an image to a certain size and channel number
863 # if there was previously data in the image it is discarded
868 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
870 if (defined($self->{IMG})) {
871 # let IIM_DESTROY destroy it, it's possible this image is
872 # referenced from a virtual image (like masked)
873 #i_img_destroy($self->{IMG});
877 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
878 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
879 $hsh{maxcolors} || 256);
881 elsif ($hsh{bits} eq 'double') {
882 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
884 elsif ($hsh{bits} == 16) {
885 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
888 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
892 unless ($self->{IMG}) {
893 $self->{ERRSTR} = Imager->_error_as_msg();
900 # created a masked version of the current image
904 $self or return undef;
905 my %opts = (left => 0,
907 right => $self->getwidth,
908 bottom => $self->getheight,
910 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
912 my $result = Imager->new;
913 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
914 $opts{top}, $opts{right} - $opts{left},
915 $opts{bottom} - $opts{top});
916 # keep references to the mask and base images so they don't
918 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
923 # convert an RGB image into a paletted image
927 if (@_ != 1 && !ref $_[0]) {
934 unless (defined wantarray) {
936 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
940 my $result = Imager->new;
941 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
943 #print "Type ", i_img_type($result->{IMG}), "\n";
945 if ($result->{IMG}) {
949 $self->{ERRSTR} = $self->_error_as_msg;
954 # convert a paletted (or any image) to an 8-bit/channel RGB images
959 unless (defined wantarray) {
961 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
966 $result = Imager->new;
967 $result->{IMG} = i_img_to_rgb($self->{IMG})
974 # convert a paletted (or any image) to an 8-bit/channel RGB images
979 unless (defined wantarray) {
981 warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
986 $result = Imager->new;
987 $result->{IMG} = i_img_to_rgb16($self->{IMG})
996 my %opts = (colors=>[], @_);
998 unless ($self->{IMG}) {
999 $self->_set_error("empty input image");
1003 my @colors = @{$opts{colors}}
1006 for my $color (@colors) {
1007 $color = _color($color);
1009 $self->_set_error($Imager::ERRSTR);
1014 return i_addcolors($self->{IMG}, @colors);
1019 my %opts = (start=>0, colors=>[], @_);
1021 unless ($self->{IMG}) {
1022 $self->_set_error("empty input image");
1026 my @colors = @{$opts{colors}}
1029 for my $color (@colors) {
1030 $color = _color($color);
1032 $self->_set_error($Imager::ERRSTR);
1037 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1043 if (!exists $opts{start} && !exists $opts{count}) {
1046 $opts{count} = $self->colorcount;
1048 elsif (!exists $opts{count}) {
1051 elsif (!exists $opts{start}) {
1056 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1060 i_colorcount($_[0]{IMG});
1064 i_maxcolors($_[0]{IMG});
1070 $opts{color} or return undef;
1072 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1077 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1078 if ($bits && $bits == length(pack("d", 1)) * 8) {
1087 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1093 $self->{IMG} and i_img_virtual($self->{IMG});
1099 $self->{IMG} or return;
1101 return i_img_is_monochrome($self->{IMG});
1105 my ($self, %opts) = @_;
1107 $self->{IMG} or return;
1109 if (defined $opts{name}) {
1113 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1114 push @result, (i_tags_get($self->{IMG}, $found))[1];
1117 return wantarray ? @result : $result[0];
1119 elsif (defined $opts{code}) {
1123 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1124 push @result, (i_tags_get($self->{IMG}, $found))[1];
1131 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1134 return i_tags_count($self->{IMG});
1143 return -1 unless $self->{IMG};
1145 if (defined $opts{value}) {
1146 if ($opts{value} =~ /^\d+$/) {
1148 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1151 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1154 elsif (defined $opts{data}) {
1155 # force addition as a string
1156 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1159 $self->{ERRSTR} = "No value supplied";
1163 elsif ($opts{code}) {
1164 if (defined $opts{value}) {
1165 if ($opts{value} =~ /^\d+$/) {
1167 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1170 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1173 elsif (defined $opts{data}) {
1174 # force addition as a string
1175 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1178 $self->{ERRSTR} = "No value supplied";
1191 return 0 unless $self->{IMG};
1193 if (defined $opts{'index'}) {
1194 return i_tags_delete($self->{IMG}, $opts{'index'});
1196 elsif (defined $opts{name}) {
1197 return i_tags_delbyname($self->{IMG}, $opts{name});
1199 elsif (defined $opts{code}) {
1200 return i_tags_delbycode($self->{IMG}, $opts{code});
1203 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1209 my ($self, %opts) = @_;
1212 $self->deltag(name=>$opts{name});
1213 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1215 elsif (defined $opts{code}) {
1216 $self->deltag(code=>$opts{code});
1217 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1225 sub _get_reader_io {
1226 my ($self, $input) = @_;
1229 return $input->{io}, undef;
1231 elsif ($input->{fd}) {
1232 return io_new_fd($input->{fd});
1234 elsif ($input->{fh}) {
1235 my $fd = fileno($input->{fh});
1236 unless (defined $fd) {
1237 $self->_set_error("Handle in fh option not opened");
1240 return io_new_fd($fd);
1242 elsif ($input->{file}) {
1243 my $file = IO::File->new($input->{file}, "r");
1245 $self->_set_error("Could not open $input->{file}: $!");
1249 return (io_new_fd(fileno($file)), $file);
1251 elsif ($input->{data}) {
1252 return io_new_buffer($input->{data});
1254 elsif ($input->{callback} || $input->{readcb}) {
1255 if (!$input->{seekcb}) {
1256 $self->_set_error("Need a seekcb parameter");
1258 if ($input->{maxbuffer}) {
1259 return io_new_cb($input->{writecb},
1260 $input->{callback} || $input->{readcb},
1261 $input->{seekcb}, $input->{closecb},
1262 $input->{maxbuffer});
1265 return io_new_cb($input->{writecb},
1266 $input->{callback} || $input->{readcb},
1267 $input->{seekcb}, $input->{closecb});
1271 $self->_set_error("file/fd/fh/data/callback parameter missing");
1276 sub _get_writer_io {
1277 my ($self, $input, $type) = @_;
1280 return $input->{io};
1282 elsif ($input->{fd}) {
1283 return io_new_fd($input->{fd});
1285 elsif ($input->{fh}) {
1286 my $fd = fileno($input->{fh});
1287 unless (defined $fd) {
1288 $self->_set_error("Handle in fh option not opened");
1292 my $oldfh = select($input->{fh});
1293 # flush anything that's buffered, and make sure anything else is flushed
1296 return io_new_fd($fd);
1298 elsif ($input->{file}) {
1299 my $fh = new IO::File($input->{file},"w+");
1301 $self->_set_error("Could not open file $input->{file}: $!");
1304 binmode($fh) or die;
1305 return (io_new_fd(fileno($fh)), $fh);
1307 elsif ($input->{data}) {
1308 return io_new_bufchain();
1310 elsif ($input->{callback} || $input->{writecb}) {
1311 if ($input->{maxbuffer}) {
1312 return io_new_cb($input->{callback} || $input->{writecb},
1314 $input->{seekcb}, $input->{closecb},
1315 $input->{maxbuffer});
1318 return io_new_cb($input->{callback} || $input->{writecb},
1320 $input->{seekcb}, $input->{closecb});
1324 $self->_set_error("file/fd/fh/data/callback parameter missing");
1329 # Read an image from file
1335 if (defined($self->{IMG})) {
1336 # let IIM_DESTROY do the destruction, since the image may be
1337 # referenced from elsewhere
1338 #i_img_destroy($self->{IMG});
1339 undef($self->{IMG});
1342 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1344 unless ($input{'type'}) {
1345 $input{'type'} = i_test_format_probe($IO, -1);
1348 unless ($input{'type'}) {
1349 $self->_set_error('type parameter missing and not possible to guess from extension');
1353 _reader_autoload($input{type});
1355 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1356 return $readers{$input{type}}{single}->($self, $IO, %input);
1359 unless ($formats_low{$input{'type'}}) {
1360 my $read_types = join ', ', sort Imager->read_types();
1361 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1365 my $allow_incomplete = $input{allow_incomplete};
1366 defined $allow_incomplete or $allow_incomplete = 0;
1368 if ( $input{'type'} eq 'pnm' ) {
1369 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1370 if ( !defined($self->{IMG}) ) {
1371 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1374 $self->{DEBUG} && print "loading a pnm file\n";
1378 if ( $input{'type'} eq 'bmp' ) {
1379 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1380 if ( !defined($self->{IMG}) ) {
1381 $self->{ERRSTR}=$self->_error_as_msg();
1384 $self->{DEBUG} && print "loading a bmp file\n";
1387 if ( $input{'type'} eq 'gif' ) {
1388 if ($input{colors} && !ref($input{colors})) {
1389 # must be a reference to a scalar that accepts the colour map
1390 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1393 if ($input{'gif_consolidate'}) {
1394 if ($input{colors}) {
1396 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1398 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1402 $self->{IMG} =i_readgif_wiol( $IO );
1406 my $page = $input{'page'};
1407 defined $page or $page = 0;
1408 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1409 if ($self->{IMG} && $input{colors}) {
1410 ${ $input{colors} } =
1411 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1415 if ( !defined($self->{IMG}) ) {
1416 $self->{ERRSTR}=$self->_error_as_msg();
1419 $self->{DEBUG} && print "loading a gif file\n";
1422 if ( $input{'type'} eq 'tga' ) {
1423 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1424 if ( !defined($self->{IMG}) ) {
1425 $self->{ERRSTR}=$self->_error_as_msg();
1428 $self->{DEBUG} && print "loading a tga file\n";
1431 if ( $input{'type'} eq 'raw' ) {
1432 unless ( $input{xsize} && $input{ysize} ) {
1433 $self->_set_error('missing xsize or ysize parameter for raw');
1437 my $interleave = _first($input{raw_interleave}, $input{interleave});
1438 unless (defined $interleave) {
1439 my @caller = caller;
1440 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1443 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1444 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1446 $self->{IMG} = i_readraw_wiol( $IO,
1452 if ( !defined($self->{IMG}) ) {
1453 $self->{ERRSTR}=$self->_error_as_msg();
1456 $self->{DEBUG} && print "loading a raw file\n";
1462 sub register_reader {
1463 my ($class, %opts) = @_;
1466 or die "register_reader called with no type parameter\n";
1468 my $type = $opts{type};
1470 defined $opts{single} || defined $opts{multiple}
1471 or die "register_reader called with no single or multiple parameter\n";
1473 $readers{$type} = { };
1474 if ($opts{single}) {
1475 $readers{$type}{single} = $opts{single};
1477 if ($opts{multiple}) {
1478 $readers{$type}{multiple} = $opts{multiple};
1484 sub register_writer {
1485 my ($class, %opts) = @_;
1488 or die "register_writer called with no type parameter\n";
1490 my $type = $opts{type};
1492 defined $opts{single} || defined $opts{multiple}
1493 or die "register_writer called with no single or multiple parameter\n";
1495 $writers{$type} = { };
1496 if ($opts{single}) {
1497 $writers{$type}{single} = $opts{single};
1499 if ($opts{multiple}) {
1500 $writers{$type}{multiple} = $opts{multiple};
1511 grep($file_formats{$_}, keys %formats),
1512 qw(ico sgi), # formats not handled directly, but supplied with Imager
1523 grep($file_formats{$_}, keys %formats),
1524 qw(ico sgi), # formats not handled directly, but supplied with Imager
1530 # probes for an Imager::File::whatever module
1531 sub _reader_autoload {
1534 return if $formats_low{$type} || $readers{$type};
1536 return unless $type =~ /^\w+$/;
1538 my $file = "Imager/File/\U$type\E.pm";
1540 unless ($attempted_to_load{$file}) {
1542 ++$attempted_to_load{$file};
1546 # try to get a reader specific module
1547 my $file = "Imager/File/\U$type\EReader.pm";
1548 unless ($attempted_to_load{$file}) {
1550 ++$attempted_to_load{$file};
1558 # probes for an Imager::File::whatever module
1559 sub _writer_autoload {
1562 return if $formats_low{$type} || $readers{$type};
1564 return unless $type =~ /^\w+$/;
1566 my $file = "Imager/File/\U$type\E.pm";
1568 unless ($attempted_to_load{$file}) {
1570 ++$attempted_to_load{$file};
1574 # try to get a writer specific module
1575 my $file = "Imager/File/\U$type\EWriter.pm";
1576 unless ($attempted_to_load{$file}) {
1578 ++$attempted_to_load{$file};
1586 sub _fix_gif_positions {
1587 my ($opts, $opt, $msg, @imgs) = @_;
1589 my $positions = $opts->{'gif_positions'};
1591 for my $pos (@$positions) {
1592 my ($x, $y) = @$pos;
1593 my $img = $imgs[$index++];
1594 $img->settag(name=>'gif_left', value=>$x);
1595 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1597 $$msg .= "replaced with the gif_left and gif_top tags";
1602 gif_each_palette=>'gif_local_map',
1603 interlace => 'gif_interlace',
1604 gif_delays => 'gif_delay',
1605 gif_positions => \&_fix_gif_positions,
1606 gif_loop_count => 'gif_loop',
1609 # options that should be converted to colors
1610 my %color_opts = map { $_ => 1 } qw/i_background/;
1613 my ($self, $opts, $prefix, @imgs) = @_;
1615 for my $opt (keys %$opts) {
1617 if ($obsolete_opts{$opt}) {
1618 my $new = $obsolete_opts{$opt};
1619 my $msg = "Obsolete option $opt ";
1621 $new->($opts, $opt, \$msg, @imgs);
1624 $msg .= "replaced with the $new tag ";
1627 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1628 warn $msg if $warn_obsolete && $^W;
1630 next unless $tagname =~ /^\Q$prefix/;
1631 my $value = $opts->{$opt};
1632 if ($color_opts{$opt}) {
1633 $value = _color($value);
1635 $self->_set_error($Imager::ERRSTR);
1640 if (UNIVERSAL::isa($value, "Imager::Color")) {
1641 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1642 for my $img (@imgs) {
1643 $img->settag(name=>$tagname, value=>$tag);
1646 elsif (ref($value) eq 'ARRAY') {
1647 for my $i (0..$#$value) {
1648 my $val = $value->[$i];
1650 if (UNIVERSAL::isa($val, "Imager::Color")) {
1651 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1653 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1656 $self->_set_error("Unknown reference type " . ref($value) .
1657 " supplied in array for $opt");
1663 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1668 $self->_set_error("Unknown reference type " . ref($value) .
1669 " supplied for $opt");
1674 # set it as a tag for every image
1675 for my $img (@imgs) {
1676 $img->settag(name=>$tagname, value=>$value);
1684 # Write an image to file
1687 my %input=(jpegquality=>75,
1697 $self->_set_opts(\%input, "i_", $self)
1700 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1702 if (!$input{'type'} and $input{file}) {
1703 $input{'type'}=$FORMATGUESS->($input{file});
1705 if (!$input{'type'}) {
1706 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1710 _writer_autoload($input{type});
1713 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1714 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1717 $writers{$input{type}}{single}->($self, $IO, %input)
1721 if (!$formats_low{$input{'type'}}) {
1722 my $write_types = join ', ', sort Imager->write_types();
1723 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1727 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1730 if ( $input{'type'} eq 'pnm' ) {
1731 $self->_set_opts(\%input, "pnm_", $self)
1733 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1734 $self->{ERRSTR} = $self->_error_as_msg();
1737 $self->{DEBUG} && print "writing a pnm file\n";
1738 } elsif ( $input{'type'} eq 'raw' ) {
1739 $self->_set_opts(\%input, "raw_", $self)
1741 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1742 $self->{ERRSTR} = $self->_error_as_msg();
1745 $self->{DEBUG} && print "writing a raw file\n";
1746 } elsif ( $input{'type'} eq 'jpeg' ) {
1747 $self->_set_opts(\%input, "jpeg_", $self)
1749 $self->_set_opts(\%input, "exif_", $self)
1751 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1752 $self->{ERRSTR} = $self->_error_as_msg();
1755 $self->{DEBUG} && print "writing a jpeg file\n";
1756 } elsif ( $input{'type'} eq 'bmp' ) {
1757 $self->_set_opts(\%input, "bmp_", $self)
1759 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1760 $self->{ERRSTR} = $self->_error_as_msg;
1763 $self->{DEBUG} && print "writing a bmp file\n";
1764 } elsif ( $input{'type'} eq 'tga' ) {
1765 $self->_set_opts(\%input, "tga_", $self)
1768 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1769 $self->{ERRSTR}=$self->_error_as_msg();
1772 $self->{DEBUG} && print "writing a tga file\n";
1773 } elsif ( $input{'type'} eq 'gif' ) {
1774 $self->_set_opts(\%input, "gif_", $self)
1776 # compatibility with the old interfaces
1777 if ($input{gifquant} eq 'lm') {
1778 $input{make_colors} = 'addi';
1779 $input{translate} = 'perturb';
1780 $input{perturb} = $input{lmdither};
1781 } elsif ($input{gifquant} eq 'gen') {
1782 # just pass options through
1784 $input{make_colors} = 'webmap'; # ignored
1785 $input{translate} = 'giflib';
1787 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1788 $self->{ERRSTR} = $self->_error_as_msg;
1794 if (exists $input{'data'}) {
1795 my $data = io_slurp($IO);
1797 $self->{ERRSTR}='Could not slurp from buffer';
1800 ${$input{data}} = $data;
1806 my ($class, $opts, @images) = @_;
1808 my $type = $opts->{type};
1810 if (!$type && $opts->{'file'}) {
1811 $type = $FORMATGUESS->($opts->{'file'});
1814 $class->_set_error('type parameter missing and not possible to guess from extension');
1817 # translate to ImgRaw
1818 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1819 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1822 $class->_set_opts($opts, "i_", @images)
1824 my @work = map $_->{IMG}, @images;
1826 _writer_autoload($type);
1829 if ($writers{$type} && $writers{$type}{multiple}) {
1830 ($IO, $file) = $class->_get_writer_io($opts, $type)
1833 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1837 if (!$formats{$type}) {
1838 my $write_types = join ', ', sort Imager->write_types();
1839 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1843 ($IO, $file) = $class->_get_writer_io($opts, $type)
1846 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1850 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1855 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1861 if (exists $opts->{'data'}) {
1862 my $data = io_slurp($IO);
1864 Imager->_set_error('Could not slurp from buffer');
1867 ${$opts->{data}} = $data;
1872 # read multiple images from a file
1874 my ($class, %opts) = @_;
1876 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1879 my $type = $opts{'type'};
1881 $type = i_test_format_probe($IO, -1);
1884 if ($opts{file} && !$type) {
1886 $type = $FORMATGUESS->($opts{file});
1890 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1894 _reader_autoload($type);
1896 if ($readers{$type} && $readers{$type}{multiple}) {
1897 return $readers{$type}{multiple}->($IO, %opts);
1900 unless ($formats{$type}) {
1901 my $read_types = join ', ', sort Imager->read_types();
1902 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1907 if ($type eq 'pnm') {
1908 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1911 my $img = Imager->new;
1912 if ($img->read(%opts, io => $IO, type => $type)) {
1915 Imager->_set_error($img->errstr);
1920 $ERRSTR = _error_as_msg();
1924 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1928 # Destroy an Imager object
1932 # delete $instances{$self};
1933 if (defined($self->{IMG})) {
1934 # the following is now handled by the XS DESTROY method for
1935 # Imager::ImgRaw object
1936 # Re-enabling this will break virtual images
1937 # tested for in t/t020masked.t
1938 # i_img_destroy($self->{IMG});
1939 undef($self->{IMG});
1941 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1945 # Perform an inplace filter of an image
1946 # that is the image will be overwritten with the data
1952 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1954 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1956 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1957 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1960 if ($filters{$input{'type'}}{names}) {
1961 my $names = $filters{$input{'type'}}{names};
1962 for my $name (keys %$names) {
1963 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1964 $input{$name} = $names->{$name}{$input{$name}};
1968 if (defined($filters{$input{'type'}}{defaults})) {
1969 %hsh=( image => $self->{IMG},
1971 %{$filters{$input{'type'}}{defaults}},
1974 %hsh=( image => $self->{IMG},
1979 my @cs=@{$filters{$input{'type'}}{callseq}};
1982 if (!defined($hsh{$_})) {
1983 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1988 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1989 &{$filters{$input{'type'}}{callsub}}(%hsh);
1992 chomp($self->{ERRSTR} = $@);
1998 $self->{DEBUG} && print "callseq is: @cs\n";
1999 $self->{DEBUG} && print "matching callseq is: @b\n";
2004 sub register_filter {
2006 my %hsh = ( defaults => {}, @_ );
2009 or die "register_filter() with no type\n";
2010 defined $hsh{callsub}
2011 or die "register_filter() with no callsub\n";
2012 defined $hsh{callseq}
2013 or die "register_filter() with no callseq\n";
2015 exists $filters{$hsh{type}}
2018 $filters{$hsh{type}} = \%hsh;
2023 sub scale_calculate {
2026 my %opts = ('type'=>'max', @_);
2028 # none of these should be references
2029 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2030 if (defined $opts{$name} && ref $opts{$name}) {
2031 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2036 my ($x_scale, $y_scale);
2037 my $width = $opts{width};
2038 my $height = $opts{height};
2040 defined $width or $width = $self->getwidth;
2041 defined $height or $height = $self->getheight;
2044 unless (defined $width && defined $height) {
2045 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2050 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2051 $x_scale = $opts{'xscalefactor'};
2052 $y_scale = $opts{'yscalefactor'};
2054 elsif ($opts{'xscalefactor'}) {
2055 $x_scale = $opts{'xscalefactor'};
2056 $y_scale = $opts{'scalefactor'} || $x_scale;
2058 elsif ($opts{'yscalefactor'}) {
2059 $y_scale = $opts{'yscalefactor'};
2060 $x_scale = $opts{'scalefactor'} || $y_scale;
2063 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2066 # work out the scaling
2067 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2068 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2069 $opts{ypixels} / $height );
2070 if ($opts{'type'} eq 'min') {
2071 $x_scale = $y_scale = _min($xpix,$ypix);
2073 elsif ($opts{'type'} eq 'max') {
2074 $x_scale = $y_scale = _max($xpix,$ypix);
2076 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2081 $self->_set_error('invalid value for type parameter');
2084 } elsif ($opts{xpixels}) {
2085 $x_scale = $y_scale = $opts{xpixels} / $width;
2087 elsif ($opts{ypixels}) {
2088 $x_scale = $y_scale = $opts{ypixels}/$height;
2090 elsif ($opts{constrain} && ref $opts{constrain}
2091 && $opts{constrain}->can('constrain')) {
2092 # we've been passed an Image::Math::Constrain object or something
2093 # that looks like one
2095 (undef, undef, $scalefactor)
2096 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2097 unless ($scalefactor) {
2098 $self->_set_error('constrain method failed on constrain parameter');
2101 $x_scale = $y_scale = $scalefactor;
2104 my $new_width = int($x_scale * $width + 0.5);
2105 $new_width > 0 or $new_width = 1;
2106 my $new_height = int($y_scale * $height + 0.5);
2107 $new_height > 0 or $new_height = 1;
2109 return ($x_scale, $y_scale, $new_width, $new_height);
2113 # Scale an image to requested size and return the scaled version
2117 my %opts = (qtype=>'normal' ,@_);
2118 my $img = Imager->new();
2119 my $tmp = Imager->new();
2121 unless (defined wantarray) {
2122 my @caller = caller;
2123 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2127 unless ($self->{IMG}) {
2128 $self->_set_error('empty input image');
2132 my ($x_scale, $y_scale, $new_width, $new_height) =
2133 $self->scale_calculate(%opts)
2136 if ($opts{qtype} eq 'normal') {
2137 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2138 if ( !defined($tmp->{IMG}) ) {
2139 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2142 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2143 if ( !defined($img->{IMG}) ) {
2144 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2150 elsif ($opts{'qtype'} eq 'preview') {
2151 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2152 if ( !defined($img->{IMG}) ) {
2153 $self->{ERRSTR}='unable to scale image';
2158 elsif ($opts{'qtype'} eq 'mixing') {
2159 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2160 unless ($img->{IMG}) {
2161 $self->_set_error(Imager->_error_as_msg);
2167 $self->_set_error('invalid value for qtype parameter');
2172 # Scales only along the X axis
2176 my %opts = ( scalefactor=>0.5, @_ );
2178 unless (defined wantarray) {
2179 my @caller = caller;
2180 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2184 unless ($self->{IMG}) {
2185 $self->{ERRSTR} = 'empty input image';
2189 my $img = Imager->new();
2191 my $scalefactor = $opts{scalefactor};
2193 if ($opts{pixels}) {
2194 $scalefactor = $opts{pixels} / $self->getwidth();
2197 unless ($self->{IMG}) {
2198 $self->{ERRSTR}='empty input image';
2202 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2204 if ( !defined($img->{IMG}) ) {
2205 $self->{ERRSTR} = 'unable to scale image';
2212 # Scales only along the Y axis
2216 my %opts = ( scalefactor => 0.5, @_ );
2218 unless (defined wantarray) {
2219 my @caller = caller;
2220 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2224 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2226 my $img = Imager->new();
2228 my $scalefactor = $opts{scalefactor};
2230 if ($opts{pixels}) {
2231 $scalefactor = $opts{pixels} / $self->getheight();
2234 unless ($self->{IMG}) {
2235 $self->{ERRSTR} = 'empty input image';
2238 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2240 if ( !defined($img->{IMG}) ) {
2241 $self->{ERRSTR} = 'unable to scale image';
2248 # Transform returns a spatial transformation of the input image
2249 # this moves pixels to a new location in the returned image.
2250 # NOTE - should make a utility function to check transforms for
2255 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2257 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2259 # print Dumper(\%opts);
2262 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2264 eval ("use Affix::Infix2Postfix;");
2267 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2270 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2271 {op=>'-',trans=>'Sub'},
2272 {op=>'*',trans=>'Mult'},
2273 {op=>'/',trans=>'Div'},
2274 {op=>'-','type'=>'unary',trans=>'u-'},
2276 {op=>'func','type'=>'unary'}],
2277 'grouping'=>[qw( \( \) )],
2278 'func'=>[qw( sin cos )],
2283 @xt=$I2P->translate($opts{'xexpr'});
2284 @yt=$I2P->translate($opts{'yexpr'});
2286 $numre=$I2P->{'numre'};
2289 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2290 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2291 @{$opts{'parm'}}=@pt;
2294 # print Dumper(\%opts);
2296 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2297 $self->{ERRSTR}='transform: no xopcodes given.';
2301 @op=@{$opts{'xopcodes'}};
2303 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2304 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2307 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2313 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2314 $self->{ERRSTR}='transform: no yopcodes given.';
2318 @op=@{$opts{'yopcodes'}};
2320 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2321 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2324 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2329 if ( !exists $opts{'parm'}) {
2330 $self->{ERRSTR}='transform: no parameter arg given.';
2334 # print Dumper(\@ropx);
2335 # print Dumper(\@ropy);
2336 # print Dumper(\@ropy);
2338 my $img = Imager->new();
2339 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2340 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2346 my ($opts, @imgs) = @_;
2348 require "Imager/Expr.pm";
2350 $opts->{variables} = [ qw(x y) ];
2351 my ($width, $height) = @{$opts}{qw(width height)};
2353 $width ||= $imgs[0]->getwidth();
2354 $height ||= $imgs[0]->getheight();
2356 for my $img (@imgs) {
2357 $opts->{constants}{"w$img_num"} = $img->getwidth();
2358 $opts->{constants}{"h$img_num"} = $img->getheight();
2359 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2360 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2365 $opts->{constants}{w} = $width;
2366 $opts->{constants}{cx} = $width/2;
2369 $Imager::ERRSTR = "No width supplied";
2373 $opts->{constants}{h} = $height;
2374 $opts->{constants}{cy} = $height/2;
2377 $Imager::ERRSTR = "No height supplied";
2380 my $code = Imager::Expr->new($opts);
2382 $Imager::ERRSTR = Imager::Expr::error();
2385 my $channels = $opts->{channels} || 3;
2386 unless ($channels >= 1 && $channels <= 4) {
2387 return Imager->_set_error("channels must be an integer between 1 and 4");
2390 my $img = Imager->new();
2391 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2392 $channels, $code->code(),
2393 $code->nregs(), $code->cregs(),
2394 [ map { $_->{IMG} } @imgs ]);
2395 if (!defined $img->{IMG}) {
2396 $Imager::ERRSTR = Imager->_error_as_msg();
2407 unless ($self->{IMG}) {
2408 $self->{ERRSTR}='empty input image';
2411 unless ($opts{src} && $opts{src}->{IMG}) {
2412 $self->{ERRSTR}='empty input image for src';
2416 %opts = (src_minx => 0,
2418 src_maxx => $opts{src}->getwidth(),
2419 src_maxy => $opts{src}->getheight(),
2423 defined $tx or $tx = $opts{left};
2424 defined $tx or $tx = 0;
2427 defined $ty or $ty = $opts{top};
2428 defined $ty or $ty = 0;
2430 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2431 $opts{src_minx}, $opts{src_miny},
2432 $opts{src_maxx}, $opts{src_maxy})) {
2433 $self->_set_error($self->_error_as_msg());
2450 unless ($self->{IMG}) {
2451 $self->_set_error("compose: empty input image");
2455 unless ($opts{src}) {
2456 $self->_set_error("compose: src parameter missing");
2460 unless ($opts{src}{IMG}) {
2461 $self->_set_error("compose: src parameter empty image");
2464 my $src = $opts{src};
2466 my $left = $opts{left};
2467 defined $left or $left = $opts{tx};
2468 defined $left or $left = 0;
2470 my $top = $opts{top};
2471 defined $top or $top = $opts{ty};
2472 defined $top or $top = 0;
2474 my $src_left = $opts{src_left};
2475 defined $src_left or $src_left = $opts{src_minx};
2476 defined $src_left or $src_left = 0;
2478 my $src_top = $opts{src_top};
2479 defined $src_top or $src_top = $opts{src_miny};
2480 defined $src_top or $src_top = 0;
2482 my $width = $opts{width};
2483 if (!defined $width && defined $opts{src_maxx}) {
2484 $width = $opts{src_maxx} - $src_left;
2486 defined $width or $width = $src->getwidth() - $src_left;
2488 my $height = $opts{height};
2489 if (!defined $height && defined $opts{src_maxy}) {
2490 $height = $opts{src_maxy} - $src_top;
2492 defined $height or $height = $src->getheight() - $src_top;
2494 my $combine = $self->_combine($opts{combine}, 'normal');
2497 unless ($opts{mask}{IMG}) {
2498 $self->_set_error("compose: mask parameter empty image");
2502 my $mask_left = $opts{mask_left};
2503 defined $mask_left or $mask_left = $opts{mask_minx};
2504 defined $mask_left or $mask_left = 0;
2506 my $mask_top = $opts{mask_top};
2507 defined $mask_top or $mask_top = $opts{mask_miny};
2508 defined $mask_top or $mask_top = 0;
2510 i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2511 $left, $top, $src_left, $src_top,
2512 $mask_left, $mask_top, $width, $height,
2513 $combine, $opts{opacity})
2517 i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2518 $width, $height, $combine, $opts{opacity})
2528 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2530 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2531 $dir = $xlate{$opts{'dir'}};
2532 return $self if i_flipxy($self->{IMG}, $dir);
2540 unless (defined wantarray) {
2541 my @caller = caller;
2542 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2546 if (defined $opts{right}) {
2547 my $degrees = $opts{right};
2549 $degrees += 360 * int(((-$degrees)+360)/360);
2551 $degrees = $degrees % 360;
2552 if ($degrees == 0) {
2553 return $self->copy();
2555 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2556 my $result = Imager->new();
2557 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2561 $self->{ERRSTR} = $self->_error_as_msg();
2566 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2570 elsif (defined $opts{radians} || defined $opts{degrees}) {
2571 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2573 my $back = $opts{back};
2574 my $result = Imager->new;
2576 $back = _color($back);
2578 $self->_set_error(Imager->errstr);
2582 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2585 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2587 if ($result->{IMG}) {
2591 $self->{ERRSTR} = $self->_error_as_msg();
2596 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2601 sub matrix_transform {
2605 unless (defined wantarray) {
2606 my @caller = caller;
2607 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2611 if ($opts{matrix}) {
2612 my $xsize = $opts{xsize} || $self->getwidth;
2613 my $ysize = $opts{ysize} || $self->getheight;
2615 my $result = Imager->new;
2617 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2618 $opts{matrix}, $opts{back})
2622 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2630 $self->{ERRSTR} = "matrix parameter required";
2636 *yatf = \&matrix_transform;
2638 # These two are supported for legacy code only
2641 return Imager::Color->new(@_);
2645 return Imager::Color::set(@_);
2648 # Draws a box between the specified corner points.
2651 my $raw = $self->{IMG};
2654 $self->{ERRSTR}='empty input image';
2660 my ($xmin, $ymin, $xmax, $ymax);
2661 if (exists $opts{'box'}) {
2662 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2663 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2664 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2665 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2668 defined($xmin = $opts{xmin}) or $xmin = 0;
2669 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2670 defined($ymin = $opts{ymin}) or $ymin = 0;
2671 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2674 if ($opts{filled}) {
2675 my $color = $opts{'color'};
2677 if (defined $color) {
2678 unless (_is_color_object($color)) {
2679 $color = _color($color);
2681 $self->{ERRSTR} = $Imager::ERRSTR;
2687 $color = i_color_new(255,255,255,255);
2690 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2692 elsif ($opts{fill}) {
2693 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2694 # assume it's a hash ref
2695 require 'Imager/Fill.pm';
2696 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2697 $self->{ERRSTR} = $Imager::ERRSTR;
2701 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2704 my $color = $opts{'color'};
2705 if (defined $color) {
2706 unless (_is_color_object($color)) {
2707 $color = _color($color);
2709 $self->{ERRSTR} = $Imager::ERRSTR;
2715 $color = i_color_new(255, 255, 255, 255);
2718 $self->{ERRSTR} = $Imager::ERRSTR;
2721 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2729 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2730 my $dflcl= [ 255, 255, 255, 255];
2735 'r'=>_min($self->getwidth(),$self->getheight())/3,
2736 'x'=>$self->getwidth()/2,
2737 'y'=>$self->getheight()/2,
2744 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2745 # assume it's a hash ref
2746 require 'Imager/Fill.pm';
2747 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2748 $self->{ERRSTR} = $Imager::ERRSTR;
2752 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2753 $opts{'d2'}, $opts{fill}{fill});
2755 elsif ($opts{filled}) {
2756 my $color = _color($opts{'color'});
2758 $self->{ERRSTR} = $Imager::ERRSTR;
2761 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2762 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2766 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2767 $opts{'d1'}, $opts{'d2'}, $color);
2771 my $color = _color($opts{'color'});
2772 if ($opts{d2} - $opts{d1} >= 360) {
2773 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2776 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2782 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2783 # assume it's a hash ref
2784 require 'Imager/Fill.pm';
2785 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2786 $self->{ERRSTR} = $Imager::ERRSTR;
2790 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2791 $opts{'d2'}, $opts{fill}{fill});
2794 my $color = _color($opts{'color'});
2796 $self->{ERRSTR} = $Imager::ERRSTR;
2799 if ($opts{filled}) {
2800 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2801 $opts{'d1'}, $opts{'d2'}, $color);
2804 if ($opts{d1} == 0 && $opts{d2} == 361) {
2805 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2808 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2814 $self->_set_error($self->_error_as_msg);
2821 # Draws a line from one point to the other
2822 # the endpoint is set if the endp parameter is set which it is by default.
2823 # to turn of the endpoint being set use endp=>0 when calling line.
2827 my $dflcl=i_color_new(0,0,0,0);
2828 my %opts=(color=>$dflcl,
2831 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2833 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2834 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2836 my $color = _color($opts{'color'});
2838 $self->{ERRSTR} = $Imager::ERRSTR;
2842 $opts{antialias} = $opts{aa} if defined $opts{aa};
2843 if ($opts{antialias}) {
2844 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2845 $color, $opts{endp});
2847 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2848 $color, $opts{endp});
2853 # Draws a line between an ordered set of points - It more or less just transforms this
2854 # into a list of lines.
2858 my ($pt,$ls,@points);
2859 my $dflcl=i_color_new(0,0,0,0);
2860 my %opts=(color=>$dflcl,@_);
2862 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2864 if (exists($opts{points})) { @points=@{$opts{points}}; }
2865 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2866 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2869 # print Dumper(\@points);
2871 my $color = _color($opts{'color'});
2873 $self->{ERRSTR} = $Imager::ERRSTR;
2876 $opts{antialias} = $opts{aa} if defined $opts{aa};
2877 if ($opts{antialias}) {
2880 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2887 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2897 my ($pt,$ls,@points);
2898 my $dflcl = i_color_new(0,0,0,0);
2899 my %opts = (color=>$dflcl, @_);
2901 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2903 if (exists($opts{points})) {
2904 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2905 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2908 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2909 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2912 if ($opts{'fill'}) {
2913 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2914 # assume it's a hash ref
2915 require 'Imager/Fill.pm';
2916 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2917 $self->{ERRSTR} = $Imager::ERRSTR;
2921 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2922 $opts{'fill'}{'fill'});
2925 my $color = _color($opts{'color'});
2927 $self->{ERRSTR} = $Imager::ERRSTR;
2930 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2937 # this the multipoint bezier curve
2938 # this is here more for testing that actual usage since
2939 # this is not a good algorithm. Usually the curve would be
2940 # broken into smaller segments and each done individually.
2944 my ($pt,$ls,@points);
2945 my $dflcl=i_color_new(0,0,0,0);
2946 my %opts=(color=>$dflcl,@_);
2948 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2950 if (exists $opts{points}) {
2951 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2952 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2955 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2956 $self->{ERRSTR}='Missing or invalid points.';
2960 my $color = _color($opts{'color'});
2962 $self->{ERRSTR} = $Imager::ERRSTR;
2965 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2971 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2974 unless (exists $opts{'x'} && exists $opts{'y'}) {
2975 $self->{ERRSTR} = "missing seed x and y parameters";
2979 if ($opts{border}) {
2980 my $border = _color($opts{border});
2982 $self->_set_error($Imager::ERRSTR);
2986 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2987 # assume it's a hash ref
2988 require Imager::Fill;
2989 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2990 $self->{ERRSTR} = $Imager::ERRSTR;
2994 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2995 $opts{fill}{fill}, $border);
2998 my $color = _color($opts{'color'});
3000 $self->{ERRSTR} = $Imager::ERRSTR;
3003 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3010 $self->{ERRSTR} = $self->_error_as_msg();
3016 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3017 # assume it's a hash ref
3018 require 'Imager/Fill.pm';
3019 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3020 $self->{ERRSTR} = $Imager::ERRSTR;
3024 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3027 my $color = _color($opts{'color'});
3029 $self->{ERRSTR} = $Imager::ERRSTR;
3032 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3038 $self->{ERRSTR} = $self->_error_as_msg();
3045 my ($self, %opts) = @_;
3047 my $color = $opts{color};
3048 unless (defined $color) {
3049 $color = $self->{fg};
3050 defined $color or $color = NC(255, 255, 255);
3053 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3054 $color = _color($color)
3058 unless (exists $opts{'x'} && exists $opts{'y'}) {
3059 $self->{ERRSTR} = 'missing x and y parameters';
3065 if (ref $x && ref $y) {
3066 unless (@$x == @$y) {
3067 $self->{ERRSTR} = 'length of x and y mismatch';
3071 if ($color->isa('Imager::Color')) {
3072 for my $i (0..$#{$opts{'x'}}) {
3073 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3078 for my $i (0..$#{$opts{'x'}}) {
3079 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3087 if ($color->isa('Imager::Color')) {
3088 i_ppix($self->{IMG}, $x, $y, $color)
3092 i_ppixf($self->{IMG}, $x, $y, $color)
3103 my %opts = ( "type"=>'8bit', @_);
3105 unless (exists $opts{'x'} && exists $opts{'y'}) {
3106 $self->{ERRSTR} = 'missing x and y parameters';
3112 if (ref $x && ref $y) {
3113 unless (@$x == @$y) {
3114 $self->{ERRSTR} = 'length of x and y mismatch';
3118 if ($opts{"type"} eq '8bit') {
3119 for my $i (0..$#{$opts{'x'}}) {
3120 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3124 for my $i (0..$#{$opts{'x'}}) {
3125 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3128 return wantarray ? @result : \@result;
3131 if ($opts{"type"} eq '8bit') {
3132 return i_get_pixel($self->{IMG}, $x, $y);
3135 return i_gpixf($self->{IMG}, $x, $y);
3144 my %opts = ( type => '8bit', x=>0, @_);
3146 $self->_valid_image or return;
3148 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3150 unless (defined $opts{'y'}) {
3151 $self->_set_error("missing y parameter");
3155 if ($opts{type} eq '8bit') {
3156 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3159 elsif ($opts{type} eq 'float') {
3160 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3163 elsif ($opts{type} eq 'index') {
3164 unless (i_img_type($self->{IMG})) {
3165 $self->_set_error("type => index only valid on paletted images");
3168 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3172 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3179 my %opts = ( x=>0, @_);
3181 $self->_valid_image or return;
3183 unless (defined $opts{'y'}) {
3184 $self->_set_error("missing y parameter");
3189 if (ref $opts{pixels} && @{$opts{pixels}}) {
3190 # try to guess the type
3191 if ($opts{pixels}[0]->isa('Imager::Color')) {
3192 $opts{type} = '8bit';
3194 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3195 $opts{type} = 'float';
3198 $self->_set_error("missing type parameter and could not guess from pixels");
3204 $opts{type} = '8bit';
3208 if ($opts{type} eq '8bit') {
3209 if (ref $opts{pixels}) {
3210 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3213 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3216 elsif ($opts{type} eq 'float') {
3217 if (ref $opts{pixels}) {
3218 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3221 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3224 elsif ($opts{type} eq 'index') {
3225 if (ref $opts{pixels}) {
3226 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3229 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3233 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3240 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3242 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3244 unless (defined $opts{'y'}) {
3245 $self->_set_error("missing y parameter");
3249 unless ($opts{channels}) {
3250 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3253 if ($opts{target}) {
3254 my $target = $opts{target};
3255 my $offset = $opts{offset};
3256 if ($opts{type} eq '8bit') {
3257 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3258 $opts{y}, @{$opts{channels}})
3260 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3261 return scalar(@samples);
3263 elsif ($opts{type} eq 'float') {
3264 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3265 $opts{y}, @{$opts{channels}});
3266 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3267 return scalar(@samples);
3269 elsif ($opts{type} =~ /^(\d+)bit$/) {
3273 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3274 $opts{y}, $bits, $target,
3275 $offset, @{$opts{channels}});
3276 unless (defined $count) {
3277 $self->_set_error(Imager->_error_as_msg);
3284 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3289 if ($opts{type} eq '8bit') {
3290 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3291 $opts{y}, @{$opts{channels}});
3293 elsif ($opts{type} eq 'float') {
3294 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3295 $opts{y}, @{$opts{channels}});
3297 elsif ($opts{type} =~ /^(\d+)bit$/) {
3301 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3302 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3307 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3315 my %opts = ( x => 0, offset => 0, @_ );
3317 unless ($self->{IMG}) {
3318 $self->_set_error('setsamples: empty input image');
3322 unless(defined $opts{data} && ref $opts{data}) {
3323 $self->_set_error('setsamples: data parameter missing or invalid');
3327 unless ($opts{channels}) {
3328 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3331 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3332 $self->_set_error('setsamples: type parameter missing or invalid');
3337 unless (defined $opts{width}) {
3338 $opts{width} = $self->getwidth() - $opts{x};
3341 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3342 $opts{channels}, $opts{data}, $opts{offset},
3344 unless (defined $count) {
3345 $self->_set_error(Imager->_error_as_msg);
3352 # make an identity matrix of the given size
3356 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3357 for my $c (0 .. ($size-1)) {
3358 $matrix->[$c][$c] = 1;
3363 # general function to convert an image
3365 my ($self, %opts) = @_;
3368 unless (defined wantarray) {
3369 my @caller = caller;
3370 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3374 # the user can either specify a matrix or preset
3375 # the matrix overrides the preset
3376 if (!exists($opts{matrix})) {
3377 unless (exists($opts{preset})) {
3378 $self->{ERRSTR} = "convert() needs a matrix or preset";
3382 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3383 # convert to greyscale, keeping the alpha channel if any
3384 if ($self->getchannels == 3) {
3385 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3387 elsif ($self->getchannels == 4) {
3388 # preserve the alpha channel
3389 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3394 $matrix = _identity($self->getchannels);
3397 elsif ($opts{preset} eq 'noalpha') {
3398 # strip the alpha channel
3399 if ($self->getchannels == 2 or $self->getchannels == 4) {
3400 $matrix = _identity($self->getchannels);
3401 pop(@$matrix); # lose the alpha entry
3404 $matrix = _identity($self->getchannels);
3407 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3409 $matrix = [ [ 1 ] ];
3411 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3412 $matrix = [ [ 0, 1 ] ];
3414 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3415 $matrix = [ [ 0, 0, 1 ] ];
3417 elsif ($opts{preset} eq 'alpha') {
3418 if ($self->getchannels == 2 or $self->getchannels == 4) {
3419 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3422 # the alpha is just 1 <shrug>
3423 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3426 elsif ($opts{preset} eq 'rgb') {
3427 if ($self->getchannels == 1) {
3428 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3430 elsif ($self->getchannels == 2) {
3431 # preserve the alpha channel
3432 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3435 $matrix = _identity($self->getchannels);
3438 elsif ($opts{preset} eq 'addalpha') {
3439 if ($self->getchannels == 1) {
3440 $matrix = _identity(2);
3442 elsif ($self->getchannels == 3) {
3443 $matrix = _identity(4);
3446 $matrix = _identity($self->getchannels);
3450 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3456 $matrix = $opts{matrix};
3459 my $new = Imager->new;
3460 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3461 unless ($new->{IMG}) {
3462 # most likely a bad matrix
3463 $self->{ERRSTR} = _error_as_msg();
3470 # general function to map an image through lookup tables
3473 my ($self, %opts) = @_;
3474 my @chlist = qw( red green blue alpha );
3476 if (!exists($opts{'maps'})) {
3477 # make maps from channel maps
3479 for $chnum (0..$#chlist) {
3480 if (exists $opts{$chlist[$chnum]}) {
3481 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3482 } elsif (exists $opts{'all'}) {
3483 $opts{'maps'}[$chnum] = $opts{'all'};
3487 if ($opts{'maps'} and $self->{IMG}) {
3488 i_map($self->{IMG}, $opts{'maps'} );
3494 my ($self, %opts) = @_;
3496 defined $opts{mindist} or $opts{mindist} = 0;
3498 defined $opts{other}
3499 or return $self->_set_error("No 'other' parameter supplied");
3500 defined $opts{other}{IMG}
3501 or return $self->_set_error("No image data in 'other' image");
3504 or return $self->_set_error("No image data");
3506 my $result = Imager->new;
3507 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3509 or return $self->_set_error($self->_error_as_msg());
3514 # destructive border - image is shrunk by one pixel all around
3517 my ($self,%opts)=@_;
3518 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3519 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3523 # Get the width of an image
3528 if (my $raw = $self->{IMG}) {
3529 return i_img_get_width($raw);
3532 $self->{ERRSTR} = 'image is empty'; return undef;
3536 # Get the height of an image
3541 if (my $raw = $self->{IMG}) {
3542 return i_img_get_height($raw);
3545 $self->{ERRSTR} = 'image is empty'; return undef;
3549 # Get number of channels in an image
3553 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3554 return i_img_getchannels($self->{IMG});
3561 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3562 return i_img_getmask($self->{IMG});
3570 if (!defined($self->{IMG})) {
3571 $self->{ERRSTR} = 'image is empty';
3574 unless (defined $opts{mask}) {
3575 $self->_set_error("mask parameter required");
3578 i_img_setmask( $self->{IMG} , $opts{mask} );
3583 # Get number of colors in an image
3587 my %opts=('maxcolors'=>2**30,@_);
3588 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3589 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3590 return ($rc==-1? undef : $rc);
3593 # Returns a reference to a hash. The keys are colour named (packed) and the
3594 # values are the number of pixels in this colour.
3595 sub getcolorusagehash {
3598 my %opts = ( maxcolors => 2**30, @_ );
3599 my $max_colors = $opts{maxcolors};
3600 unless (defined $max_colors && $max_colors > 0) {
3601 $self->_set_error('maxcolors must be a positive integer');
3605 unless (defined $self->{IMG}) {
3606 $self->_set_error('empty input image');
3610 my $channels= $self->getchannels;
3611 # We don't want to look at the alpha channel, because some gifs using it
3612 # doesn't define it for every colour (but only for some)
3613 $channels -= 1 if $channels == 2 or $channels == 4;
3615 my $height = $self->getheight;
3616 for my $y (0 .. $height - 1) {
3617 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3618 while (length $colors) {
3619 $color_use{ substr($colors, 0, $channels, '') }++;
3621 keys %color_use > $max_colors
3627 # This will return a ordered array of the colour usage. Kind of the sorted
3628 # version of the values of the hash returned by getcolorusagehash.
3629 # You might want to add safety checks and change the names, etc...
3633 my %opts = ( maxcolors => 2**30, @_ );
3634 my $max_colors = $opts{maxcolors};
3635 unless (defined $max_colors && $max_colors > 0) {
3636 $self->_set_error('maxcolors must be a positive integer');
3640 unless (defined $self->{IMG}) {
3641 $self->_set_error('empty input image');
3645 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3648 # draw string to an image
3652 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3654 my %input=('x'=>0, 'y'=>0, @_);
3655 defined($input{string}) or $input{string} = $input{text};
3657 unless(defined $input{string}) {
3658 $self->{ERRSTR}="missing required parameter 'string'";
3662 unless($input{font}) {
3663 $self->{ERRSTR}="missing required parameter 'font'";
3667 unless ($input{font}->draw(image=>$self, %input)) {
3679 unless ($self->{IMG}) {
3680 $self->{ERRSTR}='empty input image';
3689 my %input=('x'=>0, 'y'=>0, @_);
3690 defined $input{string}
3691 or $input{string} = $input{text};
3693 unless(exists $input{string}) {
3694 $self->_set_error("missing required parameter 'string'");
3698 unless($input{font}) {
3699 $self->_set_error("missing required parameter 'font'");
3704 unless (@result = $input{font}->align(image=>$img, %input)) {
3708 return wantarray ? @result : $result[0];
3711 my @file_limit_names = qw/width height bytes/;
3713 sub set_file_limits {
3720 @values{@file_limit_names} = (0) x @file_limit_names;
3723 @values{@file_limit_names} = i_get_image_file_limits();
3726 for my $key (keys %values) {
3727 defined $opts{$key} and $values{$key} = $opts{$key};
3730 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3733 sub get_file_limits {
3734 i_get_image_file_limits();
3737 # Shortcuts that can be exported
3739 sub newcolor { Imager::Color->new(@_); }
3740 sub newfont { Imager::Font->new(@_); }
3742 require Imager::Color::Float;
3743 return Imager::Color::Float->new(@_);
3746 *NC=*newcolour=*newcolor;
3753 #### Utility routines
3756 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3760 my ($self, $msg) = @_;
3763 $self->{ERRSTR} = $msg;
3771 # Default guess for the type of an image from extension
3773 sub def_guess_type {
3776 $ext=($name =~ m/\.([^\.]+)$/)[0];
3777 return 'tiff' if ($ext =~ m/^tiff?$/);
3778 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3779 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3780 return 'png' if ($ext eq "png");
3781 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3782 return 'tga' if ($ext eq "tga");
3783 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3784 return 'gif' if ($ext eq "gif");
3785 return 'raw' if ($ext eq "raw");
3786 return lc $ext; # best guess
3791 return @combine_types;
3794 # get the minimum of a list
3798 for(@_) { if ($_<$mx) { $mx=$_; }}
3802 # get the maximum of a list
3806 for(@_) { if ($_>$mx) { $mx=$_; }}
3810 # string stuff for iptc headers
3814 $str = substr($str,3);
3815 $str =~ s/[\n\r]//g;
3822 # A little hack to parse iptc headers.
3827 my($caption,$photogr,$headln,$credit);
3829 my $str=$self->{IPTCRAW};
3834 @ar=split(/8BIM/,$str);
3839 @sar=split(/\034\002/);
3840 foreach $item (@sar) {
3841 if ($item =~ m/^x/) {
3842 $caption = _clean($item);
3845 if ($item =~ m/^P/) {
3846 $photogr = _clean($item);
3849 if ($item =~ m/^i/) {
3850 $headln = _clean($item);
3853 if ($item =~ m/^n/) {
3854 $credit = _clean($item);
3860 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3867 or die "Only C language supported";
3869 require Imager::ExtUtils;
3870 return Imager::ExtUtils->inline_config;
3873 # threads shouldn't try to close raw Imager objects
3874 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3876 # backward compatibility for %formats
3877 package Imager::FORMATS;
3879 use constant IX_FORMATS => 0;
3880 use constant IX_LIST => 1;
3881 use constant IX_INDEX => 2;
3882 use constant IX_CLASSES => 3;
3885 my ($class, $formats, $classes) = @_;
3887 return bless [ $formats, [ ], 0, $classes ], $class;
3891 my ($self, $key) = @_;
3893 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
3895 if (eval { require $file; 1 }) {
3901 $self->[IX_FORMATS]{$key} = $value;
3907 my ($self, $key) = @_;
3909 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
3911 $self->[IX_CLASSES]{$key} or return undef;
3913 return $self->_check($key);
3917 die "%Imager::formats is not user monifiable";
3921 die "%Imager::formats is not user monifiable";
3925 die "%Imager::formats is not user monifiable";
3929 my ($self, $key) = @_;
3931 if (exists $self->[IX_FORMATS]{$key}) {
3932 my $value = $self->[IX_FORMATS]{$key}
3937 $self->_check($key) or return 1==0;
3945 unless (@{$self->[IX_LIST]}) {
3947 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
3948 keys %{$self->[IX_FORMATS]};
3950 for my $key (keys %{$self->[IX_CLASSES]}) {
3951 $self->[IX_FORMATS]{$key} and next;
3953 and push @{$self->[IX_LIST]}, $key;
3957 @{$self->[IX_LIST]} or return;
3958 $self->[IX_INDEX] = 1;
3959 return $self->[IX_LIST][0];
3965 $self->[IX_INDEX] < @{$self->[IX_LIST]}
3968 return $self->[IX_LIST][$self->[IX_INDEX]++];
3974 return scalar @{$self->[IX_LIST]};
3979 # Below is the stub of documentation for your module. You better edit it!
3983 Imager - Perl extension for Generating 24 bit Images
3993 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3998 # see Imager::Files for information on the read() method
3999 my $im = Imager->new(file=>$file)
4000 or die Imager->errstr();
4002 $file =~ s/\.[^.]*$//;
4004 # Create smaller version
4005 # documented in Imager::Transformations
4006 my $thumb = $img->scale(scalefactor=>.3);
4008 # Autostretch individual channels
4009 $thumb->filter(type=>'autolevels');
4011 # try to save in one of these formats
4014 for $format ( qw( png gif jpeg tiff ppm ) ) {
4015 # Check if given format is supported
4016 if ($Imager::formats{$format}) {
4017 $file.="_low.$format";
4018 print "Storing image as: $file\n";
4019 # documented in Imager::Files
4020 $thumb->write(file=>$file) or
4028 Imager is a module for creating and altering images. It can read and
4029 write various image formats, draw primitive shapes like lines,and
4030 polygons, blend multiple images together in various ways, scale, crop,
4031 render text and more.
4033 =head2 Overview of documentation
4039 Imager - This document - Synopsis, Example, Table of Contents and
4044 L<Imager::Tutorial> - a brief introduction to Imager.
4048 L<Imager::Cookbook> - how to do various things with Imager.
4052 L<Imager::ImageTypes> - Basics of constructing image objects with
4053 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4054 8/16/double bits/channel, color maps, channel masks, image tags, color
4055 quantization. Also discusses basic image information methods.
4059 L<Imager::Files> - IO interaction, reading/writing images, format
4064 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4069 L<Imager::Color> - Color specification.
4073 L<Imager::Fill> - Fill pattern specification.
4077 L<Imager::Font> - General font rendering, bounding boxes and font
4082 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4083 blending, pasting, convert and map.
4087 L<Imager::Engines> - Programmable transformations through
4088 C<transform()>, C<transform2()> and C<matrix_transform()>.
4092 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4097 L<Imager::Expr> - Expressions for evaluation engine used by
4102 L<Imager::Matrix2d> - Helper class for affine transformations.
4106 L<Imager::Fountain> - Helper for making gradient profiles.
4110 L<Imager::API> - using Imager's C API
4114 L<Imager::APIRef> - API function reference
4118 L<Imager::Inline> - using Imager's C API from Inline::C
4122 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4126 =head2 Basic Overview
4128 An Image object is created with C<$img = Imager-E<gt>new()>.
4131 $img=Imager->new(); # create empty image
4132 $img->read(file=>'lena.png',type=>'png') or # read image from file
4133 die $img->errstr(); # give an explanation
4134 # if something failed
4136 or if you want to create an empty image:
4138 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4140 This example creates a completely black image of width 400 and height
4143 =head1 ERROR HANDLING
4145 In general a method will return false when it fails, if it does use
4146 the C<errstr()> method to find out why:
4152 Returns the last error message in that context.
4154 If the last error you received was from calling an object method, such
4155 as read, call errstr() as an object method to find out why:
4157 my $image = Imager->new;
4158 $image->read(file => 'somefile.gif')
4159 or die $image->errstr;
4161 If it was a class method then call errstr() as a class method:
4163 my @imgs = Imager->read_multi(file => 'somefile.gif')
4164 or die Imager->errstr;
4166 Note that in some cases object methods are implemented in terms of
4167 class methods so a failing object method may set both.
4171 The C<Imager-E<gt>new> method is described in detail in
4172 L<Imager::ImageTypes>.
4176 Where to find information on methods for Imager class objects.
4178 addcolors() - L<Imager::ImageTypes/addcolors> - add colors to a
4181 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4183 align_string() - L<Imager::Draw/align_string> - draw text aligned on a
4186 arc() - L<Imager::Draw/arc> - draw a filled arc
4188 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4191 box() - L<Imager::Draw/box> - draw a filled or outline box.
4193 circle() - L<Imager::Draw/circle> - draw a filled circle
4195 colorcount() - L<Imager::Draw/colorcount> - the number of colors in an
4196 image's palette (paletted images only)
4198 combines() - L<Imager::Draw/combines> - return a list of the different
4199 combine type keywords
4201 compose() - L<Imager::Transformations/compose> - compose one image
4204 convert() - L<Imager::Transformations/"Color transformations"> -
4205 transform the color space
4207 copy() - L<Imager::Transformations/copy> - make a duplicate of an
4210 crop() - L<Imager::Transformations/crop> - extract part of an image
4212 def_guess_type() - L<Imager::Files/def_guess_type> - default function
4213 used to guess the output file format based on the output file name
4215 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4217 difference() - L<Imager::Filters/"Image Difference"> - produce a
4218 difference images from two input images.
4220 errstr() - L<"Basic Overview"> - the error from the last failed
4223 filter() - L<Imager::Filters> - image filtering
4225 findcolor() - L<Imager::ImageTypes/findcolor> - search the image
4226 palette, if it has one
4228 flip() - L<Imager::Transformations/flip> - flip an image, vertically,
4231 flood_fill() - L<Imager::Draw/flood_fill> - fill an enclosed or same
4234 getchannels() - L<Imager::ImageTypes/getchannels> - the number of
4235 samples per pixel for an image
4237 getcolorcount() - L<Imager::ImageTypes/getcolorcount> - the number of
4238 different colors used by an image (works for direct color images)
4240 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4241 palette, if it has one
4243 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4245 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4247 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4249 getheight() - L<Imager::ImageTypes/getwidth> - height of the image in
4252 getmask() - L<Imager::ImageTypes/getmask> - write mask for the image
4254 getpixel() - L<Imager::Draw/getpixel> - retrieve one or more pixel
4257 getsamples() - L<Imager::Draw/getsamples> - retrieve samples from a
4258 row or partial row of pixels.
4260 getscanline() - L<Imager::Draw/getscanline> - retrieve colors for a
4261 row or partial row of pixels.
4263 getwidth() - L<Imager::ImageTypes/getwidth> - width of the image in
4266 img_set() - L<Imager::ImageTypes/img_set> - re-use an Imager object
4269 init() - L<Imager::ImageTypes/init>
4271 is_bilevel() - L<Imager::ImageTypes/is_bilevel> - returns whether
4272 image write functions should write the image in their bilevel (blank
4273 and white, no gray levels) format
4275 line() - L<Imager::Draw/line> - draw an interval
4277 load_plugin() - L<Imager::Filters/load_plugin>
4279 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4282 masked() - L<Imager::ImageTypes/masked> - make a masked image
4284 matrix_transform() - L<Imager::Engines/matrix_transform>
4286 maxcolors() - L<Imager::ImageTypes/maxcolors>
4288 NC() - L<Imager::Handy/NC>
4290 NCF() - L<Imager::Handy/NCF>
4292 new() - L<Imager::ImageTypes/new>
4294 newcolor() - L<Imager::Handy/newcolor>
4296 newcolour() - L<Imager::Handy/newcolour>
4298 newfont() - L<Imager::Handy/newfont>
4300 NF() - L<Imager::Handy/NF>
4302 open() - L<Imager::Files> - an alias for read()
4306 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4309 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4311 polygon() - L<Imager::Draw/polygon>
4313 polyline() - L<Imager::Draw/polyline>
4315 read() - L<Imager::Files> - read a single image from an image file
4317 read_multi() - L<Imager::Files> - read multiple images from an image
4320 read_types() - L<Imager::Files/read_types> - list image types Imager
4323 register_filter() - L<Imager::Filters/register_filter>
4325 register_reader() - L<Imager::Files/register_reader>
4327 register_writer() - L<Imager::Files/register_writer>
4329 rotate() - L<Imager::Transformations/rotate>
4331 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4332 image and use the alpha channel
4334 scale() - L<Imager::Transformations/scale>
4336 scale_calculate() - L<Imager::Transformations/scale_calculate>
4338 scaleX() - L<Imager::Transformations/scaleX>
4340 scaleY() - L<Imager::Transformations/scaleY>
4342 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4345 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4347 setmask() - L<Imager::ImageTypes/setmask>
4349 setpixel() - L<Imager::Draw/setpixel>
4351 setsamples() - L<Imager::Draw/setsamples>
4353 setscanline() - L<Imager::Draw/setscanline>
4355 settag() - L<Imager::ImageTypes/settag>
4357 string() - L<Imager::Draw/string> - draw text on an image
4359 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4361 to_paletted() - L<Imager::ImageTypes/to_paletted>
4363 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4365 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4367 transform() - L<Imager::Engines/"transform">
4369 transform2() - L<Imager::Engines/"transform2">
4371 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4373 unload_plugin() - L<Imager::Filters/unload_plugin>
4375 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4378 write() - L<Imager::Files> - write an image to a file
4380 write_multi() - L<Imager::Files> - write multiple image to an image
4383 write_types() - L<Imager::Files/read_types> - list image types Imager
4386 =head1 CONCEPT INDEX
4388 animated GIF - L<Imager::Files/"Writing an animated GIF">
4390 aspect ratio - L<Imager::ImageTypes/i_xres>,
4391 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4393 blend - alpha blending one image onto another
4394 L<Imager::Transformations/rubthrough>
4396 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4398 boxes, drawing - L<Imager::Draw/box>
4400 changes between image - L<Imager::Filters/"Image Difference">
4402 color - L<Imager::Color>
4404 color names - L<Imager::Color>, L<Imager::Color::Table>
4406 combine modes - L<Imager::Draw/"Combine Types">
4408 compare images - L<Imager::Filters/"Image Difference">
4410 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4412 convolution - L<Imager::Filters/conv>
4414 cropping - L<Imager::Transformations/crop>
4416 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4418 C<diff> images - L<Imager::Filters/"Image Difference">
4420 dpi - L<Imager::ImageTypes/i_xres>,
4421 L<Imager::Cookbook/"Image spatial resolution">
4423 drawing boxes - L<Imager::Draw/box>
4425 drawing lines - L<Imager::Draw/line>
4427 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4429 error message - L<"ERROR HANDLING">
4431 files, font - L<Imager::Font>
4433 files, image - L<Imager::Files>
4435 filling, types of fill - L<Imager::Fill>
4437 filling, boxes - L<Imager::Draw/box>
4439 filling, flood fill - L<Imager::Draw/flood_fill>
4441 flood fill - L<Imager::Draw/flood_fill>
4443 fonts - L<Imager::Font>
4445 fonts, drawing with - L<Imager::Draw/string>,
4446 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4448 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4450 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4452 fountain fill - L<Imager::Fill/"Fountain fills">,
4453 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4454 L<Imager::Filters/gradgen>
4456 GIF files - L<Imager::Files/"GIF">
4458 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4460 gradient fill - L<Imager::Fill/"Fountain fills">,
4461 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4462 L<Imager::Filters/gradgen>
4464 gray scale, convert image to - L<Imager::Transformations/convert>
4466 guassian blur - L<Imager::Filters/guassian>
4468 hatch fills - L<Imager::Fill/"Hatched fills">
4470 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4472 invert image - L<Imager::Filters/hardinvert>,
4473 L<Imager::Filters/hardinvertall>
4475 JPEG - L<Imager::Files/"JPEG">
4477 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4479 lines, drawing - L<Imager::Draw/line>
4481 matrix - L<Imager::Matrix2d>,
4482 L<Imager::Transformations/"Matrix Transformations">,
4483 L<Imager::Font/transform>
4485 metadata, image - L<Imager::ImageTypes/"Tags">
4487 mosaic - L<Imager::Filters/mosaic>
4489 noise, filter - L<Imager::Filters/noise>
4491 noise, rendered - L<Imager::Filters/turbnoise>,
4492 L<Imager::Filters/radnoise>
4494 paste - L<Imager::Transformations/paste>,
4495 L<Imager::Transformations/rubthrough>
4497 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4498 L<Imager::ImageTypes/new>
4500 =for stopwords posterize
4502 posterize - L<Imager::Filters/postlevels>
4504 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4506 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4508 rectangles, drawing - L<Imager::Draw/box>
4510 resizing an image - L<Imager::Transformations/scale>,
4511 L<Imager::Transformations/crop>
4513 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4515 saving an image - L<Imager::Files>
4517 scaling - L<Imager::Transformations/scale>
4519 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4521 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4523 size, image - L<Imager::ImageTypes/getwidth>,
4524 L<Imager::ImageTypes/getheight>
4526 size, text - L<Imager::Font/bounding_box>
4528 tags, image metadata - L<Imager::ImageTypes/"Tags">
4530 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4531 L<Imager::Font::Wrap>
4533 text, wrapping text in an area - L<Imager::Font::Wrap>
4535 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4537 tiles, color - L<Imager::Filters/mosaic>
4539 =for stopwords unsharp
4541 unsharp mask - L<Imager::Filters/unsharpmask>
4543 watermark - L<Imager::Filters/watermark>
4545 writing an image to a file - L<Imager::Files>
4549 Imager doesn't support perl threads.
4551 Imager has limited code to prevent double frees if you create images,
4552 colors etc, and then create a thread, but has no code to prevent two
4553 threads entering Imager's error handling code, and none is likely to
4558 The best place to get help with Imager is the mailing list.
4560 To subscribe send a message with C<subscribe> in the body to:
4562 imager-devel+request@molar.is
4568 L<http://www.molar.is/en/lists/imager-devel/>
4572 where you can also find the mailing list archive.
4574 You can report bugs by pointing your browser at:
4578 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4582 or by sending an email to:
4586 bug-Imager@rt.cpan.org
4590 Please remember to include the versions of Imager, perl, supporting
4591 libraries, and any relevant code. If you have specific images that
4592 cause the problems, please include those too.
4594 If you don't want to publish your email address on a mailing list you
4595 can use CPAN::Forum:
4597 http://www.cpanforum.com/dist/Imager
4599 You will need to register to post.
4601 =head1 CONTRIBUTING TO IMAGER
4607 If you like or dislike Imager, you can add a public review of Imager
4610 http://cpanratings.perl.org/dist/Imager
4612 =for stopwords Bitcard
4614 This requires a Bitcard account (http://www.bitcard.org).
4616 You can also send email to the maintainer below.
4618 If you send me a bug report via email, it will be copied to Request
4623 I accept patches, preferably against the main branch in subversion.
4624 You should include an explanation of the reason for why the patch is
4627 Your patch should include regression tests where possible, otherwise
4628 it will be delayed until I get a chance to write them.
4632 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4634 Arnar M. Hrafnkelsson is the original author of Imager.
4636 Many others have contributed to Imager, please see the C<README> for a
4641 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4642 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4643 L<Imager::Font>(3), L<Imager::Transformations>(3),
4644 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4645 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4647 L<http://imager.perl.org/>
4649 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4651 Other perl imaging modules include:
4653 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).