4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
122 # registered file readers
125 # registered file writers
128 # modules we attempted to autoload
129 my %attempted_to_load;
131 # library keys that are image file formats
132 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
134 # image pixel combine types
136 qw/none normal multiply dissolve add subtract diff lighten darken
137 hue saturation value color/;
139 @combine_types{@combine_types} = 0 .. $#combine_types;
140 $combine_types{mult} = $combine_types{multiply};
141 $combine_types{'sub'} = $combine_types{subtract};
142 $combine_types{sat} = $combine_types{saturation};
144 # this will be used to store global defaults at some point
150 $VERSION = '0.80_01';
153 XSLoader::load(Imager => $VERSION);
157 push @ISA, 'DynaLoader';
158 bootstrap Imager $VERSION;
165 png => "Imager::File::PNG",
166 gif => "Imager::File::GIF",
167 tiff => "Imager::File::TIFF",
168 jpeg => "Imager::File::JPEG",
169 w32 => "Imager::Font::W32",
170 ft2 => "Imager::Font::FT2",
171 t1 => "Imager::Font::T1",
174 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
177 for(i_list_formats()) { $formats_low{$_}++; }
179 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
183 # the members of the subhashes under %filters are:
184 # callseq - a list of the parameters to the underlying filter in the
185 # order they are passed
186 # callsub - a code ref that takes a named parameter list and calls the
188 # defaults - a hash of default values
189 # names - defines names for value of given parameters so if the names
190 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
191 # foo parameter, the filter will receive 1 for the foo
194 callseq => ['image','intensity'],
195 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
199 callseq => ['image', 'amount', 'subtype'],
200 defaults => { amount=>3,subtype=>0 },
201 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
204 $filters{hardinvert} ={
205 callseq => ['image'],
207 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
210 $filters{hardinvertall} =
212 callseq => ['image'],
214 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
217 $filters{autolevels} ={
218 callseq => ['image','lsat','usat','skew'],
219 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
220 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
223 $filters{turbnoise} ={
224 callseq => ['image'],
225 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
226 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
229 $filters{radnoise} ={
230 callseq => ['image'],
231 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
232 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
237 callseq => ['image', 'coef'],
242 i_conv($hsh{image},$hsh{coef})
243 or die Imager->_error_as_msg() . "\n";
249 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
250 defaults => { dist => 0 },
254 my @colors = @{$hsh{colors}};
257 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
261 $filters{nearest_color} =
263 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
268 # make sure the segments are specified with colors
270 for my $color (@{$hsh{colors}}) {
271 my $new_color = _color($color)
272 or die $Imager::ERRSTR."\n";
273 push @colors, $new_color;
276 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
278 or die Imager->_error_as_msg() . "\n";
281 $filters{gaussian} = {
282 callseq => [ 'image', 'stddev' ],
284 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
288 callseq => [ qw(image size) ],
289 defaults => { size => 20 },
290 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
294 callseq => [ qw(image bump elevation lightx lighty st) ],
295 defaults => { elevation=>0, st=> 2 },
298 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
299 $hsh{lightx}, $hsh{lighty}, $hsh{st});
302 $filters{bumpmap_complex} =
304 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
321 for my $cname (qw/Ia Il Is/) {
322 my $old = $hsh{$cname};
323 my $new_color = _color($old)
324 or die $Imager::ERRSTR, "\n";
325 $hsh{$cname} = $new_color;
327 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
328 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
329 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
333 $filters{postlevels} =
335 callseq => [ qw(image levels) ],
336 defaults => { levels => 10 },
337 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
339 $filters{watermark} =
341 callseq => [ qw(image wmark tx ty pixdiff) ],
342 defaults => { pixdiff=>10, tx=>0, ty=>0 },
346 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
352 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
354 ftype => { linear => 0,
360 repeat => { none => 0,
375 multiply => 2, mult => 2,
378 subtract => 5, 'sub' => 5,
388 defaults => { ftype => 0, repeat => 0, combine => 0,
389 super_sample => 0, ssample_param => 4,
402 # make sure the segments are specified with colors
404 for my $segment (@{$hsh{segments}}) {
405 my @new_segment = @$segment;
407 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
408 push @segments, \@new_segment;
411 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
412 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
413 $hsh{ssample_param}, \@segments)
414 or die Imager->_error_as_msg() . "\n";
417 $filters{unsharpmask} =
419 callseq => [ qw(image stddev scale) ],
420 defaults => { stddev=>2.0, scale=>1.0 },
424 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
428 $FORMATGUESS=\&def_guess_type;
438 # NOTE: this might be moved to an import override later on
443 if ($_[$i] eq '-log-stderr') {
451 goto &Exporter::import;
455 i_init_log($_[0],$_[1]);
456 i_log_entry("Imager $VERSION starting\n", 1);
461 my %parms=(loglevel=>1,@_);
463 init_log($parms{'log'},$parms{'loglevel'});
466 if (exists $parms{'warn_obsolete'}) {
467 $warn_obsolete = $parms{'warn_obsolete'};
470 if (exists $parms{'t1log'}) {
472 Imager::Font::T1::i_init_t1($parms{'t1log'});
479 print "shutdown code\n";
480 # for(keys %instances) { $instances{$_}->DESTROY(); }
481 malloc_state(); # how do decide if this should be used? -- store something from the import
482 print "Imager exiting\n";
486 # Load a filter plugin
491 my ($DSO_handle,$str)=DSO_open($filename);
492 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
493 my %funcs=DSO_funclist($DSO_handle);
494 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
496 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
498 $DSOs{$filename}=[$DSO_handle,\%funcs];
501 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
502 $DEBUG && print "eval string:\n",$evstr,"\n";
514 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
515 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
516 for(keys %{$funcref}) {
518 $DEBUG && print "unloading: $_\n";
520 my $rc=DSO_close($DSO_handle);
521 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
525 # take the results of i_error() and make a message out of it
527 return join(": ", map $_->[0], i_errors());
530 # this function tries to DWIM for color parameters
531 # color objects are used as is
532 # simple scalars are simply treated as single parameters to Imager::Color->new
533 # hashrefs are treated as named argument lists to Imager::Color->new
534 # arrayrefs are treated as list arguments to Imager::Color->new iff any
536 # other arrayrefs are treated as list arguments to Imager::Color::Float
540 # perl 5.6.0 seems to do weird things to $arg if we don't make an
541 # explicitly stringified copy
542 # I vaguely remember a bug on this on p5p, but couldn't find it
543 # through bugs.perl.org (I had trouble getting it to find any bugs)
544 my $copy = $arg . "";
548 if (UNIVERSAL::isa($arg, "Imager::Color")
549 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
553 if ($copy =~ /^HASH\(/) {
554 $result = Imager::Color->new(%$arg);
556 elsif ($copy =~ /^ARRAY\(/) {
557 $result = Imager::Color->new(@$arg);
560 $Imager::ERRSTR = "Not a color";
565 # assume Imager::Color::new knows how to handle it
566 $result = Imager::Color->new($arg);
573 my ($self, $combine, $default) = @_;
575 if (!defined $combine && ref $self) {
576 $combine = $self->{combine};
578 defined $combine or $combine = $defaults{combine};
579 defined $combine or $combine = $default;
581 if (exists $combine_types{$combine}) {
582 $combine = $combine_types{$combine};
591 $self->{IMG} and return 1;
593 $self->_set_error('empty input image');
598 # returns first defined parameter
601 return $_ if defined $_;
607 # Methods to be called on objects.
610 # Create a new Imager object takes very few parameters.
611 # usually you call this method and then call open from
612 # the resulting object
619 $self->{IMG}=undef; # Just to indicate what exists
620 $self->{ERRSTR}=undef; #
621 $self->{DEBUG}=$DEBUG;
622 $self->{DEBUG} and print "Initialized Imager\n";
623 if (defined $hsh{xsize} || defined $hsh{ysize}) {
624 unless ($self->img_set(%hsh)) {
625 $Imager::ERRSTR = $self->{ERRSTR};
629 elsif (defined $hsh{file} ||
632 defined $hsh{callback} ||
633 defined $hsh{readcb} ||
634 defined $hsh{data}) {
635 # allow $img = Imager->new(file => $filename)
638 # type is already used as a parameter to new(), rename it for the
640 if ($hsh{filetype}) {
641 $extras{type} = $hsh{filetype};
643 unless ($self->read(%hsh, %extras)) {
644 $Imager::ERRSTR = $self->{ERRSTR};
652 # Copy an entire image with no changes
653 # - if an image has magic the copy of it will not be magical
657 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
659 unless (defined wantarray) {
661 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
665 my $newcopy=Imager->new();
666 $newcopy->{IMG} = i_copy($self->{IMG});
675 unless ($self->{IMG}) {
676 $self->_set_error('empty input image');
679 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
680 my $src = $input{img} || $input{src};
682 $self->_set_error("no source image");
685 $input{left}=0 if $input{left} <= 0;
686 $input{top}=0 if $input{top} <= 0;
688 my($r,$b)=i_img_info($src->{IMG});
689 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
690 my ($src_right, $src_bottom);
691 if ($input{src_coords}) {
692 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
695 if (defined $input{src_maxx}) {
696 $src_right = $input{src_maxx};
698 elsif (defined $input{width}) {
699 if ($input{width} <= 0) {
700 $self->_set_error("paste: width must me positive");
703 $src_right = $src_left + $input{width};
708 if (defined $input{src_maxy}) {
709 $src_bottom = $input{src_maxy};
711 elsif (defined $input{height}) {
712 if ($input{height} < 0) {
713 $self->_set_error("paste: height must be positive");
716 $src_bottom = $src_top + $input{height};
723 $src_right > $r and $src_right = $r;
724 $src_bottom > $b and $src_bottom = $b;
726 if ($src_right <= $src_left
727 || $src_bottom < $src_top) {
728 $self->_set_error("nothing to paste");
732 i_copyto($self->{IMG}, $src->{IMG},
733 $src_left, $src_top, $src_right, $src_bottom,
734 $input{left}, $input{top});
736 return $self; # What should go here??
739 # Crop an image - i.e. return a new image that is smaller
743 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
745 unless (defined wantarray) {
747 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
753 my ($w, $h, $l, $r, $b, $t) =
754 @hsh{qw(width height left right bottom top)};
756 # work through the various possibilities
761 elsif (!defined $r) {
762 $r = $self->getwidth;
774 $l = int(0.5+($self->getwidth()-$w)/2);
779 $r = $self->getwidth;
785 elsif (!defined $b) {
786 $b = $self->getheight;
798 $t=int(0.5+($self->getheight()-$h)/2);
803 $b = $self->getheight;
806 ($l,$r)=($r,$l) if $l>$r;
807 ($t,$b)=($b,$t) if $t>$b;
810 $r > $self->getwidth and $r = $self->getwidth;
812 $b > $self->getheight and $b = $self->getheight;
814 if ($l == $r || $t == $b) {
815 $self->_set_error("resulting image would have no content");
818 if( $r < $l or $b < $t ) {
819 $self->_set_error("attempting to crop outside of the image");
822 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
824 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
829 my ($self, %opts) = @_;
831 $self->{IMG} or return $self->_set_error("Not a valid image");
833 my $x = $opts{xsize} || $self->getwidth;
834 my $y = $opts{ysize} || $self->getheight;
835 my $channels = $opts{channels} || $self->getchannels;
837 my $out = Imager->new;
838 if ($channels == $self->getchannels) {
839 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
842 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
844 unless ($out->{IMG}) {
845 $self->{ERRSTR} = $self->_error_as_msg;
852 # Sets an image to a certain size and channel number
853 # if there was previously data in the image it is discarded
858 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
860 if (defined($self->{IMG})) {
861 # let IIM_DESTROY destroy it, it's possible this image is
862 # referenced from a virtual image (like masked)
863 #i_img_destroy($self->{IMG});
867 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
868 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
869 $hsh{maxcolors} || 256);
871 elsif ($hsh{bits} eq 'double') {
872 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
874 elsif ($hsh{bits} == 16) {
875 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
878 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
882 unless ($self->{IMG}) {
883 $self->{ERRSTR} = Imager->_error_as_msg();
890 # created a masked version of the current image
894 $self or return undef;
895 my %opts = (left => 0,
897 right => $self->getwidth,
898 bottom => $self->getheight,
900 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
902 my $result = Imager->new;
903 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
904 $opts{top}, $opts{right} - $opts{left},
905 $opts{bottom} - $opts{top});
906 unless ($result->{IMG}) {
907 $self->_set_error(Imager->_error_as_msg);
911 # keep references to the mask and base images so they don't
913 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
918 # convert an RGB image into a paletted image
922 if (@_ != 1 && !ref $_[0]) {
929 unless (defined wantarray) {
931 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
935 my $result = Imager->new;
936 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
938 #print "Type ", i_img_type($result->{IMG}), "\n";
940 if ($result->{IMG}) {
944 $self->{ERRSTR} = $self->_error_as_msg;
949 # convert a paletted (or any image) to an 8-bit/channel RGB images
954 unless (defined wantarray) {
956 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
961 $result = Imager->new;
962 $result->{IMG} = i_img_to_rgb($self->{IMG})
969 # convert a paletted (or any image) to an 8-bit/channel RGB images
974 unless (defined wantarray) {
976 warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
981 $result = Imager->new;
982 $result->{IMG} = i_img_to_rgb16($self->{IMG})
991 my %opts = (colors=>[], @_);
993 unless ($self->{IMG}) {
994 $self->_set_error("empty input image");
998 my @colors = @{$opts{colors}}
1001 for my $color (@colors) {
1002 $color = _color($color);
1004 $self->_set_error($Imager::ERRSTR);
1009 return i_addcolors($self->{IMG}, @colors);
1014 my %opts = (start=>0, colors=>[], @_);
1016 unless ($self->{IMG}) {
1017 $self->_set_error("empty input image");
1021 my @colors = @{$opts{colors}}
1024 for my $color (@colors) {
1025 $color = _color($color);
1027 $self->_set_error($Imager::ERRSTR);
1032 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1038 if (!exists $opts{start} && !exists $opts{count}) {
1041 $opts{count} = $self->colorcount;
1043 elsif (!exists $opts{count}) {
1046 elsif (!exists $opts{start}) {
1051 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1055 i_colorcount($_[0]{IMG});
1059 i_maxcolors($_[0]{IMG});
1065 $opts{color} or return undef;
1067 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1072 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1073 if ($bits && $bits == length(pack("d", 1)) * 8) {
1082 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1088 $self->{IMG} and i_img_virtual($self->{IMG});
1094 $self->{IMG} or return;
1096 return i_img_is_monochrome($self->{IMG});
1100 my ($self, %opts) = @_;
1102 $self->{IMG} or return;
1104 if (defined $opts{name}) {
1108 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1109 push @result, (i_tags_get($self->{IMG}, $found))[1];
1112 return wantarray ? @result : $result[0];
1114 elsif (defined $opts{code}) {
1118 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1119 push @result, (i_tags_get($self->{IMG}, $found))[1];
1126 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1129 return i_tags_count($self->{IMG});
1138 return -1 unless $self->{IMG};
1140 if (defined $opts{value}) {
1141 if ($opts{value} =~ /^\d+$/) {
1143 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1146 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1149 elsif (defined $opts{data}) {
1150 # force addition as a string
1151 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1154 $self->{ERRSTR} = "No value supplied";
1158 elsif ($opts{code}) {
1159 if (defined $opts{value}) {
1160 if ($opts{value} =~ /^\d+$/) {
1162 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1165 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1168 elsif (defined $opts{data}) {
1169 # force addition as a string
1170 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1173 $self->{ERRSTR} = "No value supplied";
1186 return 0 unless $self->{IMG};
1188 if (defined $opts{'index'}) {
1189 return i_tags_delete($self->{IMG}, $opts{'index'});
1191 elsif (defined $opts{name}) {
1192 return i_tags_delbyname($self->{IMG}, $opts{name});
1194 elsif (defined $opts{code}) {
1195 return i_tags_delbycode($self->{IMG}, $opts{code});
1198 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1204 my ($self, %opts) = @_;
1207 $self->deltag(name=>$opts{name});
1208 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1210 elsif (defined $opts{code}) {
1211 $self->deltag(code=>$opts{code});
1212 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1220 sub _get_reader_io {
1221 my ($self, $input) = @_;
1224 return $input->{io}, undef;
1226 elsif ($input->{fd}) {
1227 return io_new_fd($input->{fd});
1229 elsif ($input->{fh}) {
1230 my $fd = fileno($input->{fh});
1231 unless (defined $fd) {
1232 $self->_set_error("Handle in fh option not opened");
1235 return io_new_fd($fd);
1237 elsif ($input->{file}) {
1238 my $file = IO::File->new($input->{file}, "r");
1240 $self->_set_error("Could not open $input->{file}: $!");
1244 return (io_new_fd(fileno($file)), $file);
1246 elsif ($input->{data}) {
1247 return io_new_buffer($input->{data});
1249 elsif ($input->{callback} || $input->{readcb}) {
1250 if (!$input->{seekcb}) {
1251 $self->_set_error("Need a seekcb parameter");
1253 if ($input->{maxbuffer}) {
1254 return io_new_cb($input->{writecb},
1255 $input->{callback} || $input->{readcb},
1256 $input->{seekcb}, $input->{closecb},
1257 $input->{maxbuffer});
1260 return io_new_cb($input->{writecb},
1261 $input->{callback} || $input->{readcb},
1262 $input->{seekcb}, $input->{closecb});
1266 $self->_set_error("file/fd/fh/data/callback parameter missing");
1271 sub _get_writer_io {
1272 my ($self, $input, $type) = @_;
1275 return $input->{io};
1277 elsif ($input->{fd}) {
1278 return io_new_fd($input->{fd});
1280 elsif ($input->{fh}) {
1281 my $fd = fileno($input->{fh});
1282 unless (defined $fd) {
1283 $self->_set_error("Handle in fh option not opened");
1287 my $oldfh = select($input->{fh});
1288 # flush anything that's buffered, and make sure anything else is flushed
1291 return io_new_fd($fd);
1293 elsif ($input->{file}) {
1294 my $fh = new IO::File($input->{file},"w+");
1296 $self->_set_error("Could not open file $input->{file}: $!");
1299 binmode($fh) or die;
1300 return (io_new_fd(fileno($fh)), $fh);
1302 elsif ($input->{data}) {
1303 return io_new_bufchain();
1305 elsif ($input->{callback} || $input->{writecb}) {
1306 if ($input->{maxbuffer}) {
1307 return io_new_cb($input->{callback} || $input->{writecb},
1309 $input->{seekcb}, $input->{closecb},
1310 $input->{maxbuffer});
1313 return io_new_cb($input->{callback} || $input->{writecb},
1315 $input->{seekcb}, $input->{closecb});
1319 $self->_set_error("file/fd/fh/data/callback parameter missing");
1324 # Read an image from file
1330 if (defined($self->{IMG})) {
1331 # let IIM_DESTROY do the destruction, since the image may be
1332 # referenced from elsewhere
1333 #i_img_destroy($self->{IMG});
1334 undef($self->{IMG});
1337 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1339 unless ($input{'type'}) {
1340 $input{'type'} = i_test_format_probe($IO, -1);
1343 unless ($input{'type'}) {
1344 $self->_set_error('type parameter missing and not possible to guess from extension');
1348 _reader_autoload($input{type});
1350 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1351 return $readers{$input{type}}{single}->($self, $IO, %input);
1354 unless ($formats_low{$input{'type'}}) {
1355 my $read_types = join ', ', sort Imager->read_types();
1356 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1360 my $allow_incomplete = $input{allow_incomplete};
1361 defined $allow_incomplete or $allow_incomplete = 0;
1363 if ( $input{'type'} eq 'pnm' ) {
1364 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1365 if ( !defined($self->{IMG}) ) {
1366 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1369 $self->{DEBUG} && print "loading a pnm file\n";
1373 if ( $input{'type'} eq 'bmp' ) {
1374 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1375 if ( !defined($self->{IMG}) ) {
1376 $self->{ERRSTR}=$self->_error_as_msg();
1379 $self->{DEBUG} && print "loading a bmp file\n";
1382 if ( $input{'type'} eq 'gif' ) {
1383 if ($input{colors} && !ref($input{colors})) {
1384 # must be a reference to a scalar that accepts the colour map
1385 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1388 if ($input{'gif_consolidate'}) {
1389 if ($input{colors}) {
1391 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1393 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1397 $self->{IMG} =i_readgif_wiol( $IO );
1401 my $page = $input{'page'};
1402 defined $page or $page = 0;
1403 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1404 if ($self->{IMG} && $input{colors}) {
1405 ${ $input{colors} } =
1406 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1410 if ( !defined($self->{IMG}) ) {
1411 $self->{ERRSTR}=$self->_error_as_msg();
1414 $self->{DEBUG} && print "loading a gif file\n";
1417 if ( $input{'type'} eq 'tga' ) {
1418 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1419 if ( !defined($self->{IMG}) ) {
1420 $self->{ERRSTR}=$self->_error_as_msg();
1423 $self->{DEBUG} && print "loading a tga file\n";
1426 if ( $input{'type'} eq 'raw' ) {
1427 unless ( $input{xsize} && $input{ysize} ) {
1428 $self->_set_error('missing xsize or ysize parameter for raw');
1432 my $interleave = _first($input{raw_interleave}, $input{interleave});
1433 unless (defined $interleave) {
1434 my @caller = caller;
1435 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1438 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1439 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1441 $self->{IMG} = i_readraw_wiol( $IO,
1447 if ( !defined($self->{IMG}) ) {
1448 $self->{ERRSTR}=$self->_error_as_msg();
1451 $self->{DEBUG} && print "loading a raw file\n";
1457 sub register_reader {
1458 my ($class, %opts) = @_;
1461 or die "register_reader called with no type parameter\n";
1463 my $type = $opts{type};
1465 defined $opts{single} || defined $opts{multiple}
1466 or die "register_reader called with no single or multiple parameter\n";
1468 $readers{$type} = { };
1469 if ($opts{single}) {
1470 $readers{$type}{single} = $opts{single};
1472 if ($opts{multiple}) {
1473 $readers{$type}{multiple} = $opts{multiple};
1479 sub register_writer {
1480 my ($class, %opts) = @_;
1483 or die "register_writer called with no type parameter\n";
1485 my $type = $opts{type};
1487 defined $opts{single} || defined $opts{multiple}
1488 or die "register_writer called with no single or multiple parameter\n";
1490 $writers{$type} = { };
1491 if ($opts{single}) {
1492 $writers{$type}{single} = $opts{single};
1494 if ($opts{multiple}) {
1495 $writers{$type}{multiple} = $opts{multiple};
1506 grep($file_formats{$_}, keys %formats),
1507 qw(ico sgi), # formats not handled directly, but supplied with Imager
1518 grep($file_formats{$_}, keys %formats),
1519 qw(ico sgi), # formats not handled directly, but supplied with Imager
1525 # probes for an Imager::File::whatever module
1526 sub _reader_autoload {
1529 return if $formats_low{$type} || $readers{$type};
1531 return unless $type =~ /^\w+$/;
1533 my $file = "Imager/File/\U$type\E.pm";
1535 unless ($attempted_to_load{$file}) {
1537 ++$attempted_to_load{$file};
1541 # try to get a reader specific module
1542 my $file = "Imager/File/\U$type\EReader.pm";
1543 unless ($attempted_to_load{$file}) {
1545 ++$attempted_to_load{$file};
1553 # probes for an Imager::File::whatever module
1554 sub _writer_autoload {
1557 return if $formats_low{$type} || $readers{$type};
1559 return unless $type =~ /^\w+$/;
1561 my $file = "Imager/File/\U$type\E.pm";
1563 unless ($attempted_to_load{$file}) {
1565 ++$attempted_to_load{$file};
1569 # try to get a writer specific module
1570 my $file = "Imager/File/\U$type\EWriter.pm";
1571 unless ($attempted_to_load{$file}) {
1573 ++$attempted_to_load{$file};
1581 sub _fix_gif_positions {
1582 my ($opts, $opt, $msg, @imgs) = @_;
1584 my $positions = $opts->{'gif_positions'};
1586 for my $pos (@$positions) {
1587 my ($x, $y) = @$pos;
1588 my $img = $imgs[$index++];
1589 $img->settag(name=>'gif_left', value=>$x);
1590 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1592 $$msg .= "replaced with the gif_left and gif_top tags";
1597 gif_each_palette=>'gif_local_map',
1598 interlace => 'gif_interlace',
1599 gif_delays => 'gif_delay',
1600 gif_positions => \&_fix_gif_positions,
1601 gif_loop_count => 'gif_loop',
1604 # options that should be converted to colors
1605 my %color_opts = map { $_ => 1 } qw/i_background/;
1608 my ($self, $opts, $prefix, @imgs) = @_;
1610 for my $opt (keys %$opts) {
1612 if ($obsolete_opts{$opt}) {
1613 my $new = $obsolete_opts{$opt};
1614 my $msg = "Obsolete option $opt ";
1616 $new->($opts, $opt, \$msg, @imgs);
1619 $msg .= "replaced with the $new tag ";
1622 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1623 warn $msg if $warn_obsolete && $^W;
1625 next unless $tagname =~ /^\Q$prefix/;
1626 my $value = $opts->{$opt};
1627 if ($color_opts{$opt}) {
1628 $value = _color($value);
1630 $self->_set_error($Imager::ERRSTR);
1635 if (UNIVERSAL::isa($value, "Imager::Color")) {
1636 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1637 for my $img (@imgs) {
1638 $img->settag(name=>$tagname, value=>$tag);
1641 elsif (ref($value) eq 'ARRAY') {
1642 for my $i (0..$#$value) {
1643 my $val = $value->[$i];
1645 if (UNIVERSAL::isa($val, "Imager::Color")) {
1646 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1648 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1651 $self->_set_error("Unknown reference type " . ref($value) .
1652 " supplied in array for $opt");
1658 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1663 $self->_set_error("Unknown reference type " . ref($value) .
1664 " supplied for $opt");
1669 # set it as a tag for every image
1670 for my $img (@imgs) {
1671 $img->settag(name=>$tagname, value=>$value);
1679 # Write an image to file
1682 my %input=(jpegquality=>75,
1692 $self->_set_opts(\%input, "i_", $self)
1695 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1697 if (!$input{'type'} and $input{file}) {
1698 $input{'type'}=$FORMATGUESS->($input{file});
1700 if (!$input{'type'}) {
1701 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1705 _writer_autoload($input{type});
1708 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1709 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1712 $writers{$input{type}}{single}->($self, $IO, %input)
1716 if (!$formats_low{$input{'type'}}) {
1717 my $write_types = join ', ', sort Imager->write_types();
1718 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1722 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1725 if ( $input{'type'} eq 'pnm' ) {
1726 $self->_set_opts(\%input, "pnm_", $self)
1728 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1729 $self->{ERRSTR} = $self->_error_as_msg();
1732 $self->{DEBUG} && print "writing a pnm file\n";
1733 } elsif ( $input{'type'} eq 'raw' ) {
1734 $self->_set_opts(\%input, "raw_", $self)
1736 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1737 $self->{ERRSTR} = $self->_error_as_msg();
1740 $self->{DEBUG} && print "writing a raw file\n";
1741 } elsif ( $input{'type'} eq 'jpeg' ) {
1742 $self->_set_opts(\%input, "jpeg_", $self)
1744 $self->_set_opts(\%input, "exif_", $self)
1746 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1747 $self->{ERRSTR} = $self->_error_as_msg();
1750 $self->{DEBUG} && print "writing a jpeg file\n";
1751 } elsif ( $input{'type'} eq 'bmp' ) {
1752 $self->_set_opts(\%input, "bmp_", $self)
1754 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1755 $self->{ERRSTR} = $self->_error_as_msg;
1758 $self->{DEBUG} && print "writing a bmp file\n";
1759 } elsif ( $input{'type'} eq 'tga' ) {
1760 $self->_set_opts(\%input, "tga_", $self)
1763 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1764 $self->{ERRSTR}=$self->_error_as_msg();
1767 $self->{DEBUG} && print "writing a tga file\n";
1768 } elsif ( $input{'type'} eq 'gif' ) {
1769 $self->_set_opts(\%input, "gif_", $self)
1771 # compatibility with the old interfaces
1772 if ($input{gifquant} eq 'lm') {
1773 $input{make_colors} = 'addi';
1774 $input{translate} = 'perturb';
1775 $input{perturb} = $input{lmdither};
1776 } elsif ($input{gifquant} eq 'gen') {
1777 # just pass options through
1779 $input{make_colors} = 'webmap'; # ignored
1780 $input{translate} = 'giflib';
1782 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1783 $self->{ERRSTR} = $self->_error_as_msg;
1789 if (exists $input{'data'}) {
1790 my $data = io_slurp($IO);
1792 $self->{ERRSTR}='Could not slurp from buffer';
1795 ${$input{data}} = $data;
1801 my ($class, $opts, @images) = @_;
1803 my $type = $opts->{type};
1805 if (!$type && $opts->{'file'}) {
1806 $type = $FORMATGUESS->($opts->{'file'});
1809 $class->_set_error('type parameter missing and not possible to guess from extension');
1812 # translate to ImgRaw
1813 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1814 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1817 $class->_set_opts($opts, "i_", @images)
1819 my @work = map $_->{IMG}, @images;
1821 _writer_autoload($type);
1824 if ($writers{$type} && $writers{$type}{multiple}) {
1825 ($IO, $file) = $class->_get_writer_io($opts, $type)
1828 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1832 if (!$formats{$type}) {
1833 my $write_types = join ', ', sort Imager->write_types();
1834 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1838 ($IO, $file) = $class->_get_writer_io($opts, $type)
1841 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1845 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1850 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1856 if (exists $opts->{'data'}) {
1857 my $data = io_slurp($IO);
1859 Imager->_set_error('Could not slurp from buffer');
1862 ${$opts->{data}} = $data;
1867 # read multiple images from a file
1869 my ($class, %opts) = @_;
1871 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1874 my $type = $opts{'type'};
1876 $type = i_test_format_probe($IO, -1);
1879 if ($opts{file} && !$type) {
1881 $type = $FORMATGUESS->($opts{file});
1885 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1889 _reader_autoload($type);
1891 if ($readers{$type} && $readers{$type}{multiple}) {
1892 return $readers{$type}{multiple}->($IO, %opts);
1895 unless ($formats{$type}) {
1896 my $read_types = join ', ', sort Imager->read_types();
1897 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1902 if ($type eq 'pnm') {
1903 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1906 my $img = Imager->new;
1907 if ($img->read(%opts, io => $IO, type => $type)) {
1910 Imager->_set_error($img->errstr);
1915 $ERRSTR = _error_as_msg();
1919 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1923 # Destroy an Imager object
1927 # delete $instances{$self};
1928 if (defined($self->{IMG})) {
1929 # the following is now handled by the XS DESTROY method for
1930 # Imager::ImgRaw object
1931 # Re-enabling this will break virtual images
1932 # tested for in t/t020masked.t
1933 # i_img_destroy($self->{IMG});
1934 undef($self->{IMG});
1936 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1940 # Perform an inplace filter of an image
1941 # that is the image will be overwritten with the data
1947 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1949 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1951 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1952 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1955 if ($filters{$input{'type'}}{names}) {
1956 my $names = $filters{$input{'type'}}{names};
1957 for my $name (keys %$names) {
1958 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1959 $input{$name} = $names->{$name}{$input{$name}};
1963 if (defined($filters{$input{'type'}}{defaults})) {
1964 %hsh=( image => $self->{IMG},
1966 %{$filters{$input{'type'}}{defaults}},
1969 %hsh=( image => $self->{IMG},
1974 my @cs=@{$filters{$input{'type'}}{callseq}};
1977 if (!defined($hsh{$_})) {
1978 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1983 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1984 &{$filters{$input{'type'}}{callsub}}(%hsh);
1987 chomp($self->{ERRSTR} = $@);
1993 $self->{DEBUG} && print "callseq is: @cs\n";
1994 $self->{DEBUG} && print "matching callseq is: @b\n";
1999 sub register_filter {
2001 my %hsh = ( defaults => {}, @_ );
2004 or die "register_filter() with no type\n";
2005 defined $hsh{callsub}
2006 or die "register_filter() with no callsub\n";
2007 defined $hsh{callseq}
2008 or die "register_filter() with no callseq\n";
2010 exists $filters{$hsh{type}}
2013 $filters{$hsh{type}} = \%hsh;
2018 sub scale_calculate {
2021 my %opts = ('type'=>'max', @_);
2023 # none of these should be references
2024 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2025 if (defined $opts{$name} && ref $opts{$name}) {
2026 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2031 my ($x_scale, $y_scale);
2032 my $width = $opts{width};
2033 my $height = $opts{height};
2035 defined $width or $width = $self->getwidth;
2036 defined $height or $height = $self->getheight;
2039 unless (defined $width && defined $height) {
2040 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2045 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2046 $x_scale = $opts{'xscalefactor'};
2047 $y_scale = $opts{'yscalefactor'};
2049 elsif ($opts{'xscalefactor'}) {
2050 $x_scale = $opts{'xscalefactor'};
2051 $y_scale = $opts{'scalefactor'} || $x_scale;
2053 elsif ($opts{'yscalefactor'}) {
2054 $y_scale = $opts{'yscalefactor'};
2055 $x_scale = $opts{'scalefactor'} || $y_scale;
2058 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2061 # work out the scaling
2062 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2063 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2064 $opts{ypixels} / $height );
2065 if ($opts{'type'} eq 'min') {
2066 $x_scale = $y_scale = _min($xpix,$ypix);
2068 elsif ($opts{'type'} eq 'max') {
2069 $x_scale = $y_scale = _max($xpix,$ypix);
2071 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2076 $self->_set_error('invalid value for type parameter');
2079 } elsif ($opts{xpixels}) {
2080 $x_scale = $y_scale = $opts{xpixels} / $width;
2082 elsif ($opts{ypixels}) {
2083 $x_scale = $y_scale = $opts{ypixels}/$height;
2085 elsif ($opts{constrain} && ref $opts{constrain}
2086 && $opts{constrain}->can('constrain')) {
2087 # we've been passed an Image::Math::Constrain object or something
2088 # that looks like one
2090 (undef, undef, $scalefactor)
2091 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2092 unless ($scalefactor) {
2093 $self->_set_error('constrain method failed on constrain parameter');
2096 $x_scale = $y_scale = $scalefactor;
2099 my $new_width = int($x_scale * $width + 0.5);
2100 $new_width > 0 or $new_width = 1;
2101 my $new_height = int($y_scale * $height + 0.5);
2102 $new_height > 0 or $new_height = 1;
2104 return ($x_scale, $y_scale, $new_width, $new_height);
2108 # Scale an image to requested size and return the scaled version
2112 my %opts = (qtype=>'normal' ,@_);
2113 my $img = Imager->new();
2114 my $tmp = Imager->new();
2116 unless (defined wantarray) {
2117 my @caller = caller;
2118 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2122 unless ($self->{IMG}) {
2123 $self->_set_error('empty input image');
2127 my ($x_scale, $y_scale, $new_width, $new_height) =
2128 $self->scale_calculate(%opts)
2131 if ($opts{qtype} eq 'normal') {
2132 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2133 if ( !defined($tmp->{IMG}) ) {
2134 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2137 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2138 if ( !defined($img->{IMG}) ) {
2139 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2145 elsif ($opts{'qtype'} eq 'preview') {
2146 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2147 if ( !defined($img->{IMG}) ) {
2148 $self->{ERRSTR}='unable to scale image';
2153 elsif ($opts{'qtype'} eq 'mixing') {
2154 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2155 unless ($img->{IMG}) {
2156 $self->_set_error(Imager->_error_as_msg);
2162 $self->_set_error('invalid value for qtype parameter');
2167 # Scales only along the X axis
2171 my %opts = ( scalefactor=>0.5, @_ );
2173 unless (defined wantarray) {
2174 my @caller = caller;
2175 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2179 unless ($self->{IMG}) {
2180 $self->{ERRSTR} = 'empty input image';
2184 my $img = Imager->new();
2186 my $scalefactor = $opts{scalefactor};
2188 if ($opts{pixels}) {
2189 $scalefactor = $opts{pixels} / $self->getwidth();
2192 unless ($self->{IMG}) {
2193 $self->{ERRSTR}='empty input image';
2197 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2199 if ( !defined($img->{IMG}) ) {
2200 $self->{ERRSTR} = 'unable to scale image';
2207 # Scales only along the Y axis
2211 my %opts = ( scalefactor => 0.5, @_ );
2213 unless (defined wantarray) {
2214 my @caller = caller;
2215 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2219 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2221 my $img = Imager->new();
2223 my $scalefactor = $opts{scalefactor};
2225 if ($opts{pixels}) {
2226 $scalefactor = $opts{pixels} / $self->getheight();
2229 unless ($self->{IMG}) {
2230 $self->{ERRSTR} = 'empty input image';
2233 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2235 if ( !defined($img->{IMG}) ) {
2236 $self->{ERRSTR} = 'unable to scale image';
2243 # Transform returns a spatial transformation of the input image
2244 # this moves pixels to a new location in the returned image.
2245 # NOTE - should make a utility function to check transforms for
2250 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2252 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2254 # print Dumper(\%opts);
2257 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2259 eval ("use Affix::Infix2Postfix;");
2262 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2265 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2266 {op=>'-',trans=>'Sub'},
2267 {op=>'*',trans=>'Mult'},
2268 {op=>'/',trans=>'Div'},
2269 {op=>'-','type'=>'unary',trans=>'u-'},
2271 {op=>'func','type'=>'unary'}],
2272 'grouping'=>[qw( \( \) )],
2273 'func'=>[qw( sin cos )],
2278 @xt=$I2P->translate($opts{'xexpr'});
2279 @yt=$I2P->translate($opts{'yexpr'});
2281 $numre=$I2P->{'numre'};
2284 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2285 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2286 @{$opts{'parm'}}=@pt;
2289 # print Dumper(\%opts);
2291 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2292 $self->{ERRSTR}='transform: no xopcodes given.';
2296 @op=@{$opts{'xopcodes'}};
2298 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2299 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2302 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2308 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2309 $self->{ERRSTR}='transform: no yopcodes given.';
2313 @op=@{$opts{'yopcodes'}};
2315 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2316 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2319 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2324 if ( !exists $opts{'parm'}) {
2325 $self->{ERRSTR}='transform: no parameter arg given.';
2329 # print Dumper(\@ropx);
2330 # print Dumper(\@ropy);
2331 # print Dumper(\@ropy);
2333 my $img = Imager->new();
2334 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2335 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2341 my ($opts, @imgs) = @_;
2343 require "Imager/Expr.pm";
2345 $opts->{variables} = [ qw(x y) ];
2346 my ($width, $height) = @{$opts}{qw(width height)};
2348 $width ||= $imgs[0]->getwidth();
2349 $height ||= $imgs[0]->getheight();
2351 for my $img (@imgs) {
2352 $opts->{constants}{"w$img_num"} = $img->getwidth();
2353 $opts->{constants}{"h$img_num"} = $img->getheight();
2354 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2355 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2360 $opts->{constants}{w} = $width;
2361 $opts->{constants}{cx} = $width/2;
2364 $Imager::ERRSTR = "No width supplied";
2368 $opts->{constants}{h} = $height;
2369 $opts->{constants}{cy} = $height/2;
2372 $Imager::ERRSTR = "No height supplied";
2375 my $code = Imager::Expr->new($opts);
2377 $Imager::ERRSTR = Imager::Expr::error();
2380 my $channels = $opts->{channels} || 3;
2381 unless ($channels >= 1 && $channels <= 4) {
2382 return Imager->_set_error("channels must be an integer between 1 and 4");
2385 my $img = Imager->new();
2386 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2387 $channels, $code->code(),
2388 $code->nregs(), $code->cregs(),
2389 [ map { $_->{IMG} } @imgs ]);
2390 if (!defined $img->{IMG}) {
2391 $Imager::ERRSTR = Imager->_error_as_msg();
2402 unless ($self->{IMG}) {
2403 $self->{ERRSTR}='empty input image';
2406 unless ($opts{src} && $opts{src}->{IMG}) {
2407 $self->{ERRSTR}='empty input image for src';
2411 %opts = (src_minx => 0,
2413 src_maxx => $opts{src}->getwidth(),
2414 src_maxy => $opts{src}->getheight(),
2418 defined $tx or $tx = $opts{left};
2419 defined $tx or $tx = 0;
2422 defined $ty or $ty = $opts{top};
2423 defined $ty or $ty = 0;
2425 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2426 $opts{src_minx}, $opts{src_miny},
2427 $opts{src_maxx}, $opts{src_maxy})) {
2428 $self->_set_error($self->_error_as_msg());
2445 unless ($self->{IMG}) {
2446 $self->_set_error("compose: empty input image");
2450 unless ($opts{src}) {
2451 $self->_set_error("compose: src parameter missing");
2455 unless ($opts{src}{IMG}) {
2456 $self->_set_error("compose: src parameter empty image");
2459 my $src = $opts{src};
2461 my $left = $opts{left};
2462 defined $left or $left = $opts{tx};
2463 defined $left or $left = 0;
2465 my $top = $opts{top};
2466 defined $top or $top = $opts{ty};
2467 defined $top or $top = 0;
2469 my $src_left = $opts{src_left};
2470 defined $src_left or $src_left = $opts{src_minx};
2471 defined $src_left or $src_left = 0;
2473 my $src_top = $opts{src_top};
2474 defined $src_top or $src_top = $opts{src_miny};
2475 defined $src_top or $src_top = 0;
2477 my $width = $opts{width};
2478 if (!defined $width && defined $opts{src_maxx}) {
2479 $width = $opts{src_maxx} - $src_left;
2481 defined $width or $width = $src->getwidth() - $src_left;
2483 my $height = $opts{height};
2484 if (!defined $height && defined $opts{src_maxy}) {
2485 $height = $opts{src_maxy} - $src_top;
2487 defined $height or $height = $src->getheight() - $src_top;
2489 my $combine = $self->_combine($opts{combine}, 'normal');
2492 unless ($opts{mask}{IMG}) {
2493 $self->_set_error("compose: mask parameter empty image");
2497 my $mask_left = $opts{mask_left};
2498 defined $mask_left or $mask_left = $opts{mask_minx};
2499 defined $mask_left or $mask_left = 0;
2501 my $mask_top = $opts{mask_top};
2502 defined $mask_top or $mask_top = $opts{mask_miny};
2503 defined $mask_top or $mask_top = 0;
2505 i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2506 $left, $top, $src_left, $src_top,
2507 $mask_left, $mask_top, $width, $height,
2508 $combine, $opts{opacity})
2512 i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2513 $width, $height, $combine, $opts{opacity})
2523 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2525 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2526 $dir = $xlate{$opts{'dir'}};
2527 return $self if i_flipxy($self->{IMG}, $dir);
2535 unless (defined wantarray) {
2536 my @caller = caller;
2537 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2541 if (defined $opts{right}) {
2542 my $degrees = $opts{right};
2544 $degrees += 360 * int(((-$degrees)+360)/360);
2546 $degrees = $degrees % 360;
2547 if ($degrees == 0) {
2548 return $self->copy();
2550 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2551 my $result = Imager->new();
2552 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2556 $self->{ERRSTR} = $self->_error_as_msg();
2561 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2565 elsif (defined $opts{radians} || defined $opts{degrees}) {
2566 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2568 my $back = $opts{back};
2569 my $result = Imager->new;
2571 $back = _color($back);
2573 $self->_set_error(Imager->errstr);
2577 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2580 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2582 if ($result->{IMG}) {
2586 $self->{ERRSTR} = $self->_error_as_msg();
2591 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2596 sub matrix_transform {
2600 unless (defined wantarray) {
2601 my @caller = caller;
2602 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2606 if ($opts{matrix}) {
2607 my $xsize = $opts{xsize} || $self->getwidth;
2608 my $ysize = $opts{ysize} || $self->getheight;
2610 my $result = Imager->new;
2612 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2613 $opts{matrix}, $opts{back})
2617 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2625 $self->{ERRSTR} = "matrix parameter required";
2631 *yatf = \&matrix_transform;
2633 # These two are supported for legacy code only
2636 return Imager::Color->new(@_);
2640 return Imager::Color::set(@_);
2643 # Draws a box between the specified corner points.
2646 my $raw = $self->{IMG};
2649 $self->{ERRSTR}='empty input image';
2655 my ($xmin, $ymin, $xmax, $ymax);
2656 if (exists $opts{'box'}) {
2657 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2658 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2659 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2660 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2663 defined($xmin = $opts{xmin}) or $xmin = 0;
2664 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2665 defined($ymin = $opts{ymin}) or $ymin = 0;
2666 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2669 if ($opts{filled}) {
2670 my $color = $opts{'color'};
2672 if (defined $color) {
2673 unless (_is_color_object($color)) {
2674 $color = _color($color);
2676 $self->{ERRSTR} = $Imager::ERRSTR;
2682 $color = i_color_new(255,255,255,255);
2685 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2687 elsif ($opts{fill}) {
2688 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2689 # assume it's a hash ref
2690 require 'Imager/Fill.pm';
2691 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2692 $self->{ERRSTR} = $Imager::ERRSTR;
2696 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2699 my $color = $opts{'color'};
2700 if (defined $color) {
2701 unless (_is_color_object($color)) {
2702 $color = _color($color);
2704 $self->{ERRSTR} = $Imager::ERRSTR;
2710 $color = i_color_new(255, 255, 255, 255);
2713 $self->{ERRSTR} = $Imager::ERRSTR;
2716 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2724 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2725 my $dflcl= [ 255, 255, 255, 255];
2730 'r'=>_min($self->getwidth(),$self->getheight())/3,
2731 'x'=>$self->getwidth()/2,
2732 'y'=>$self->getheight()/2,
2739 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2740 # assume it's a hash ref
2741 require 'Imager/Fill.pm';
2742 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2743 $self->{ERRSTR} = $Imager::ERRSTR;
2747 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2748 $opts{'d2'}, $opts{fill}{fill});
2750 elsif ($opts{filled}) {
2751 my $color = _color($opts{'color'});
2753 $self->{ERRSTR} = $Imager::ERRSTR;
2756 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2757 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2761 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2762 $opts{'d1'}, $opts{'d2'}, $color);
2766 my $color = _color($opts{'color'});
2767 if ($opts{d2} - $opts{d1} >= 360) {
2768 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2771 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2777 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2778 # assume it's a hash ref
2779 require 'Imager/Fill.pm';
2780 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2781 $self->{ERRSTR} = $Imager::ERRSTR;
2785 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2786 $opts{'d2'}, $opts{fill}{fill});
2789 my $color = _color($opts{'color'});
2791 $self->{ERRSTR} = $Imager::ERRSTR;
2794 if ($opts{filled}) {
2795 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2796 $opts{'d1'}, $opts{'d2'}, $color);
2799 if ($opts{d1} == 0 && $opts{d2} == 361) {
2800 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2803 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2809 $self->_set_error($self->_error_as_msg);
2816 # Draws a line from one point to the other
2817 # the endpoint is set if the endp parameter is set which it is by default.
2818 # to turn of the endpoint being set use endp=>0 when calling line.
2822 my $dflcl=i_color_new(0,0,0,0);
2823 my %opts=(color=>$dflcl,
2826 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2828 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2829 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2831 my $color = _color($opts{'color'});
2833 $self->{ERRSTR} = $Imager::ERRSTR;
2837 $opts{antialias} = $opts{aa} if defined $opts{aa};
2838 if ($opts{antialias}) {
2839 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2840 $color, $opts{endp});
2842 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2843 $color, $opts{endp});
2848 # Draws a line between an ordered set of points - It more or less just transforms this
2849 # into a list of lines.
2853 my ($pt,$ls,@points);
2854 my $dflcl=i_color_new(0,0,0,0);
2855 my %opts=(color=>$dflcl,@_);
2857 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2859 if (exists($opts{points})) { @points=@{$opts{points}}; }
2860 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2861 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2864 # print Dumper(\@points);
2866 my $color = _color($opts{'color'});
2868 $self->{ERRSTR} = $Imager::ERRSTR;
2871 $opts{antialias} = $opts{aa} if defined $opts{aa};
2872 if ($opts{antialias}) {
2875 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2882 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2892 my ($pt,$ls,@points);
2893 my $dflcl = i_color_new(0,0,0,0);
2894 my %opts = (color=>$dflcl, @_);
2896 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2898 if (exists($opts{points})) {
2899 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2900 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2903 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2904 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2907 if ($opts{'fill'}) {
2908 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2909 # assume it's a hash ref
2910 require 'Imager/Fill.pm';
2911 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2912 $self->{ERRSTR} = $Imager::ERRSTR;
2916 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2917 $opts{'fill'}{'fill'});
2920 my $color = _color($opts{'color'});
2922 $self->{ERRSTR} = $Imager::ERRSTR;
2925 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2932 # this the multipoint bezier curve
2933 # this is here more for testing that actual usage since
2934 # this is not a good algorithm. Usually the curve would be
2935 # broken into smaller segments and each done individually.
2939 my ($pt,$ls,@points);
2940 my $dflcl=i_color_new(0,0,0,0);
2941 my %opts=(color=>$dflcl,@_);
2943 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2945 if (exists $opts{points}) {
2946 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2947 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2950 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2951 $self->{ERRSTR}='Missing or invalid points.';
2955 my $color = _color($opts{'color'});
2957 $self->{ERRSTR} = $Imager::ERRSTR;
2960 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2966 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2969 unless (exists $opts{'x'} && exists $opts{'y'}) {
2970 $self->{ERRSTR} = "missing seed x and y parameters";
2974 if ($opts{border}) {
2975 my $border = _color($opts{border});
2977 $self->_set_error($Imager::ERRSTR);
2981 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2982 # assume it's a hash ref
2983 require Imager::Fill;
2984 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2985 $self->{ERRSTR} = $Imager::ERRSTR;
2989 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2990 $opts{fill}{fill}, $border);
2993 my $color = _color($opts{'color'});
2995 $self->{ERRSTR} = $Imager::ERRSTR;
2998 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3005 $self->{ERRSTR} = $self->_error_as_msg();
3011 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3012 # assume it's a hash ref
3013 require 'Imager/Fill.pm';
3014 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3015 $self->{ERRSTR} = $Imager::ERRSTR;
3019 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3022 my $color = _color($opts{'color'});
3024 $self->{ERRSTR} = $Imager::ERRSTR;
3027 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3033 $self->{ERRSTR} = $self->_error_as_msg();
3040 my ($self, %opts) = @_;
3042 my $color = $opts{color};
3043 unless (defined $color) {
3044 $color = $self->{fg};
3045 defined $color or $color = NC(255, 255, 255);
3048 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3049 $color = _color($color)
3053 unless (exists $opts{'x'} && exists $opts{'y'}) {
3054 $self->{ERRSTR} = 'missing x and y parameters';
3060 if (ref $x && ref $y) {
3061 unless (@$x == @$y) {
3062 $self->{ERRSTR} = 'length of x and y mismatch';
3066 if ($color->isa('Imager::Color')) {
3067 for my $i (0..$#{$opts{'x'}}) {
3068 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3073 for my $i (0..$#{$opts{'x'}}) {
3074 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3082 if ($color->isa('Imager::Color')) {
3083 i_ppix($self->{IMG}, $x, $y, $color)
3087 i_ppixf($self->{IMG}, $x, $y, $color)
3098 my %opts = ( "type"=>'8bit', @_);
3100 unless (exists $opts{'x'} && exists $opts{'y'}) {
3101 $self->{ERRSTR} = 'missing x and y parameters';
3107 if (ref $x && ref $y) {
3108 unless (@$x == @$y) {
3109 $self->{ERRSTR} = 'length of x and y mismatch';
3113 if ($opts{"type"} eq '8bit') {
3114 for my $i (0..$#{$opts{'x'}}) {
3115 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3119 for my $i (0..$#{$opts{'x'}}) {
3120 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3123 return wantarray ? @result : \@result;
3126 if ($opts{"type"} eq '8bit') {
3127 return i_get_pixel($self->{IMG}, $x, $y);
3130 return i_gpixf($self->{IMG}, $x, $y);
3139 my %opts = ( type => '8bit', x=>0, @_);
3141 $self->_valid_image or return;
3143 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3145 unless (defined $opts{'y'}) {
3146 $self->_set_error("missing y parameter");
3150 if ($opts{type} eq '8bit') {
3151 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3154 elsif ($opts{type} eq 'float') {
3155 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3158 elsif ($opts{type} eq 'index') {
3159 unless (i_img_type($self->{IMG})) {
3160 $self->_set_error("type => index only valid on paletted images");
3163 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3167 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3174 my %opts = ( x=>0, @_);
3176 $self->_valid_image or return;
3178 unless (defined $opts{'y'}) {
3179 $self->_set_error("missing y parameter");
3184 if (ref $opts{pixels} && @{$opts{pixels}}) {
3185 # try to guess the type
3186 if ($opts{pixels}[0]->isa('Imager::Color')) {
3187 $opts{type} = '8bit';
3189 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3190 $opts{type} = 'float';
3193 $self->_set_error("missing type parameter and could not guess from pixels");
3199 $opts{type} = '8bit';
3203 if ($opts{type} eq '8bit') {
3204 if (ref $opts{pixels}) {
3205 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3208 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3211 elsif ($opts{type} eq 'float') {
3212 if (ref $opts{pixels}) {
3213 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3216 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3219 elsif ($opts{type} eq 'index') {
3220 if (ref $opts{pixels}) {
3221 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3224 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3228 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3235 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3237 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3239 unless (defined $opts{'y'}) {
3240 $self->_set_error("missing y parameter");
3244 unless ($opts{channels}) {
3245 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3248 if ($opts{target}) {
3249 my $target = $opts{target};
3250 my $offset = $opts{offset};
3251 if ($opts{type} eq '8bit') {
3252 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3253 $opts{y}, @{$opts{channels}})
3255 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3256 return scalar(@samples);
3258 elsif ($opts{type} eq 'float') {
3259 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3260 $opts{y}, @{$opts{channels}});
3261 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3262 return scalar(@samples);
3264 elsif ($opts{type} =~ /^(\d+)bit$/) {
3268 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3269 $opts{y}, $bits, $target,
3270 $offset, @{$opts{channels}});
3271 unless (defined $count) {
3272 $self->_set_error(Imager->_error_as_msg);
3279 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3284 if ($opts{type} eq '8bit') {
3285 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3286 $opts{y}, @{$opts{channels}});
3288 elsif ($opts{type} eq 'float') {
3289 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3290 $opts{y}, @{$opts{channels}});
3292 elsif ($opts{type} =~ /^(\d+)bit$/) {
3296 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3297 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3302 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3310 my %opts = ( x => 0, offset => 0, @_ );
3312 unless ($self->{IMG}) {
3313 $self->_set_error('setsamples: empty input image');
3317 unless(defined $opts{data} && ref $opts{data}) {
3318 $self->_set_error('setsamples: data parameter missing or invalid');
3322 unless ($opts{channels}) {
3323 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3326 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3327 $self->_set_error('setsamples: type parameter missing or invalid');
3332 unless (defined $opts{width}) {
3333 $opts{width} = $self->getwidth() - $opts{x};
3336 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3337 $opts{channels}, $opts{data}, $opts{offset},
3339 unless (defined $count) {
3340 $self->_set_error(Imager->_error_as_msg);
3347 # make an identity matrix of the given size
3351 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3352 for my $c (0 .. ($size-1)) {
3353 $matrix->[$c][$c] = 1;
3358 # general function to convert an image
3360 my ($self, %opts) = @_;
3363 unless (defined wantarray) {
3364 my @caller = caller;
3365 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3369 # the user can either specify a matrix or preset
3370 # the matrix overrides the preset
3371 if (!exists($opts{matrix})) {
3372 unless (exists($opts{preset})) {
3373 $self->{ERRSTR} = "convert() needs a matrix or preset";
3377 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3378 # convert to greyscale, keeping the alpha channel if any
3379 if ($self->getchannels == 3) {
3380 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3382 elsif ($self->getchannels == 4) {
3383 # preserve the alpha channel
3384 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3389 $matrix = _identity($self->getchannels);
3392 elsif ($opts{preset} eq 'noalpha') {
3393 # strip the alpha channel
3394 if ($self->getchannels == 2 or $self->getchannels == 4) {
3395 $matrix = _identity($self->getchannels);
3396 pop(@$matrix); # lose the alpha entry
3399 $matrix = _identity($self->getchannels);
3402 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3404 $matrix = [ [ 1 ] ];
3406 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3407 $matrix = [ [ 0, 1 ] ];
3409 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3410 $matrix = [ [ 0, 0, 1 ] ];
3412 elsif ($opts{preset} eq 'alpha') {
3413 if ($self->getchannels == 2 or $self->getchannels == 4) {
3414 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3417 # the alpha is just 1 <shrug>
3418 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3421 elsif ($opts{preset} eq 'rgb') {
3422 if ($self->getchannels == 1) {
3423 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3425 elsif ($self->getchannels == 2) {
3426 # preserve the alpha channel
3427 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3430 $matrix = _identity($self->getchannels);
3433 elsif ($opts{preset} eq 'addalpha') {
3434 if ($self->getchannels == 1) {
3435 $matrix = _identity(2);
3437 elsif ($self->getchannels == 3) {
3438 $matrix = _identity(4);
3441 $matrix = _identity($self->getchannels);
3445 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3451 $matrix = $opts{matrix};
3454 my $new = Imager->new;
3455 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3456 unless ($new->{IMG}) {
3457 # most likely a bad matrix
3458 $self->{ERRSTR} = _error_as_msg();
3464 # combine channels from multiple input images, a class method
3466 my ($class, %opts) = @_;
3468 my $src = delete $opts{src};
3470 $class->_set_error("src parameter missing");
3475 for my $img (@$src) {
3476 unless (eval { $img->isa("Imager") }) {
3477 $class->_set_error("src must contain image objects");
3480 unless ($img->{IMG}) {
3481 $class->_set_error("empty input image");
3484 push @imgs, $img->{IMG};
3487 if (my $channels = delete $opts{channels}) {
3488 $result = i_combine(\@imgs, $channels);
3491 $result = i_combine(\@imgs);
3494 $class->_set_error($class->_error_as_msg);
3498 my $img = $class->new;
3499 $img->{IMG} = $result;
3505 # general function to map an image through lookup tables
3508 my ($self, %opts) = @_;
3509 my @chlist = qw( red green blue alpha );
3511 if (!exists($opts{'maps'})) {
3512 # make maps from channel maps
3514 for $chnum (0..$#chlist) {
3515 if (exists $opts{$chlist[$chnum]}) {
3516 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3517 } elsif (exists $opts{'all'}) {
3518 $opts{'maps'}[$chnum] = $opts{'all'};
3522 if ($opts{'maps'} and $self->{IMG}) {
3523 i_map($self->{IMG}, $opts{'maps'} );
3529 my ($self, %opts) = @_;
3531 defined $opts{mindist} or $opts{mindist} = 0;
3533 defined $opts{other}
3534 or return $self->_set_error("No 'other' parameter supplied");
3535 defined $opts{other}{IMG}
3536 or return $self->_set_error("No image data in 'other' image");
3539 or return $self->_set_error("No image data");
3541 my $result = Imager->new;
3542 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3544 or return $self->_set_error($self->_error_as_msg());
3549 # destructive border - image is shrunk by one pixel all around
3552 my ($self,%opts)=@_;
3553 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3554 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3558 # Get the width of an image
3563 if (my $raw = $self->{IMG}) {
3564 return i_img_get_width($raw);
3567 $self->{ERRSTR} = 'image is empty'; return undef;
3571 # Get the height of an image
3576 if (my $raw = $self->{IMG}) {
3577 return i_img_get_height($raw);
3580 $self->{ERRSTR} = 'image is empty'; return undef;
3584 # Get number of channels in an image
3588 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3589 return i_img_getchannels($self->{IMG});
3596 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3597 return i_img_getmask($self->{IMG});
3605 if (!defined($self->{IMG})) {
3606 $self->{ERRSTR} = 'image is empty';
3609 unless (defined $opts{mask}) {
3610 $self->_set_error("mask parameter required");
3613 i_img_setmask( $self->{IMG} , $opts{mask} );
3618 # Get number of colors in an image
3622 my %opts=('maxcolors'=>2**30,@_);
3623 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3624 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3625 return ($rc==-1? undef : $rc);
3628 # Returns a reference to a hash. The keys are colour named (packed) and the
3629 # values are the number of pixels in this colour.
3630 sub getcolorusagehash {
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 my $channels= $self->getchannels;
3646 # We don't want to look at the alpha channel, because some gifs using it
3647 # doesn't define it for every colour (but only for some)
3648 $channels -= 1 if $channels == 2 or $channels == 4;
3650 my $height = $self->getheight;
3651 for my $y (0 .. $height - 1) {
3652 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3653 while (length $colors) {
3654 $color_use{ substr($colors, 0, $channels, '') }++;
3656 keys %color_use > $max_colors
3662 # This will return a ordered array of the colour usage. Kind of the sorted
3663 # version of the values of the hash returned by getcolorusagehash.
3664 # You might want to add safety checks and change the names, etc...
3668 my %opts = ( maxcolors => 2**30, @_ );
3669 my $max_colors = $opts{maxcolors};
3670 unless (defined $max_colors && $max_colors > 0) {
3671 $self->_set_error('maxcolors must be a positive integer');
3675 unless (defined $self->{IMG}) {
3676 $self->_set_error('empty input image');
3680 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3683 # draw string to an image
3687 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3689 my %input=('x'=>0, 'y'=>0, @_);
3690 defined($input{string}) or $input{string} = $input{text};
3692 unless(defined $input{string}) {
3693 $self->{ERRSTR}="missing required parameter 'string'";
3697 unless($input{font}) {
3698 $self->{ERRSTR}="missing required parameter 'font'";
3702 unless ($input{font}->draw(image=>$self, %input)) {
3714 unless ($self->{IMG}) {
3715 $self->{ERRSTR}='empty input image';
3724 my %input=('x'=>0, 'y'=>0, @_);
3725 defined $input{string}
3726 or $input{string} = $input{text};
3728 unless(exists $input{string}) {
3729 $self->_set_error("missing required parameter 'string'");
3733 unless($input{font}) {
3734 $self->_set_error("missing required parameter 'font'");
3739 unless (@result = $input{font}->align(image=>$img, %input)) {
3743 return wantarray ? @result : $result[0];
3746 my @file_limit_names = qw/width height bytes/;
3748 sub set_file_limits {
3755 @values{@file_limit_names} = (0) x @file_limit_names;
3758 @values{@file_limit_names} = i_get_image_file_limits();
3761 for my $key (keys %values) {
3762 defined $opts{$key} and $values{$key} = $opts{$key};
3765 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3768 sub get_file_limits {
3769 i_get_image_file_limits();
3772 # Shortcuts that can be exported
3774 sub newcolor { Imager::Color->new(@_); }
3775 sub newfont { Imager::Font->new(@_); }
3777 require Imager::Color::Float;
3778 return Imager::Color::Float->new(@_);
3781 *NC=*newcolour=*newcolor;
3788 #### Utility routines
3791 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3795 my ($self, $msg) = @_;
3798 $self->{ERRSTR} = $msg;
3806 # Default guess for the type of an image from extension
3808 sub def_guess_type {
3811 $ext=($name =~ m/\.([^\.]+)$/)[0];
3812 return 'tiff' if ($ext =~ m/^tiff?$/);
3813 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3814 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3815 return 'png' if ($ext eq "png");
3816 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3817 return 'tga' if ($ext eq "tga");
3818 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3819 return 'gif' if ($ext eq "gif");
3820 return 'raw' if ($ext eq "raw");
3821 return lc $ext; # best guess
3826 return @combine_types;
3829 # get the minimum of a list
3833 for(@_) { if ($_<$mx) { $mx=$_; }}
3837 # get the maximum of a list
3841 for(@_) { if ($_>$mx) { $mx=$_; }}
3845 # string stuff for iptc headers
3849 $str = substr($str,3);
3850 $str =~ s/[\n\r]//g;
3857 # A little hack to parse iptc headers.
3862 my($caption,$photogr,$headln,$credit);
3864 my $str=$self->{IPTCRAW};
3869 @ar=split(/8BIM/,$str);
3874 @sar=split(/\034\002/);
3875 foreach $item (@sar) {
3876 if ($item =~ m/^x/) {
3877 $caption = _clean($item);
3880 if ($item =~ m/^P/) {
3881 $photogr = _clean($item);
3884 if ($item =~ m/^i/) {
3885 $headln = _clean($item);
3888 if ($item =~ m/^n/) {
3889 $credit = _clean($item);
3895 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3902 or die "Only C language supported";
3904 require Imager::ExtUtils;
3905 return Imager::ExtUtils->inline_config;
3908 # threads shouldn't try to close raw Imager objects
3909 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3912 # this serves two purposes:
3913 # - a class method to load the file support modules included with Image
3914 # (or were included, once the library dependent modules are split out)
3915 # - something for Module::ScanDeps to analyze
3916 # https://rt.cpan.org/Ticket/Display.html?id=6566
3918 eval { require Imager::File::GIF };
3919 eval { require Imager::File::JPEG };
3920 eval { require Imager::File::PNG };
3921 eval { require Imager::File::SGI };
3922 eval { require Imager::File::TIFF };
3923 eval { require Imager::File::ICO };
3924 eval { require Imager::Font::W32 };
3925 eval { require Imager::Font::FT2 };
3926 eval { require Imager::Font::T1 };
3929 # backward compatibility for %formats
3930 package Imager::FORMATS;
3932 use constant IX_FORMATS => 0;
3933 use constant IX_LIST => 1;
3934 use constant IX_INDEX => 2;
3935 use constant IX_CLASSES => 3;
3938 my ($class, $formats, $classes) = @_;
3940 return bless [ $formats, [ ], 0, $classes ], $class;
3944 my ($self, $key) = @_;
3946 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
3948 if (eval { require $file; 1 }) {
3954 $self->[IX_FORMATS]{$key} = $value;
3960 my ($self, $key) = @_;
3962 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
3964 $self->[IX_CLASSES]{$key} or return undef;
3966 return $self->_check($key);
3970 die "%Imager::formats is not user monifiable";
3974 die "%Imager::formats is not user monifiable";
3978 die "%Imager::formats is not user monifiable";
3982 my ($self, $key) = @_;
3984 if (exists $self->[IX_FORMATS]{$key}) {
3985 my $value = $self->[IX_FORMATS]{$key}
3990 $self->_check($key) or return 1==0;
3998 unless (@{$self->[IX_LIST]}) {
4000 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4001 keys %{$self->[IX_FORMATS]};
4003 for my $key (keys %{$self->[IX_CLASSES]}) {
4004 $self->[IX_FORMATS]{$key} and next;
4006 and push @{$self->[IX_LIST]}, $key;
4010 @{$self->[IX_LIST]} or return;
4011 $self->[IX_INDEX] = 1;
4012 return $self->[IX_LIST][0];
4018 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4021 return $self->[IX_LIST][$self->[IX_INDEX]++];
4027 return scalar @{$self->[IX_LIST]};
4032 # Below is the stub of documentation for your module. You better edit it!
4036 Imager - Perl extension for Generating 24 bit Images
4046 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4051 # see Imager::Files for information on the read() method
4052 my $img = Imager->new(file=>$file)
4053 or die Imager->errstr();
4055 $file =~ s/\.[^.]*$//;
4057 # Create smaller version
4058 # documented in Imager::Transformations
4059 my $thumb = $img->scale(scalefactor=>.3);
4061 # Autostretch individual channels
4062 $thumb->filter(type=>'autolevels');
4064 # try to save in one of these formats
4067 for $format ( qw( png gif jpeg tiff ppm ) ) {
4068 # Check if given format is supported
4069 if ($Imager::formats{$format}) {
4070 $file.="_low.$format";
4071 print "Storing image as: $file\n";
4072 # documented in Imager::Files
4073 $thumb->write(file=>$file) or
4081 Imager is a module for creating and altering images. It can read and
4082 write various image formats, draw primitive shapes like lines,and
4083 polygons, blend multiple images together in various ways, scale, crop,
4084 render text and more.
4086 =head2 Overview of documentation
4092 Imager - This document - Synopsis, Example, Table of Contents and
4097 L<Imager::Tutorial> - a brief introduction to Imager.
4101 L<Imager::Cookbook> - how to do various things with Imager.
4105 L<Imager::ImageTypes> - Basics of constructing image objects with
4106 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4107 8/16/double bits/channel, color maps, channel masks, image tags, color
4108 quantization. Also discusses basic image information methods.
4112 L<Imager::Files> - IO interaction, reading/writing images, format
4117 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4122 L<Imager::Color> - Color specification.
4126 L<Imager::Fill> - Fill pattern specification.
4130 L<Imager::Font> - General font rendering, bounding boxes and font
4135 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4136 blending, pasting, convert and map.
4140 L<Imager::Engines> - Programmable transformations through
4141 C<transform()>, C<transform2()> and C<matrix_transform()>.
4145 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4150 L<Imager::Expr> - Expressions for evaluation engine used by
4155 L<Imager::Matrix2d> - Helper class for affine transformations.
4159 L<Imager::Fountain> - Helper for making gradient profiles.
4163 L<Imager::API> - using Imager's C API
4167 L<Imager::APIRef> - API function reference
4171 L<Imager::Inline> - using Imager's C API from Inline::C
4175 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4179 =head2 Basic Overview
4181 An Image object is created with C<$img = Imager-E<gt>new()>.
4184 $img=Imager->new(); # create empty image
4185 $img->read(file=>'lena.png',type=>'png') or # read image from file
4186 die $img->errstr(); # give an explanation
4187 # if something failed
4189 or if you want to create an empty image:
4191 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4193 This example creates a completely black image of width 400 and height
4196 =head1 ERROR HANDLING
4198 In general a method will return false when it fails, if it does use
4199 the C<errstr()> method to find out why:
4205 Returns the last error message in that context.
4207 If the last error you received was from calling an object method, such
4208 as read, call errstr() as an object method to find out why:
4210 my $image = Imager->new;
4211 $image->read(file => 'somefile.gif')
4212 or die $image->errstr;
4214 If it was a class method then call errstr() as a class method:
4216 my @imgs = Imager->read_multi(file => 'somefile.gif')
4217 or die Imager->errstr;
4219 Note that in some cases object methods are implemented in terms of
4220 class methods so a failing object method may set both.
4224 The C<Imager-E<gt>new> method is described in detail in
4225 L<Imager::ImageTypes>.
4229 Where to find information on methods for Imager class objects.
4231 addcolors() - L<Imager::ImageTypes/addcolors> - add colors to a
4234 addtag() - L<Imager::ImageTypes/addtag> - add image tags
4236 align_string() - L<Imager::Draw/align_string> - draw text aligned on a
4239 arc() - L<Imager::Draw/arc> - draw a filled arc
4241 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
4244 box() - L<Imager::Draw/box> - draw a filled or outline box.
4246 circle() - L<Imager::Draw/circle> - draw a filled circle
4248 colorcount() - L<Imager::Draw/colorcount> - the number of colors in an
4249 image's palette (paletted images only)
4251 combine() - L<Imager::Transformations/combine> - combine channels from one or
4254 combines() - L<Imager::Draw/combines> - return a list of the different
4255 combine type keywords
4257 compose() - L<Imager::Transformations/compose> - compose one image
4260 convert() - L<Imager::Transformations/"Color transformations"> -
4261 transform the color space
4263 copy() - L<Imager::Transformations/copy> - make a duplicate of an
4266 crop() - L<Imager::Transformations/crop> - extract part of an image
4268 def_guess_type() - L<Imager::Files/def_guess_type> - default function
4269 used to guess the output file format based on the output file name
4271 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
4273 difference() - L<Imager::Filters/"Image Difference"> - produce a
4274 difference images from two input images.
4276 errstr() - L<"Basic Overview"> - the error from the last failed
4279 filter() - L<Imager::Filters> - image filtering
4281 findcolor() - L<Imager::ImageTypes/findcolor> - search the image
4282 palette, if it has one
4284 flip() - L<Imager::Transformations/flip> - flip an image, vertically,
4287 flood_fill() - L<Imager::Draw/flood_fill> - fill an enclosed or same
4290 getchannels() - L<Imager::ImageTypes/getchannels> - the number of
4291 samples per pixel for an image
4293 getcolorcount() - L<Imager::ImageTypes/getcolorcount> - the number of
4294 different colors used by an image (works for direct color images)
4296 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
4297 palette, if it has one
4299 getcolorusage() - L<Imager::ImageTypes/getcolorusage>
4301 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
4303 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4305 getheight() - L<Imager::ImageTypes/getwidth> - height of the image in
4308 getmask() - L<Imager::ImageTypes/getmask> - write mask for the image
4310 getpixel() - L<Imager::Draw/getpixel> - retrieve one or more pixel
4313 getsamples() - L<Imager::Draw/getsamples> - retrieve samples from a
4314 row or partial row of pixels.
4316 getscanline() - L<Imager::Draw/getscanline> - retrieve colors for a
4317 row or partial row of pixels.
4319 getwidth() - L<Imager::ImageTypes/getwidth> - width of the image in
4322 img_set() - L<Imager::ImageTypes/img_set> - re-use an Imager object
4325 init() - L<Imager::ImageTypes/init>
4327 is_bilevel() - L<Imager::ImageTypes/is_bilevel> - returns whether
4328 image write functions should write the image in their bilevel (blank
4329 and white, no gray levels) format
4331 line() - L<Imager::Draw/line> - draw an interval
4333 load_plugin() - L<Imager::Filters/load_plugin>
4335 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4338 masked() - L<Imager::ImageTypes/masked> - make a masked image
4340 matrix_transform() - L<Imager::Engines/matrix_transform>
4342 maxcolors() - L<Imager::ImageTypes/maxcolors>
4344 NC() - L<Imager::Handy/NC>
4346 NCF() - L<Imager::Handy/NCF>
4348 new() - L<Imager::ImageTypes/new>
4350 newcolor() - L<Imager::Handy/newcolor>
4352 newcolour() - L<Imager::Handy/newcolour>
4354 newfont() - L<Imager::Handy/newfont>
4356 NF() - L<Imager::Handy/NF>
4358 open() - L<Imager::Files> - an alias for read()
4362 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
4365 paste() - L<Imager::Transformations/paste> - draw an image onto an image
4367 polygon() - L<Imager::Draw/polygon>
4369 polyline() - L<Imager::Draw/polyline>
4371 preload() - L<Imager::Files/preload>
4373 read() - L<Imager::Files> - read a single image from an image file
4375 read_multi() - L<Imager::Files> - read multiple images from an image
4378 read_types() - L<Imager::Files/read_types> - list image types Imager
4381 register_filter() - L<Imager::Filters/register_filter>
4383 register_reader() - L<Imager::Files/register_reader>
4385 register_writer() - L<Imager::Files/register_writer>
4387 rotate() - L<Imager::Transformations/rotate>
4389 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
4390 image and use the alpha channel
4392 scale() - L<Imager::Transformations/scale>
4394 scale_calculate() - L<Imager::Transformations/scale_calculate>
4396 scaleX() - L<Imager::Transformations/scaleX>
4398 scaleY() - L<Imager::Transformations/scaleY>
4400 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
4403 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4405 setmask() - L<Imager::ImageTypes/setmask>
4407 setpixel() - L<Imager::Draw/setpixel>
4409 setsamples() - L<Imager::Draw/setsamples>
4411 setscanline() - L<Imager::Draw/setscanline>
4413 settag() - L<Imager::ImageTypes/settag>
4415 string() - L<Imager::Draw/string> - draw text on an image
4417 tags() - L<Imager::ImageTypes/tags> - fetch image tags
4419 to_paletted() - L<Imager::ImageTypes/to_paletted>
4421 to_rgb16() - L<Imager::ImageTypes/to_rgb16>
4423 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
4425 transform() - L<Imager::Engines/"transform">
4427 transform2() - L<Imager::Engines/"transform2">
4429 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
4431 unload_plugin() - L<Imager::Filters/unload_plugin>
4433 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
4436 write() - L<Imager::Files> - write an image to a file
4438 write_multi() - L<Imager::Files> - write multiple image to an image
4441 write_types() - L<Imager::Files/read_types> - list image types Imager
4444 =head1 CONCEPT INDEX
4446 animated GIF - L<Imager::Files/"Writing an animated GIF">
4448 aspect ratio - L<Imager::ImageTypes/i_xres>,
4449 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
4451 blend - alpha blending one image onto another
4452 L<Imager::Transformations/rubthrough>
4454 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
4456 boxes, drawing - L<Imager::Draw/box>
4458 changes between image - L<Imager::Filters/"Image Difference">
4460 channels, combine into one image - L<Imager::Transformations/combine>
4462 color - L<Imager::Color>
4464 color names - L<Imager::Color>, L<Imager::Color::Table>
4466 combine modes - L<Imager::Draw/"Combine Types">
4468 compare images - L<Imager::Filters/"Image Difference">
4470 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4472 convolution - L<Imager::Filters/conv>
4474 cropping - L<Imager::Transformations/crop>
4476 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4478 C<diff> images - L<Imager::Filters/"Image Difference">
4480 dpi - L<Imager::ImageTypes/i_xres>,
4481 L<Imager::Cookbook/"Image spatial resolution">
4483 drawing boxes - L<Imager::Draw/box>
4485 drawing lines - L<Imager::Draw/line>
4487 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
4489 error message - L<"ERROR HANDLING">
4491 files, font - L<Imager::Font>
4493 files, image - L<Imager::Files>
4495 filling, types of fill - L<Imager::Fill>
4497 filling, boxes - L<Imager::Draw/box>
4499 filling, flood fill - L<Imager::Draw/flood_fill>
4501 flood fill - L<Imager::Draw/flood_fill>
4503 fonts - L<Imager::Font>
4505 fonts, drawing with - L<Imager::Draw/string>,
4506 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
4508 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4510 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4512 fountain fill - L<Imager::Fill/"Fountain fills">,
4513 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4514 L<Imager::Filters/gradgen>
4516 GIF files - L<Imager::Files/"GIF">
4518 GIF files, animated - L<Imager::File/"Writing an animated GIF">
4520 gradient fill - L<Imager::Fill/"Fountain fills">,
4521 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4522 L<Imager::Filters/gradgen>
4524 gray scale, convert image to - L<Imager::Transformations/convert>
4526 guassian blur - L<Imager::Filters/guassian>
4528 hatch fills - L<Imager::Fill/"Hatched fills">
4530 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4532 invert image - L<Imager::Filters/hardinvert>,
4533 L<Imager::Filters/hardinvertall>
4535 JPEG - L<Imager::Files/"JPEG">
4537 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4539 lines, drawing - L<Imager::Draw/line>
4541 matrix - L<Imager::Matrix2d>,
4542 L<Imager::Transformations/"Matrix Transformations">,
4543 L<Imager::Font/transform>
4545 metadata, image - L<Imager::ImageTypes/"Tags">
4547 mosaic - L<Imager::Filters/mosaic>
4549 noise, filter - L<Imager::Filters/noise>
4551 noise, rendered - L<Imager::Filters/turbnoise>,
4552 L<Imager::Filters/radnoise>
4554 paste - L<Imager::Transformations/paste>,
4555 L<Imager::Transformations/rubthrough>
4557 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
4558 L<Imager::ImageTypes/new>
4560 =for stopwords posterize
4562 posterize - L<Imager::Filters/postlevels>
4564 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4566 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4568 rectangles, drawing - L<Imager::Draw/box>
4570 resizing an image - L<Imager::Transformations/scale>,
4571 L<Imager::Transformations/crop>
4573 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4575 saving an image - L<Imager::Files>
4577 scaling - L<Imager::Transformations/scale>
4579 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4581 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4583 size, image - L<Imager::ImageTypes/getwidth>,
4584 L<Imager::ImageTypes/getheight>
4586 size, text - L<Imager::Font/bounding_box>
4588 tags, image metadata - L<Imager::ImageTypes/"Tags">
4590 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
4591 L<Imager::Font::Wrap>
4593 text, wrapping text in an area - L<Imager::Font::Wrap>
4595 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
4597 tiles, color - L<Imager::Filters/mosaic>
4599 transparent images - L<Imager::ImageTypes>,
4600 L<Imager::Cookbook/"Transparent PNG">
4602 =for stopwords unsharp
4604 unsharp mask - L<Imager::Filters/unsharpmask>
4606 watermark - L<Imager::Filters/watermark>
4608 writing an image to a file - L<Imager::Files>
4612 Imager doesn't support perl threads.
4614 Imager has limited code to prevent double frees if you create images,
4615 colors etc, and then create a thread, but has no code to prevent two
4616 threads entering Imager's error handling code, and none is likely to
4621 The best place to get help with Imager is the mailing list.
4623 To subscribe send a message with C<subscribe> in the body to:
4625 imager-devel+request@molar.is
4631 L<http://www.molar.is/en/lists/imager-devel/>
4635 where you can also find the mailing list archive.
4637 You can report bugs by pointing your browser at:
4641 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4645 or by sending an email to:
4649 bug-Imager@rt.cpan.org
4653 Please remember to include the versions of Imager, perl, supporting
4654 libraries, and any relevant code. If you have specific images that
4655 cause the problems, please include those too.
4657 If you don't want to publish your email address on a mailing list you
4658 can use CPAN::Forum:
4660 http://www.cpanforum.com/dist/Imager
4662 You will need to register to post.
4664 =head1 CONTRIBUTING TO IMAGER
4670 If you like or dislike Imager, you can add a public review of Imager
4673 http://cpanratings.perl.org/dist/Imager
4675 =for stopwords Bitcard
4677 This requires a Bitcard account (http://www.bitcard.org).
4679 You can also send email to the maintainer below.
4681 If you send me a bug report via email, it will be copied to Request
4686 I accept patches, preferably against the main branch in subversion.
4687 You should include an explanation of the reason for why the patch is
4690 Your patch should include regression tests where possible, otherwise
4691 it will be delayed until I get a chance to write them.
4695 Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
4697 Arnar M. Hrafnkelsson is the original author of Imager.
4699 Many others have contributed to Imager, please see the C<README> for a
4704 Imager is licensed under the same terms as perl itself.
4707 makeblendedfont Fontforge
4709 A test font, FT2/fontfiles/MMOne.pfb, contains a Postscript operator
4710 definition copyrighted by Adobe. See F<adobe.txt> in the source for
4711 license information.
4715 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4716 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4717 L<Imager::Font>(3), L<Imager::Transformations>(3),
4718 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4719 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4721 L<http://imager.perl.org/>
4723 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4725 Other perl imaging modules include:
4727 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).