4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
113 # registered file readers
116 # registered file writers
119 # modules we attempted to autoload
120 my %attempted_to_load;
122 # library keys that are image file formats
123 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
125 # image pixel combine types
127 qw/none normal multiply dissolve add subtract diff lighten darken
128 hue saturation value color/;
130 @combine_types{@combine_types} = 0 .. $#combine_types;
131 $combine_types{mult} = $combine_types{multiply};
132 $combine_types{'sub'} = $combine_types{subtract};
133 $combine_types{sat} = $combine_types{saturation};
135 # this will be used to store global defaults at some point
140 if ($Exporter::VERSION < 5.57) {
146 XSLoader::load(Imager => $VERSION);
150 push @ISA, 'DynaLoader';
151 bootstrap Imager $VERSION;
158 png => "Imager::File::PNG",
159 gif => "Imager::File::GIF",
160 tiff => "Imager::File::TIFF",
161 jpeg => "Imager::File::JPEG",
162 w32 => "Imager::Font::W32",
163 ft2 => "Imager::Font::FT2",
164 t1 => "Imager::Font::T1",
167 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
170 for(i_list_formats()) { $formats_low{$_}++; }
172 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
176 # the members of the subhashes under %filters are:
177 # callseq - a list of the parameters to the underlying filter in the
178 # order they are passed
179 # callsub - a code ref that takes a named parameter list and calls the
181 # defaults - a hash of default values
182 # names - defines names for value of given parameters so if the names
183 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
184 # foo parameter, the filter will receive 1 for the foo
187 callseq => ['image','intensity'],
188 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
192 callseq => ['image', 'amount', 'subtype'],
193 defaults => { amount=>3,subtype=>0 },
194 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
197 $filters{hardinvert} ={
198 callseq => ['image'],
200 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
203 $filters{hardinvertall} =
205 callseq => ['image'],
207 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
210 $filters{autolevels} ={
211 callseq => ['image','lsat','usat','skew'],
212 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
213 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
216 $filters{turbnoise} ={
217 callseq => ['image'],
218 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
219 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
222 $filters{radnoise} ={
223 callseq => ['image'],
224 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
225 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
230 callseq => ['image', 'coef'],
235 i_conv($hsh{image},$hsh{coef})
236 or die Imager->_error_as_msg() . "\n";
242 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
243 defaults => { dist => 0 },
247 my @colors = @{$hsh{colors}};
250 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
254 $filters{nearest_color} =
256 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
261 # make sure the segments are specified with colors
263 for my $color (@{$hsh{colors}}) {
264 my $new_color = _color($color)
265 or die $Imager::ERRSTR."\n";
266 push @colors, $new_color;
269 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
271 or die Imager->_error_as_msg() . "\n";
274 $filters{gaussian} = {
275 callseq => [ 'image', 'stddev' ],
277 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
281 callseq => [ qw(image size) ],
282 defaults => { size => 20 },
283 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
287 callseq => [ qw(image bump elevation lightx lighty st) ],
288 defaults => { elevation=>0, st=> 2 },
291 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
292 $hsh{lightx}, $hsh{lighty}, $hsh{st});
295 $filters{bumpmap_complex} =
297 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
314 for my $cname (qw/Ia Il Is/) {
315 my $old = $hsh{$cname};
316 my $new_color = _color($old)
317 or die $Imager::ERRSTR, "\n";
318 $hsh{$cname} = $new_color;
320 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
321 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
322 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
326 $filters{postlevels} =
328 callseq => [ qw(image levels) ],
329 defaults => { levels => 10 },
330 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
332 $filters{watermark} =
334 callseq => [ qw(image wmark tx ty pixdiff) ],
335 defaults => { pixdiff=>10, tx=>0, ty=>0 },
339 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
345 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
347 ftype => { linear => 0,
353 repeat => { none => 0,
368 multiply => 2, mult => 2,
371 subtract => 5, 'sub' => 5,
381 defaults => { ftype => 0, repeat => 0, combine => 0,
382 super_sample => 0, ssample_param => 4,
395 # make sure the segments are specified with colors
397 for my $segment (@{$hsh{segments}}) {
398 my @new_segment = @$segment;
400 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
401 push @segments, \@new_segment;
404 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
405 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
406 $hsh{ssample_param}, \@segments)
407 or die Imager->_error_as_msg() . "\n";
410 $filters{unsharpmask} =
412 callseq => [ qw(image stddev scale) ],
413 defaults => { stddev=>2.0, scale=>1.0 },
417 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
421 $FORMATGUESS=\&def_guess_type;
431 # NOTE: this might be moved to an import override later on
436 if ($_[$i] eq '-log-stderr') {
444 goto &Exporter::import;
448 Imager->open_log(log => $_[0], level => $_[1]);
453 my %parms=(loglevel=>1,@_);
455 Imager->open_log(log => $parms{log}, level => $parms{loglevel});
458 if (exists $parms{'warn_obsolete'}) {
459 $warn_obsolete = $parms{'warn_obsolete'};
462 if (exists $parms{'t1log'}) {
464 Imager::Font::T1::i_init_t1($parms{'t1log'});
474 my (%opts) = ( loglevel => 1, @_ );
476 $is_logging = i_init_log($opts{log}, $opts{loglevel});
477 unless ($is_logging) {
478 Imager->_set_error(Imager->_error_as_msg());
482 Imager->log("Imager $VERSION starting\n", 1);
488 i_init_log(undef, -1);
493 my ($class, $message, $level) = @_;
495 defined $level or $level = 1;
497 i_log_entry($message, $level);
507 print "shutdown code\n";
508 # for(keys %instances) { $instances{$_}->DESTROY(); }
509 malloc_state(); # how do decide if this should be used? -- store something from the import
510 print "Imager exiting\n";
514 # Load a filter plugin
519 my ($DSO_handle,$str)=DSO_open($filename);
520 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
521 my %funcs=DSO_funclist($DSO_handle);
522 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
524 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
526 $DSOs{$filename}=[$DSO_handle,\%funcs];
529 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
530 $DEBUG && print "eval string:\n",$evstr,"\n";
542 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
543 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
544 for(keys %{$funcref}) {
546 $DEBUG && print "unloading: $_\n";
548 my $rc=DSO_close($DSO_handle);
549 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
553 # take the results of i_error() and make a message out of it
555 return join(": ", map $_->[0], i_errors());
558 # this function tries to DWIM for color parameters
559 # color objects are used as is
560 # simple scalars are simply treated as single parameters to Imager::Color->new
561 # hashrefs are treated as named argument lists to Imager::Color->new
562 # arrayrefs are treated as list arguments to Imager::Color->new iff any
564 # other arrayrefs are treated as list arguments to Imager::Color::Float
568 # perl 5.6.0 seems to do weird things to $arg if we don't make an
569 # explicitly stringified copy
570 # I vaguely remember a bug on this on p5p, but couldn't find it
571 # through bugs.perl.org (I had trouble getting it to find any bugs)
572 my $copy = $arg . "";
576 if (UNIVERSAL::isa($arg, "Imager::Color")
577 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
581 if ($copy =~ /^HASH\(/) {
582 $result = Imager::Color->new(%$arg);
584 elsif ($copy =~ /^ARRAY\(/) {
585 $result = Imager::Color->new(@$arg);
588 $Imager::ERRSTR = "Not a color";
593 # assume Imager::Color::new knows how to handle it
594 $result = Imager::Color->new($arg);
601 my ($self, $combine, $default) = @_;
603 if (!defined $combine && ref $self) {
604 $combine = $self->{combine};
606 defined $combine or $combine = $defaults{combine};
607 defined $combine or $combine = $default;
609 if (exists $combine_types{$combine}) {
610 $combine = $combine_types{$combine};
619 $self->{IMG} and return 1;
621 $self->_set_error('empty input image');
626 # returns first defined parameter
629 return $_ if defined $_;
635 # Methods to be called on objects.
638 # Create a new Imager object takes very few parameters.
639 # usually you call this method and then call open from
640 # the resulting object
647 $self->{IMG}=undef; # Just to indicate what exists
648 $self->{ERRSTR}=undef; #
649 $self->{DEBUG}=$DEBUG;
650 $self->{DEBUG} and print "Initialized Imager\n";
651 if (defined $hsh{xsize} || defined $hsh{ysize}) {
652 unless ($self->img_set(%hsh)) {
653 $Imager::ERRSTR = $self->{ERRSTR};
657 elsif (defined $hsh{file} ||
660 defined $hsh{callback} ||
661 defined $hsh{readcb} ||
662 defined $hsh{data}) {
663 # allow $img = Imager->new(file => $filename)
666 # type is already used as a parameter to new(), rename it for the
668 if ($hsh{filetype}) {
669 $extras{type} = $hsh{filetype};
671 unless ($self->read(%hsh, %extras)) {
672 $Imager::ERRSTR = $self->{ERRSTR};
680 # Copy an entire image with no changes
681 # - if an image has magic the copy of it will not be magical
685 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
687 unless (defined wantarray) {
689 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
693 my $newcopy=Imager->new();
694 $newcopy->{IMG} = i_copy($self->{IMG});
703 unless ($self->{IMG}) {
704 $self->_set_error('empty input image');
707 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
708 my $src = $input{img} || $input{src};
710 $self->_set_error("no source image");
713 $input{left}=0 if $input{left} <= 0;
714 $input{top}=0 if $input{top} <= 0;
716 my($r,$b)=i_img_info($src->{IMG});
717 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
718 my ($src_right, $src_bottom);
719 if ($input{src_coords}) {
720 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
723 if (defined $input{src_maxx}) {
724 $src_right = $input{src_maxx};
726 elsif (defined $input{width}) {
727 if ($input{width} <= 0) {
728 $self->_set_error("paste: width must me positive");
731 $src_right = $src_left + $input{width};
736 if (defined $input{src_maxy}) {
737 $src_bottom = $input{src_maxy};
739 elsif (defined $input{height}) {
740 if ($input{height} < 0) {
741 $self->_set_error("paste: height must be positive");
744 $src_bottom = $src_top + $input{height};
751 $src_right > $r and $src_right = $r;
752 $src_bottom > $b and $src_bottom = $b;
754 if ($src_right <= $src_left
755 || $src_bottom < $src_top) {
756 $self->_set_error("nothing to paste");
760 i_copyto($self->{IMG}, $src->{IMG},
761 $src_left, $src_top, $src_right, $src_bottom,
762 $input{left}, $input{top});
764 return $self; # What should go here??
767 # Crop an image - i.e. return a new image that is smaller
771 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
773 unless (defined wantarray) {
775 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
781 my ($w, $h, $l, $r, $b, $t) =
782 @hsh{qw(width height left right bottom top)};
784 # work through the various possibilities
789 elsif (!defined $r) {
790 $r = $self->getwidth;
802 $l = int(0.5+($self->getwidth()-$w)/2);
807 $r = $self->getwidth;
813 elsif (!defined $b) {
814 $b = $self->getheight;
826 $t=int(0.5+($self->getheight()-$h)/2);
831 $b = $self->getheight;
834 ($l,$r)=($r,$l) if $l>$r;
835 ($t,$b)=($b,$t) if $t>$b;
838 $r > $self->getwidth and $r = $self->getwidth;
840 $b > $self->getheight and $b = $self->getheight;
842 if ($l == $r || $t == $b) {
843 $self->_set_error("resulting image would have no content");
846 if( $r < $l or $b < $t ) {
847 $self->_set_error("attempting to crop outside of the image");
850 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
852 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
857 my ($self, %opts) = @_;
859 $self->{IMG} or return $self->_set_error("Not a valid image");
861 my $x = $opts{xsize} || $self->getwidth;
862 my $y = $opts{ysize} || $self->getheight;
863 my $channels = $opts{channels} || $self->getchannels;
865 my $out = Imager->new;
866 if ($channels == $self->getchannels) {
867 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
870 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
872 unless ($out->{IMG}) {
873 $self->{ERRSTR} = $self->_error_as_msg;
880 # Sets an image to a certain size and channel number
881 # if there was previously data in the image it is discarded
886 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
888 if (defined($self->{IMG})) {
889 # let IIM_DESTROY destroy it, it's possible this image is
890 # referenced from a virtual image (like masked)
891 #i_img_destroy($self->{IMG});
895 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
896 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
897 $hsh{maxcolors} || 256);
899 elsif ($hsh{bits} eq 'double') {
900 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
902 elsif ($hsh{bits} == 16) {
903 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
906 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
910 unless ($self->{IMG}) {
911 $self->{ERRSTR} = Imager->_error_as_msg();
918 # created a masked version of the current image
922 $self or return undef;
923 my %opts = (left => 0,
925 right => $self->getwidth,
926 bottom => $self->getheight,
928 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
930 my $result = Imager->new;
931 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
932 $opts{top}, $opts{right} - $opts{left},
933 $opts{bottom} - $opts{top});
934 unless ($result->{IMG}) {
935 $self->_set_error(Imager->_error_as_msg);
939 # keep references to the mask and base images so they don't
941 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
946 # convert an RGB image into a paletted image
950 if (@_ != 1 && !ref $_[0]) {
957 unless (defined wantarray) {
959 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
966 my $result = Imager->new;
967 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
968 $self->_set_error(Imager->_error_as_msg);
975 # convert a paletted (or any image) to an 8-bit/channel RGB image
979 unless (defined wantarray) {
981 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
988 my $result = Imager->new;
989 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
990 $self->_set_error(Imager->_error_as_msg());
997 # convert a paletted (or any image) to a 16-bit/channel RGB image
1001 unless (defined wantarray) {
1002 my @caller = caller;
1003 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1010 my $result = Imager->new;
1011 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1012 $self->_set_error(Imager->_error_as_msg());
1019 # convert a paletted (or any image) to an double/channel RGB image
1023 unless (defined wantarray) {
1024 my @caller = caller;
1025 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1032 my $result = Imager->new;
1033 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1034 $self->_set_error(Imager->_error_as_msg());
1043 my %opts = (colors=>[], @_);
1045 unless ($self->{IMG}) {
1046 $self->_set_error("empty input image");
1050 my @colors = @{$opts{colors}}
1053 for my $color (@colors) {
1054 $color = _color($color);
1056 $self->_set_error($Imager::ERRSTR);
1061 return i_addcolors($self->{IMG}, @colors);
1066 my %opts = (start=>0, colors=>[], @_);
1068 unless ($self->{IMG}) {
1069 $self->_set_error("empty input image");
1073 my @colors = @{$opts{colors}}
1076 for my $color (@colors) {
1077 $color = _color($color);
1079 $self->_set_error($Imager::ERRSTR);
1084 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1090 if (!exists $opts{start} && !exists $opts{count}) {
1093 $opts{count} = $self->colorcount;
1095 elsif (!exists $opts{count}) {
1098 elsif (!exists $opts{start}) {
1103 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1107 i_colorcount($_[0]{IMG});
1111 i_maxcolors($_[0]{IMG});
1117 $opts{color} or return undef;
1119 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1124 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1125 if ($bits && $bits == length(pack("d", 1)) * 8) {
1134 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1140 $self->{IMG} and i_img_virtual($self->{IMG});
1146 $self->{IMG} or return;
1148 return i_img_is_monochrome($self->{IMG});
1152 my ($self, %opts) = @_;
1154 $self->{IMG} or return;
1156 if (defined $opts{name}) {
1160 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1161 push @result, (i_tags_get($self->{IMG}, $found))[1];
1164 return wantarray ? @result : $result[0];
1166 elsif (defined $opts{code}) {
1170 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1171 push @result, (i_tags_get($self->{IMG}, $found))[1];
1178 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1181 return i_tags_count($self->{IMG});
1190 return -1 unless $self->{IMG};
1192 if (defined $opts{value}) {
1193 if ($opts{value} =~ /^\d+$/) {
1195 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1198 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1201 elsif (defined $opts{data}) {
1202 # force addition as a string
1203 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1206 $self->{ERRSTR} = "No value supplied";
1210 elsif ($opts{code}) {
1211 if (defined $opts{value}) {
1212 if ($opts{value} =~ /^\d+$/) {
1214 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1217 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1220 elsif (defined $opts{data}) {
1221 # force addition as a string
1222 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1225 $self->{ERRSTR} = "No value supplied";
1238 return 0 unless $self->{IMG};
1240 if (defined $opts{'index'}) {
1241 return i_tags_delete($self->{IMG}, $opts{'index'});
1243 elsif (defined $opts{name}) {
1244 return i_tags_delbyname($self->{IMG}, $opts{name});
1246 elsif (defined $opts{code}) {
1247 return i_tags_delbycode($self->{IMG}, $opts{code});
1250 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1256 my ($self, %opts) = @_;
1259 $self->deltag(name=>$opts{name});
1260 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1262 elsif (defined $opts{code}) {
1263 $self->deltag(code=>$opts{code});
1264 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1272 sub _get_reader_io {
1273 my ($self, $input) = @_;
1276 return $input->{io}, undef;
1278 elsif ($input->{fd}) {
1279 return io_new_fd($input->{fd});
1281 elsif ($input->{fh}) {
1282 my $fd = fileno($input->{fh});
1283 unless (defined $fd) {
1284 $self->_set_error("Handle in fh option not opened");
1287 return io_new_fd($fd);
1289 elsif ($input->{file}) {
1290 my $file = IO::File->new($input->{file}, "r");
1292 $self->_set_error("Could not open $input->{file}: $!");
1296 return (io_new_fd(fileno($file)), $file);
1298 elsif ($input->{data}) {
1299 return io_new_buffer($input->{data});
1301 elsif ($input->{callback} || $input->{readcb}) {
1302 if (!$input->{seekcb}) {
1303 $self->_set_error("Need a seekcb parameter");
1305 if ($input->{maxbuffer}) {
1306 return io_new_cb($input->{writecb},
1307 $input->{callback} || $input->{readcb},
1308 $input->{seekcb}, $input->{closecb},
1309 $input->{maxbuffer});
1312 return io_new_cb($input->{writecb},
1313 $input->{callback} || $input->{readcb},
1314 $input->{seekcb}, $input->{closecb});
1318 $self->_set_error("file/fd/fh/data/callback parameter missing");
1323 sub _get_writer_io {
1324 my ($self, $input, $type) = @_;
1327 return $input->{io};
1329 elsif ($input->{fd}) {
1330 return io_new_fd($input->{fd});
1332 elsif ($input->{fh}) {
1333 my $fd = fileno($input->{fh});
1334 unless (defined $fd) {
1335 $self->_set_error("Handle in fh option not opened");
1339 my $oldfh = select($input->{fh});
1340 # flush anything that's buffered, and make sure anything else is flushed
1343 return io_new_fd($fd);
1345 elsif ($input->{file}) {
1346 my $fh = new IO::File($input->{file},"w+");
1348 $self->_set_error("Could not open file $input->{file}: $!");
1351 binmode($fh) or die;
1352 return (io_new_fd(fileno($fh)), $fh);
1354 elsif ($input->{data}) {
1355 return io_new_bufchain();
1357 elsif ($input->{callback} || $input->{writecb}) {
1358 if ($input->{maxbuffer}) {
1359 return io_new_cb($input->{callback} || $input->{writecb},
1361 $input->{seekcb}, $input->{closecb},
1362 $input->{maxbuffer});
1365 return io_new_cb($input->{callback} || $input->{writecb},
1367 $input->{seekcb}, $input->{closecb});
1371 $self->_set_error("file/fd/fh/data/callback parameter missing");
1376 # Read an image from file
1382 if (defined($self->{IMG})) {
1383 # let IIM_DESTROY do the destruction, since the image may be
1384 # referenced from elsewhere
1385 #i_img_destroy($self->{IMG});
1386 undef($self->{IMG});
1389 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1391 unless ($input{'type'}) {
1392 $input{'type'} = i_test_format_probe($IO, -1);
1395 unless ($input{'type'}) {
1396 $self->_set_error('type parameter missing and not possible to guess from extension');
1400 _reader_autoload($input{type});
1402 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1403 return $readers{$input{type}}{single}->($self, $IO, %input);
1406 unless ($formats_low{$input{'type'}}) {
1407 my $read_types = join ', ', sort Imager->read_types();
1408 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1412 my $allow_incomplete = $input{allow_incomplete};
1413 defined $allow_incomplete or $allow_incomplete = 0;
1415 if ( $input{'type'} eq 'pnm' ) {
1416 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1417 if ( !defined($self->{IMG}) ) {
1418 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1421 $self->{DEBUG} && print "loading a pnm file\n";
1425 if ( $input{'type'} eq 'bmp' ) {
1426 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1427 if ( !defined($self->{IMG}) ) {
1428 $self->{ERRSTR}=$self->_error_as_msg();
1431 $self->{DEBUG} && print "loading a bmp file\n";
1434 if ( $input{'type'} eq 'gif' ) {
1435 if ($input{colors} && !ref($input{colors})) {
1436 # must be a reference to a scalar that accepts the colour map
1437 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1440 if ($input{'gif_consolidate'}) {
1441 if ($input{colors}) {
1443 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1445 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1449 $self->{IMG} =i_readgif_wiol( $IO );
1453 my $page = $input{'page'};
1454 defined $page or $page = 0;
1455 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1456 if ($self->{IMG} && $input{colors}) {
1457 ${ $input{colors} } =
1458 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1462 if ( !defined($self->{IMG}) ) {
1463 $self->{ERRSTR}=$self->_error_as_msg();
1466 $self->{DEBUG} && print "loading a gif file\n";
1469 if ( $input{'type'} eq 'tga' ) {
1470 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1471 if ( !defined($self->{IMG}) ) {
1472 $self->{ERRSTR}=$self->_error_as_msg();
1475 $self->{DEBUG} && print "loading a tga file\n";
1478 if ( $input{'type'} eq 'raw' ) {
1479 unless ( $input{xsize} && $input{ysize} ) {
1480 $self->_set_error('missing xsize or ysize parameter for raw');
1484 my $interleave = _first($input{raw_interleave}, $input{interleave});
1485 unless (defined $interleave) {
1486 my @caller = caller;
1487 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1490 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1491 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1493 $self->{IMG} = i_readraw_wiol( $IO,
1499 if ( !defined($self->{IMG}) ) {
1500 $self->{ERRSTR}=$self->_error_as_msg();
1503 $self->{DEBUG} && print "loading a raw file\n";
1509 sub register_reader {
1510 my ($class, %opts) = @_;
1513 or die "register_reader called with no type parameter\n";
1515 my $type = $opts{type};
1517 defined $opts{single} || defined $opts{multiple}
1518 or die "register_reader called with no single or multiple parameter\n";
1520 $readers{$type} = { };
1521 if ($opts{single}) {
1522 $readers{$type}{single} = $opts{single};
1524 if ($opts{multiple}) {
1525 $readers{$type}{multiple} = $opts{multiple};
1531 sub register_writer {
1532 my ($class, %opts) = @_;
1535 or die "register_writer called with no type parameter\n";
1537 my $type = $opts{type};
1539 defined $opts{single} || defined $opts{multiple}
1540 or die "register_writer called with no single or multiple parameter\n";
1542 $writers{$type} = { };
1543 if ($opts{single}) {
1544 $writers{$type}{single} = $opts{single};
1546 if ($opts{multiple}) {
1547 $writers{$type}{multiple} = $opts{multiple};
1558 grep($file_formats{$_}, keys %formats),
1559 qw(ico sgi), # formats not handled directly, but supplied with Imager
1570 grep($file_formats{$_}, keys %formats),
1571 qw(ico sgi), # formats not handled directly, but supplied with Imager
1577 # probes for an Imager::File::whatever module
1578 sub _reader_autoload {
1581 return if $formats_low{$type} || $readers{$type};
1583 return unless $type =~ /^\w+$/;
1585 my $file = "Imager/File/\U$type\E.pm";
1587 unless ($attempted_to_load{$file}) {
1589 ++$attempted_to_load{$file};
1593 # try to get a reader specific module
1594 my $file = "Imager/File/\U$type\EReader.pm";
1595 unless ($attempted_to_load{$file}) {
1597 ++$attempted_to_load{$file};
1605 # probes for an Imager::File::whatever module
1606 sub _writer_autoload {
1609 return if $formats_low{$type} || $readers{$type};
1611 return unless $type =~ /^\w+$/;
1613 my $file = "Imager/File/\U$type\E.pm";
1615 unless ($attempted_to_load{$file}) {
1617 ++$attempted_to_load{$file};
1621 # try to get a writer specific module
1622 my $file = "Imager/File/\U$type\EWriter.pm";
1623 unless ($attempted_to_load{$file}) {
1625 ++$attempted_to_load{$file};
1633 sub _fix_gif_positions {
1634 my ($opts, $opt, $msg, @imgs) = @_;
1636 my $positions = $opts->{'gif_positions'};
1638 for my $pos (@$positions) {
1639 my ($x, $y) = @$pos;
1640 my $img = $imgs[$index++];
1641 $img->settag(name=>'gif_left', value=>$x);
1642 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1644 $$msg .= "replaced with the gif_left and gif_top tags";
1649 gif_each_palette=>'gif_local_map',
1650 interlace => 'gif_interlace',
1651 gif_delays => 'gif_delay',
1652 gif_positions => \&_fix_gif_positions,
1653 gif_loop_count => 'gif_loop',
1656 # options that should be converted to colors
1657 my %color_opts = map { $_ => 1 } qw/i_background/;
1660 my ($self, $opts, $prefix, @imgs) = @_;
1662 for my $opt (keys %$opts) {
1664 if ($obsolete_opts{$opt}) {
1665 my $new = $obsolete_opts{$opt};
1666 my $msg = "Obsolete option $opt ";
1668 $new->($opts, $opt, \$msg, @imgs);
1671 $msg .= "replaced with the $new tag ";
1674 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1675 warn $msg if $warn_obsolete && $^W;
1677 next unless $tagname =~ /^\Q$prefix/;
1678 my $value = $opts->{$opt};
1679 if ($color_opts{$opt}) {
1680 $value = _color($value);
1682 $self->_set_error($Imager::ERRSTR);
1687 if (UNIVERSAL::isa($value, "Imager::Color")) {
1688 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1689 for my $img (@imgs) {
1690 $img->settag(name=>$tagname, value=>$tag);
1693 elsif (ref($value) eq 'ARRAY') {
1694 for my $i (0..$#$value) {
1695 my $val = $value->[$i];
1697 if (UNIVERSAL::isa($val, "Imager::Color")) {
1698 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1700 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1703 $self->_set_error("Unknown reference type " . ref($value) .
1704 " supplied in array for $opt");
1710 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1715 $self->_set_error("Unknown reference type " . ref($value) .
1716 " supplied for $opt");
1721 # set it as a tag for every image
1722 for my $img (@imgs) {
1723 $img->settag(name=>$tagname, value=>$value);
1731 # Write an image to file
1734 my %input=(jpegquality=>75,
1744 $self->_set_opts(\%input, "i_", $self)
1747 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1749 if (!$input{'type'} and $input{file}) {
1750 $input{'type'}=$FORMATGUESS->($input{file});
1752 if (!$input{'type'}) {
1753 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1757 _writer_autoload($input{type});
1760 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1761 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1764 $writers{$input{type}}{single}->($self, $IO, %input)
1768 if (!$formats_low{$input{'type'}}) {
1769 my $write_types = join ', ', sort Imager->write_types();
1770 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1774 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1777 if ( $input{'type'} eq 'pnm' ) {
1778 $self->_set_opts(\%input, "pnm_", $self)
1780 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1781 $self->{ERRSTR} = $self->_error_as_msg();
1784 $self->{DEBUG} && print "writing a pnm file\n";
1785 } elsif ( $input{'type'} eq 'raw' ) {
1786 $self->_set_opts(\%input, "raw_", $self)
1788 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1789 $self->{ERRSTR} = $self->_error_as_msg();
1792 $self->{DEBUG} && print "writing a raw file\n";
1793 } elsif ( $input{'type'} eq 'jpeg' ) {
1794 $self->_set_opts(\%input, "jpeg_", $self)
1796 $self->_set_opts(\%input, "exif_", $self)
1798 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1799 $self->{ERRSTR} = $self->_error_as_msg();
1802 $self->{DEBUG} && print "writing a jpeg file\n";
1803 } elsif ( $input{'type'} eq 'bmp' ) {
1804 $self->_set_opts(\%input, "bmp_", $self)
1806 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1807 $self->{ERRSTR} = $self->_error_as_msg;
1810 $self->{DEBUG} && print "writing a bmp file\n";
1811 } elsif ( $input{'type'} eq 'tga' ) {
1812 $self->_set_opts(\%input, "tga_", $self)
1815 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1816 $self->{ERRSTR}=$self->_error_as_msg();
1819 $self->{DEBUG} && print "writing a tga file\n";
1820 } elsif ( $input{'type'} eq 'gif' ) {
1821 $self->_set_opts(\%input, "gif_", $self)
1823 # compatibility with the old interfaces
1824 if ($input{gifquant} eq 'lm') {
1825 $input{make_colors} = 'addi';
1826 $input{translate} = 'perturb';
1827 $input{perturb} = $input{lmdither};
1828 } elsif ($input{gifquant} eq 'gen') {
1829 # just pass options through
1831 $input{make_colors} = 'webmap'; # ignored
1832 $input{translate} = 'giflib';
1834 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1835 $self->{ERRSTR} = $self->_error_as_msg;
1841 if (exists $input{'data'}) {
1842 my $data = io_slurp($IO);
1844 $self->{ERRSTR}='Could not slurp from buffer';
1847 ${$input{data}} = $data;
1853 my ($class, $opts, @images) = @_;
1855 my $type = $opts->{type};
1857 if (!$type && $opts->{'file'}) {
1858 $type = $FORMATGUESS->($opts->{'file'});
1861 $class->_set_error('type parameter missing and not possible to guess from extension');
1864 # translate to ImgRaw
1865 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1866 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1869 $class->_set_opts($opts, "i_", @images)
1871 my @work = map $_->{IMG}, @images;
1873 _writer_autoload($type);
1876 if ($writers{$type} && $writers{$type}{multiple}) {
1877 ($IO, $file) = $class->_get_writer_io($opts, $type)
1880 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1884 if (!$formats{$type}) {
1885 my $write_types = join ', ', sort Imager->write_types();
1886 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1890 ($IO, $file) = $class->_get_writer_io($opts, $type)
1893 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1897 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1902 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1908 if (exists $opts->{'data'}) {
1909 my $data = io_slurp($IO);
1911 Imager->_set_error('Could not slurp from buffer');
1914 ${$opts->{data}} = $data;
1919 # read multiple images from a file
1921 my ($class, %opts) = @_;
1923 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1926 my $type = $opts{'type'};
1928 $type = i_test_format_probe($IO, -1);
1931 if ($opts{file} && !$type) {
1933 $type = $FORMATGUESS->($opts{file});
1937 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1941 _reader_autoload($type);
1943 if ($readers{$type} && $readers{$type}{multiple}) {
1944 return $readers{$type}{multiple}->($IO, %opts);
1947 unless ($formats{$type}) {
1948 my $read_types = join ', ', sort Imager->read_types();
1949 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1954 if ($type eq 'pnm') {
1955 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1958 my $img = Imager->new;
1959 if ($img->read(%opts, io => $IO, type => $type)) {
1962 Imager->_set_error($img->errstr);
1967 $ERRSTR = _error_as_msg();
1971 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1975 # Destroy an Imager object
1979 # delete $instances{$self};
1980 if (defined($self->{IMG})) {
1981 # the following is now handled by the XS DESTROY method for
1982 # Imager::ImgRaw object
1983 # Re-enabling this will break virtual images
1984 # tested for in t/t020masked.t
1985 # i_img_destroy($self->{IMG});
1986 undef($self->{IMG});
1988 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1992 # Perform an inplace filter of an image
1993 # that is the image will be overwritten with the data
1999 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2001 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2003 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2004 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2007 if ($filters{$input{'type'}}{names}) {
2008 my $names = $filters{$input{'type'}}{names};
2009 for my $name (keys %$names) {
2010 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2011 $input{$name} = $names->{$name}{$input{$name}};
2015 if (defined($filters{$input{'type'}}{defaults})) {
2016 %hsh=( image => $self->{IMG},
2018 %{$filters{$input{'type'}}{defaults}},
2021 %hsh=( image => $self->{IMG},
2026 my @cs=@{$filters{$input{'type'}}{callseq}};
2029 if (!defined($hsh{$_})) {
2030 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2035 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2036 &{$filters{$input{'type'}}{callsub}}(%hsh);
2039 chomp($self->{ERRSTR} = $@);
2045 $self->{DEBUG} && print "callseq is: @cs\n";
2046 $self->{DEBUG} && print "matching callseq is: @b\n";
2051 sub register_filter {
2053 my %hsh = ( defaults => {}, @_ );
2056 or die "register_filter() with no type\n";
2057 defined $hsh{callsub}
2058 or die "register_filter() with no callsub\n";
2059 defined $hsh{callseq}
2060 or die "register_filter() with no callseq\n";
2062 exists $filters{$hsh{type}}
2065 $filters{$hsh{type}} = \%hsh;
2070 sub scale_calculate {
2073 my %opts = ('type'=>'max', @_);
2075 # none of these should be references
2076 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2077 if (defined $opts{$name} && ref $opts{$name}) {
2078 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2083 my ($x_scale, $y_scale);
2084 my $width = $opts{width};
2085 my $height = $opts{height};
2087 defined $width or $width = $self->getwidth;
2088 defined $height or $height = $self->getheight;
2091 unless (defined $width && defined $height) {
2092 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2097 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2098 $x_scale = $opts{'xscalefactor'};
2099 $y_scale = $opts{'yscalefactor'};
2101 elsif ($opts{'xscalefactor'}) {
2102 $x_scale = $opts{'xscalefactor'};
2103 $y_scale = $opts{'scalefactor'} || $x_scale;
2105 elsif ($opts{'yscalefactor'}) {
2106 $y_scale = $opts{'yscalefactor'};
2107 $x_scale = $opts{'scalefactor'} || $y_scale;
2110 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2113 # work out the scaling
2114 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2115 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2116 $opts{ypixels} / $height );
2117 if ($opts{'type'} eq 'min') {
2118 $x_scale = $y_scale = _min($xpix,$ypix);
2120 elsif ($opts{'type'} eq 'max') {
2121 $x_scale = $y_scale = _max($xpix,$ypix);
2123 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2128 $self->_set_error('invalid value for type parameter');
2131 } elsif ($opts{xpixels}) {
2132 $x_scale = $y_scale = $opts{xpixels} / $width;
2134 elsif ($opts{ypixels}) {
2135 $x_scale = $y_scale = $opts{ypixels}/$height;
2137 elsif ($opts{constrain} && ref $opts{constrain}
2138 && $opts{constrain}->can('constrain')) {
2139 # we've been passed an Image::Math::Constrain object or something
2140 # that looks like one
2142 (undef, undef, $scalefactor)
2143 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2144 unless ($scalefactor) {
2145 $self->_set_error('constrain method failed on constrain parameter');
2148 $x_scale = $y_scale = $scalefactor;
2151 my $new_width = int($x_scale * $width + 0.5);
2152 $new_width > 0 or $new_width = 1;
2153 my $new_height = int($y_scale * $height + 0.5);
2154 $new_height > 0 or $new_height = 1;
2156 return ($x_scale, $y_scale, $new_width, $new_height);
2160 # Scale an image to requested size and return the scaled version
2164 my %opts = (qtype=>'normal' ,@_);
2165 my $img = Imager->new();
2166 my $tmp = Imager->new();
2168 unless (defined wantarray) {
2169 my @caller = caller;
2170 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2174 unless ($self->{IMG}) {
2175 $self->_set_error('empty input image');
2179 my ($x_scale, $y_scale, $new_width, $new_height) =
2180 $self->scale_calculate(%opts)
2183 if ($opts{qtype} eq 'normal') {
2184 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2185 if ( !defined($tmp->{IMG}) ) {
2186 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2189 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2190 if ( !defined($img->{IMG}) ) {
2191 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2197 elsif ($opts{'qtype'} eq 'preview') {
2198 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2199 if ( !defined($img->{IMG}) ) {
2200 $self->{ERRSTR}='unable to scale image';
2205 elsif ($opts{'qtype'} eq 'mixing') {
2206 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2207 unless ($img->{IMG}) {
2208 $self->_set_error(Imager->_error_as_msg);
2214 $self->_set_error('invalid value for qtype parameter');
2219 # Scales only along the X axis
2223 my %opts = ( scalefactor=>0.5, @_ );
2225 unless (defined wantarray) {
2226 my @caller = caller;
2227 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2231 unless ($self->{IMG}) {
2232 $self->{ERRSTR} = 'empty input image';
2236 my $img = Imager->new();
2238 my $scalefactor = $opts{scalefactor};
2240 if ($opts{pixels}) {
2241 $scalefactor = $opts{pixels} / $self->getwidth();
2244 unless ($self->{IMG}) {
2245 $self->{ERRSTR}='empty input image';
2249 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2251 if ( !defined($img->{IMG}) ) {
2252 $self->{ERRSTR} = 'unable to scale image';
2259 # Scales only along the Y axis
2263 my %opts = ( scalefactor => 0.5, @_ );
2265 unless (defined wantarray) {
2266 my @caller = caller;
2267 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2271 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2273 my $img = Imager->new();
2275 my $scalefactor = $opts{scalefactor};
2277 if ($opts{pixels}) {
2278 $scalefactor = $opts{pixels} / $self->getheight();
2281 unless ($self->{IMG}) {
2282 $self->{ERRSTR} = 'empty input image';
2285 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2287 if ( !defined($img->{IMG}) ) {
2288 $self->{ERRSTR} = 'unable to scale image';
2295 # Transform returns a spatial transformation of the input image
2296 # this moves pixels to a new location in the returned image.
2297 # NOTE - should make a utility function to check transforms for
2302 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2304 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2306 # print Dumper(\%opts);
2309 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2311 eval ("use Affix::Infix2Postfix;");
2314 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2317 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2318 {op=>'-',trans=>'Sub'},
2319 {op=>'*',trans=>'Mult'},
2320 {op=>'/',trans=>'Div'},
2321 {op=>'-','type'=>'unary',trans=>'u-'},
2323 {op=>'func','type'=>'unary'}],
2324 'grouping'=>[qw( \( \) )],
2325 'func'=>[qw( sin cos )],
2330 @xt=$I2P->translate($opts{'xexpr'});
2331 @yt=$I2P->translate($opts{'yexpr'});
2333 $numre=$I2P->{'numre'};
2336 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2337 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2338 @{$opts{'parm'}}=@pt;
2341 # print Dumper(\%opts);
2343 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2344 $self->{ERRSTR}='transform: no xopcodes given.';
2348 @op=@{$opts{'xopcodes'}};
2350 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2351 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2354 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2360 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2361 $self->{ERRSTR}='transform: no yopcodes given.';
2365 @op=@{$opts{'yopcodes'}};
2367 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2368 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2371 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2376 if ( !exists $opts{'parm'}) {
2377 $self->{ERRSTR}='transform: no parameter arg given.';
2381 # print Dumper(\@ropx);
2382 # print Dumper(\@ropy);
2383 # print Dumper(\@ropy);
2385 my $img = Imager->new();
2386 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2387 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2393 my ($opts, @imgs) = @_;
2395 require "Imager/Expr.pm";
2397 $opts->{variables} = [ qw(x y) ];
2398 my ($width, $height) = @{$opts}{qw(width height)};
2400 $width ||= $imgs[0]->getwidth();
2401 $height ||= $imgs[0]->getheight();
2403 for my $img (@imgs) {
2404 $opts->{constants}{"w$img_num"} = $img->getwidth();
2405 $opts->{constants}{"h$img_num"} = $img->getheight();
2406 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2407 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2412 $opts->{constants}{w} = $width;
2413 $opts->{constants}{cx} = $width/2;
2416 $Imager::ERRSTR = "No width supplied";
2420 $opts->{constants}{h} = $height;
2421 $opts->{constants}{cy} = $height/2;
2424 $Imager::ERRSTR = "No height supplied";
2427 my $code = Imager::Expr->new($opts);
2429 $Imager::ERRSTR = Imager::Expr::error();
2432 my $channels = $opts->{channels} || 3;
2433 unless ($channels >= 1 && $channels <= 4) {
2434 return Imager->_set_error("channels must be an integer between 1 and 4");
2437 my $img = Imager->new();
2438 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2439 $channels, $code->code(),
2440 $code->nregs(), $code->cregs(),
2441 [ map { $_->{IMG} } @imgs ]);
2442 if (!defined $img->{IMG}) {
2443 $Imager::ERRSTR = Imager->_error_as_msg();
2454 unless ($self->{IMG}) {
2455 $self->{ERRSTR}='empty input image';
2458 unless ($opts{src} && $opts{src}->{IMG}) {
2459 $self->{ERRSTR}='empty input image for src';
2463 %opts = (src_minx => 0,
2465 src_maxx => $opts{src}->getwidth(),
2466 src_maxy => $opts{src}->getheight(),
2470 defined $tx or $tx = $opts{left};
2471 defined $tx or $tx = 0;
2474 defined $ty or $ty = $opts{top};
2475 defined $ty or $ty = 0;
2477 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2478 $opts{src_minx}, $opts{src_miny},
2479 $opts{src_maxx}, $opts{src_maxy})) {
2480 $self->_set_error($self->_error_as_msg());
2497 unless ($self->{IMG}) {
2498 $self->_set_error("compose: empty input image");
2502 unless ($opts{src}) {
2503 $self->_set_error("compose: src parameter missing");
2507 unless ($opts{src}{IMG}) {
2508 $self->_set_error("compose: src parameter empty image");
2511 my $src = $opts{src};
2513 my $left = $opts{left};
2514 defined $left or $left = $opts{tx};
2515 defined $left or $left = 0;
2517 my $top = $opts{top};
2518 defined $top or $top = $opts{ty};
2519 defined $top or $top = 0;
2521 my $src_left = $opts{src_left};
2522 defined $src_left or $src_left = $opts{src_minx};
2523 defined $src_left or $src_left = 0;
2525 my $src_top = $opts{src_top};
2526 defined $src_top or $src_top = $opts{src_miny};
2527 defined $src_top or $src_top = 0;
2529 my $width = $opts{width};
2530 if (!defined $width && defined $opts{src_maxx}) {
2531 $width = $opts{src_maxx} - $src_left;
2533 defined $width or $width = $src->getwidth() - $src_left;
2535 my $height = $opts{height};
2536 if (!defined $height && defined $opts{src_maxy}) {
2537 $height = $opts{src_maxy} - $src_top;
2539 defined $height or $height = $src->getheight() - $src_top;
2541 my $combine = $self->_combine($opts{combine}, 'normal');
2544 unless ($opts{mask}{IMG}) {
2545 $self->_set_error("compose: mask parameter empty image");
2549 my $mask_left = $opts{mask_left};
2550 defined $mask_left or $mask_left = $opts{mask_minx};
2551 defined $mask_left or $mask_left = 0;
2553 my $mask_top = $opts{mask_top};
2554 defined $mask_top or $mask_top = $opts{mask_miny};
2555 defined $mask_top or $mask_top = 0;
2557 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2558 $left, $top, $src_left, $src_top,
2559 $mask_left, $mask_top, $width, $height,
2560 $combine, $opts{opacity})) {
2561 $self->_set_error(Imager->_error_as_msg);
2566 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2567 $width, $height, $combine, $opts{opacity})) {
2568 $self->_set_error(Imager->_error_as_msg);
2579 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2581 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2582 $dir = $xlate{$opts{'dir'}};
2583 return $self if i_flipxy($self->{IMG}, $dir);
2591 unless (defined wantarray) {
2592 my @caller = caller;
2593 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2597 if (defined $opts{right}) {
2598 my $degrees = $opts{right};
2600 $degrees += 360 * int(((-$degrees)+360)/360);
2602 $degrees = $degrees % 360;
2603 if ($degrees == 0) {
2604 return $self->copy();
2606 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2607 my $result = Imager->new();
2608 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2612 $self->{ERRSTR} = $self->_error_as_msg();
2617 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2621 elsif (defined $opts{radians} || defined $opts{degrees}) {
2622 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2624 my $back = $opts{back};
2625 my $result = Imager->new;
2627 $back = _color($back);
2629 $self->_set_error(Imager->errstr);
2633 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2636 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2638 if ($result->{IMG}) {
2642 $self->{ERRSTR} = $self->_error_as_msg();
2647 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2652 sub matrix_transform {
2656 unless (defined wantarray) {
2657 my @caller = caller;
2658 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2662 if ($opts{matrix}) {
2663 my $xsize = $opts{xsize} || $self->getwidth;
2664 my $ysize = $opts{ysize} || $self->getheight;
2666 my $result = Imager->new;
2668 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2669 $opts{matrix}, $opts{back})
2673 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2681 $self->{ERRSTR} = "matrix parameter required";
2687 *yatf = \&matrix_transform;
2689 # These two are supported for legacy code only
2692 return Imager::Color->new(@_);
2696 return Imager::Color::set(@_);
2699 # Draws a box between the specified corner points.
2702 my $raw = $self->{IMG};
2705 $self->{ERRSTR}='empty input image';
2711 my ($xmin, $ymin, $xmax, $ymax);
2712 if (exists $opts{'box'}) {
2713 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2714 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2715 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2716 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2719 defined($xmin = $opts{xmin}) or $xmin = 0;
2720 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2721 defined($ymin = $opts{ymin}) or $ymin = 0;
2722 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2725 if ($opts{filled}) {
2726 my $color = $opts{'color'};
2728 if (defined $color) {
2729 unless (_is_color_object($color)) {
2730 $color = _color($color);
2732 $self->{ERRSTR} = $Imager::ERRSTR;
2738 $color = i_color_new(255,255,255,255);
2741 if ($color->isa("Imager::Color")) {
2742 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2745 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2748 elsif ($opts{fill}) {
2749 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2750 # assume it's a hash ref
2751 require 'Imager/Fill.pm';
2752 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2753 $self->{ERRSTR} = $Imager::ERRSTR;
2757 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2760 my $color = $opts{'color'};
2761 if (defined $color) {
2762 unless (_is_color_object($color)) {
2763 $color = _color($color);
2765 $self->{ERRSTR} = $Imager::ERRSTR;
2771 $color = i_color_new(255, 255, 255, 255);
2774 $self->{ERRSTR} = $Imager::ERRSTR;
2777 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2785 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2786 my $dflcl= [ 255, 255, 255, 255];
2791 'r'=>_min($self->getwidth(),$self->getheight())/3,
2792 'x'=>$self->getwidth()/2,
2793 'y'=>$self->getheight()/2,
2800 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2801 # assume it's a hash ref
2802 require 'Imager/Fill.pm';
2803 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2804 $self->{ERRSTR} = $Imager::ERRSTR;
2808 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2809 $opts{'d2'}, $opts{fill}{fill});
2811 elsif ($opts{filled}) {
2812 my $color = _color($opts{'color'});
2814 $self->{ERRSTR} = $Imager::ERRSTR;
2817 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2818 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2822 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2823 $opts{'d1'}, $opts{'d2'}, $color);
2827 my $color = _color($opts{'color'});
2828 if ($opts{d2} - $opts{d1} >= 360) {
2829 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2832 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2838 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2839 # assume it's a hash ref
2840 require 'Imager/Fill.pm';
2841 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2842 $self->{ERRSTR} = $Imager::ERRSTR;
2846 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2847 $opts{'d2'}, $opts{fill}{fill});
2850 my $color = _color($opts{'color'});
2852 $self->{ERRSTR} = $Imager::ERRSTR;
2855 if ($opts{filled}) {
2856 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2857 $opts{'d1'}, $opts{'d2'}, $color);
2860 if ($opts{d1} == 0 && $opts{d2} == 361) {
2861 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2864 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2870 $self->_set_error($self->_error_as_msg);
2877 # Draws a line from one point to the other
2878 # the endpoint is set if the endp parameter is set which it is by default.
2879 # to turn of the endpoint being set use endp=>0 when calling line.
2883 my $dflcl=i_color_new(0,0,0,0);
2884 my %opts=(color=>$dflcl,
2887 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2889 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2890 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2892 my $color = _color($opts{'color'});
2894 $self->{ERRSTR} = $Imager::ERRSTR;
2898 $opts{antialias} = $opts{aa} if defined $opts{aa};
2899 if ($opts{antialias}) {
2900 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2901 $color, $opts{endp});
2903 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2904 $color, $opts{endp});
2909 # Draws a line between an ordered set of points - It more or less just transforms this
2910 # into a list of lines.
2914 my ($pt,$ls,@points);
2915 my $dflcl=i_color_new(0,0,0,0);
2916 my %opts=(color=>$dflcl,@_);
2918 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2920 if (exists($opts{points})) { @points=@{$opts{points}}; }
2921 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2922 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2925 # print Dumper(\@points);
2927 my $color = _color($opts{'color'});
2929 $self->{ERRSTR} = $Imager::ERRSTR;
2932 $opts{antialias} = $opts{aa} if defined $opts{aa};
2933 if ($opts{antialias}) {
2936 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2943 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2953 my ($pt,$ls,@points);
2954 my $dflcl = i_color_new(0,0,0,0);
2955 my %opts = (color=>$dflcl, @_);
2957 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2959 if (exists($opts{points})) {
2960 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2961 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2964 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2965 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2968 if ($opts{'fill'}) {
2969 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2970 # assume it's a hash ref
2971 require 'Imager/Fill.pm';
2972 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2973 $self->{ERRSTR} = $Imager::ERRSTR;
2977 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2978 $opts{'fill'}{'fill'});
2981 my $color = _color($opts{'color'});
2983 $self->{ERRSTR} = $Imager::ERRSTR;
2986 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2993 # this the multipoint bezier curve
2994 # this is here more for testing that actual usage since
2995 # this is not a good algorithm. Usually the curve would be
2996 # broken into smaller segments and each done individually.
3000 my ($pt,$ls,@points);
3001 my $dflcl=i_color_new(0,0,0,0);
3002 my %opts=(color=>$dflcl,@_);
3004 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3006 if (exists $opts{points}) {
3007 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3008 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3011 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3012 $self->{ERRSTR}='Missing or invalid points.';
3016 my $color = _color($opts{'color'});
3018 $self->{ERRSTR} = $Imager::ERRSTR;
3021 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3027 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3030 unless (exists $opts{'x'} && exists $opts{'y'}) {
3031 $self->{ERRSTR} = "missing seed x and y parameters";
3035 if ($opts{border}) {
3036 my $border = _color($opts{border});
3038 $self->_set_error($Imager::ERRSTR);
3042 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3043 # assume it's a hash ref
3044 require Imager::Fill;
3045 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3046 $self->{ERRSTR} = $Imager::ERRSTR;
3050 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3051 $opts{fill}{fill}, $border);
3054 my $color = _color($opts{'color'});
3056 $self->{ERRSTR} = $Imager::ERRSTR;
3059 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3066 $self->{ERRSTR} = $self->_error_as_msg();
3072 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3073 # assume it's a hash ref
3074 require 'Imager/Fill.pm';
3075 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3076 $self->{ERRSTR} = $Imager::ERRSTR;
3080 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3083 my $color = _color($opts{'color'});
3085 $self->{ERRSTR} = $Imager::ERRSTR;
3088 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3094 $self->{ERRSTR} = $self->_error_as_msg();
3101 my ($self, %opts) = @_;
3103 my $color = $opts{color};
3104 unless (defined $color) {
3105 $color = $self->{fg};
3106 defined $color or $color = NC(255, 255, 255);
3109 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3110 $color = _color($color)
3114 unless (exists $opts{'x'} && exists $opts{'y'}) {
3115 $self->{ERRSTR} = 'missing x and y parameters';
3121 if (ref $x && ref $y) {
3122 unless (@$x == @$y) {
3123 $self->{ERRSTR} = 'length of x and y mismatch';
3127 if ($color->isa('Imager::Color')) {
3128 for my $i (0..$#{$opts{'x'}}) {
3129 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3134 for my $i (0..$#{$opts{'x'}}) {
3135 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3143 if ($color->isa('Imager::Color')) {
3144 i_ppix($self->{IMG}, $x, $y, $color)
3148 i_ppixf($self->{IMG}, $x, $y, $color)
3159 my %opts = ( "type"=>'8bit', @_);
3161 unless (exists $opts{'x'} && exists $opts{'y'}) {
3162 $self->{ERRSTR} = 'missing x and y parameters';
3168 if (ref $x && ref $y) {
3169 unless (@$x == @$y) {
3170 $self->{ERRSTR} = 'length of x and y mismatch';
3174 if ($opts{"type"} eq '8bit') {
3175 for my $i (0..$#{$opts{'x'}}) {
3176 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3180 for my $i (0..$#{$opts{'x'}}) {
3181 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3184 return wantarray ? @result : \@result;
3187 if ($opts{"type"} eq '8bit') {
3188 return i_get_pixel($self->{IMG}, $x, $y);
3191 return i_gpixf($self->{IMG}, $x, $y);
3200 my %opts = ( type => '8bit', x=>0, @_);
3202 $self->_valid_image or return;
3204 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3206 unless (defined $opts{'y'}) {
3207 $self->_set_error("missing y parameter");
3211 if ($opts{type} eq '8bit') {
3212 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3215 elsif ($opts{type} eq 'float') {
3216 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3219 elsif ($opts{type} eq 'index') {
3220 unless (i_img_type($self->{IMG})) {
3221 $self->_set_error("type => index only valid on paletted images");
3224 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3228 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3235 my %opts = ( x=>0, @_);
3237 $self->_valid_image or return;
3239 unless (defined $opts{'y'}) {
3240 $self->_set_error("missing y parameter");
3245 if (ref $opts{pixels} && @{$opts{pixels}}) {
3246 # try to guess the type
3247 if ($opts{pixels}[0]->isa('Imager::Color')) {
3248 $opts{type} = '8bit';
3250 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3251 $opts{type} = 'float';
3254 $self->_set_error("missing type parameter and could not guess from pixels");
3260 $opts{type} = '8bit';
3264 if ($opts{type} eq '8bit') {
3265 if (ref $opts{pixels}) {
3266 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3269 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3272 elsif ($opts{type} eq 'float') {
3273 if (ref $opts{pixels}) {
3274 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3277 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3280 elsif ($opts{type} eq 'index') {
3281 if (ref $opts{pixels}) {
3282 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3285 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3289 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3296 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3298 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3300 unless (defined $opts{'y'}) {
3301 $self->_set_error("missing y parameter");
3305 unless ($opts{channels}) {
3306 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3309 if ($opts{target}) {
3310 my $target = $opts{target};
3311 my $offset = $opts{offset};
3312 if ($opts{type} eq '8bit') {
3313 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3314 $opts{y}, @{$opts{channels}})
3316 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3317 return scalar(@samples);
3319 elsif ($opts{type} eq 'float') {
3320 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3321 $opts{y}, @{$opts{channels}});
3322 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3323 return scalar(@samples);
3325 elsif ($opts{type} =~ /^(\d+)bit$/) {
3329 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3330 $opts{y}, $bits, $target,
3331 $offset, @{$opts{channels}});
3332 unless (defined $count) {
3333 $self->_set_error(Imager->_error_as_msg);
3340 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3345 if ($opts{type} eq '8bit') {
3346 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3347 $opts{y}, @{$opts{channels}});
3349 elsif ($opts{type} eq 'float') {
3350 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3351 $opts{y}, @{$opts{channels}});
3353 elsif ($opts{type} =~ /^(\d+)bit$/) {
3357 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3358 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3363 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3371 my %opts = ( x => 0, offset => 0, @_ );
3373 unless ($self->{IMG}) {
3374 $self->_set_error('setsamples: empty input image');
3378 unless(defined $opts{data} && ref $opts{data}) {
3379 $self->_set_error('setsamples: data parameter missing or invalid');
3383 unless ($opts{channels}) {
3384 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3387 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3388 $self->_set_error('setsamples: type parameter missing or invalid');
3393 unless (defined $opts{width}) {
3394 $opts{width} = $self->getwidth() - $opts{x};
3397 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3398 $opts{channels}, $opts{data}, $opts{offset},
3400 unless (defined $count) {
3401 $self->_set_error(Imager->_error_as_msg);
3408 # make an identity matrix of the given size
3412 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3413 for my $c (0 .. ($size-1)) {
3414 $matrix->[$c][$c] = 1;
3419 # general function to convert an image
3421 my ($self, %opts) = @_;
3424 unless (defined wantarray) {
3425 my @caller = caller;
3426 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3430 # the user can either specify a matrix or preset
3431 # the matrix overrides the preset
3432 if (!exists($opts{matrix})) {
3433 unless (exists($opts{preset})) {
3434 $self->{ERRSTR} = "convert() needs a matrix or preset";
3438 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3439 # convert to greyscale, keeping the alpha channel if any
3440 if ($self->getchannels == 3) {
3441 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3443 elsif ($self->getchannels == 4) {
3444 # preserve the alpha channel
3445 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3450 $matrix = _identity($self->getchannels);
3453 elsif ($opts{preset} eq 'noalpha') {
3454 # strip the alpha channel
3455 if ($self->getchannels == 2 or $self->getchannels == 4) {
3456 $matrix = _identity($self->getchannels);
3457 pop(@$matrix); # lose the alpha entry
3460 $matrix = _identity($self->getchannels);
3463 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3465 $matrix = [ [ 1 ] ];
3467 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3468 $matrix = [ [ 0, 1 ] ];
3470 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3471 $matrix = [ [ 0, 0, 1 ] ];
3473 elsif ($opts{preset} eq 'alpha') {
3474 if ($self->getchannels == 2 or $self->getchannels == 4) {
3475 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3478 # the alpha is just 1 <shrug>
3479 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3482 elsif ($opts{preset} eq 'rgb') {
3483 if ($self->getchannels == 1) {
3484 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3486 elsif ($self->getchannels == 2) {
3487 # preserve the alpha channel
3488 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3491 $matrix = _identity($self->getchannels);
3494 elsif ($opts{preset} eq 'addalpha') {
3495 if ($self->getchannels == 1) {
3496 $matrix = _identity(2);
3498 elsif ($self->getchannels == 3) {
3499 $matrix = _identity(4);
3502 $matrix = _identity($self->getchannels);
3506 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3512 $matrix = $opts{matrix};
3515 my $new = Imager->new;
3516 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3517 unless ($new->{IMG}) {
3518 # most likely a bad matrix
3519 $self->{ERRSTR} = _error_as_msg();
3525 # combine channels from multiple input images, a class method
3527 my ($class, %opts) = @_;
3529 my $src = delete $opts{src};
3531 $class->_set_error("src parameter missing");
3536 for my $img (@$src) {
3537 unless (eval { $img->isa("Imager") }) {
3538 $class->_set_error("src must contain image objects");
3541 unless ($img->{IMG}) {
3542 $class->_set_error("empty input image");
3545 push @imgs, $img->{IMG};
3548 if (my $channels = delete $opts{channels}) {
3549 $result = i_combine(\@imgs, $channels);
3552 $result = i_combine(\@imgs);
3555 $class->_set_error($class->_error_as_msg);
3559 my $img = $class->new;
3560 $img->{IMG} = $result;
3566 # general function to map an image through lookup tables
3569 my ($self, %opts) = @_;
3570 my @chlist = qw( red green blue alpha );
3572 if (!exists($opts{'maps'})) {
3573 # make maps from channel maps
3575 for $chnum (0..$#chlist) {
3576 if (exists $opts{$chlist[$chnum]}) {
3577 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3578 } elsif (exists $opts{'all'}) {
3579 $opts{'maps'}[$chnum] = $opts{'all'};
3583 if ($opts{'maps'} and $self->{IMG}) {
3584 i_map($self->{IMG}, $opts{'maps'} );
3590 my ($self, %opts) = @_;
3592 defined $opts{mindist} or $opts{mindist} = 0;
3594 defined $opts{other}
3595 or return $self->_set_error("No 'other' parameter supplied");
3596 defined $opts{other}{IMG}
3597 or return $self->_set_error("No image data in 'other' image");
3600 or return $self->_set_error("No image data");
3602 my $result = Imager->new;
3603 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3605 or return $self->_set_error($self->_error_as_msg());
3610 # destructive border - image is shrunk by one pixel all around
3613 my ($self,%opts)=@_;
3614 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3615 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3619 # Get the width of an image
3624 if (my $raw = $self->{IMG}) {
3625 return i_img_get_width($raw);
3628 $self->{ERRSTR} = 'image is empty'; return undef;
3632 # Get the height of an image
3637 if (my $raw = $self->{IMG}) {
3638 return i_img_get_height($raw);
3641 $self->{ERRSTR} = 'image is empty'; return undef;
3645 # Get number of channels in an image
3649 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3650 return i_img_getchannels($self->{IMG});
3657 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3658 return i_img_getmask($self->{IMG});
3666 if (!defined($self->{IMG})) {
3667 $self->{ERRSTR} = 'image is empty';
3670 unless (defined $opts{mask}) {
3671 $self->_set_error("mask parameter required");
3674 i_img_setmask( $self->{IMG} , $opts{mask} );
3679 # Get number of colors in an image
3683 my %opts=('maxcolors'=>2**30,@_);
3684 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3685 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3686 return ($rc==-1? undef : $rc);
3689 # Returns a reference to a hash. The keys are colour named (packed) and the
3690 # values are the number of pixels in this colour.
3691 sub getcolorusagehash {
3694 my %opts = ( maxcolors => 2**30, @_ );
3695 my $max_colors = $opts{maxcolors};
3696 unless (defined $max_colors && $max_colors > 0) {
3697 $self->_set_error('maxcolors must be a positive integer');
3701 unless (defined $self->{IMG}) {
3702 $self->_set_error('empty input image');
3706 my $channels= $self->getchannels;
3707 # We don't want to look at the alpha channel, because some gifs using it
3708 # doesn't define it for every colour (but only for some)
3709 $channels -= 1 if $channels == 2 or $channels == 4;
3711 my $height = $self->getheight;
3712 for my $y (0 .. $height - 1) {
3713 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3714 while (length $colors) {
3715 $color_use{ substr($colors, 0, $channels, '') }++;
3717 keys %color_use > $max_colors
3723 # This will return a ordered array of the colour usage. Kind of the sorted
3724 # version of the values of the hash returned by getcolorusagehash.
3725 # You might want to add safety checks and change the names, etc...
3729 my %opts = ( maxcolors => 2**30, @_ );
3730 my $max_colors = $opts{maxcolors};
3731 unless (defined $max_colors && $max_colors > 0) {
3732 $self->_set_error('maxcolors must be a positive integer');
3736 unless (defined $self->{IMG}) {
3737 $self->_set_error('empty input image');
3741 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3744 # draw string to an image
3748 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3750 my %input=('x'=>0, 'y'=>0, @_);
3751 defined($input{string}) or $input{string} = $input{text};
3753 unless(defined $input{string}) {
3754 $self->{ERRSTR}="missing required parameter 'string'";
3758 unless($input{font}) {
3759 $self->{ERRSTR}="missing required parameter 'font'";
3763 unless ($input{font}->draw(image=>$self, %input)) {
3775 unless ($self->{IMG}) {
3776 $self->{ERRSTR}='empty input image';
3785 my %input=('x'=>0, 'y'=>0, @_);
3786 defined $input{string}
3787 or $input{string} = $input{text};
3789 unless(exists $input{string}) {
3790 $self->_set_error("missing required parameter 'string'");
3794 unless($input{font}) {
3795 $self->_set_error("missing required parameter 'font'");
3800 unless (@result = $input{font}->align(image=>$img, %input)) {
3804 return wantarray ? @result : $result[0];
3807 my @file_limit_names = qw/width height bytes/;
3809 sub set_file_limits {
3816 @values{@file_limit_names} = (0) x @file_limit_names;
3819 @values{@file_limit_names} = i_get_image_file_limits();
3822 for my $key (keys %values) {
3823 defined $opts{$key} and $values{$key} = $opts{$key};
3826 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3829 sub get_file_limits {
3830 i_get_image_file_limits();
3833 # Shortcuts that can be exported
3835 sub newcolor { Imager::Color->new(@_); }
3836 sub newfont { Imager::Font->new(@_); }
3838 require Imager::Color::Float;
3839 return Imager::Color::Float->new(@_);
3842 *NC=*newcolour=*newcolor;
3849 #### Utility routines
3852 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3856 my ($self, $msg) = @_;
3859 $self->{ERRSTR} = $msg;
3867 # Default guess for the type of an image from extension
3869 sub def_guess_type {
3872 $ext=($name =~ m/\.([^\.]+)$/)[0];
3873 return 'tiff' if ($ext =~ m/^tiff?$/);
3874 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3875 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3876 return 'png' if ($ext eq "png");
3877 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3878 return 'tga' if ($ext eq "tga");
3879 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3880 return 'gif' if ($ext eq "gif");
3881 return 'raw' if ($ext eq "raw");
3882 return lc $ext; # best guess
3887 return @combine_types;
3890 # get the minimum of a list
3894 for(@_) { if ($_<$mx) { $mx=$_; }}
3898 # get the maximum of a list
3902 for(@_) { if ($_>$mx) { $mx=$_; }}
3906 # string stuff for iptc headers
3910 $str = substr($str,3);
3911 $str =~ s/[\n\r]//g;
3918 # A little hack to parse iptc headers.
3923 my($caption,$photogr,$headln,$credit);
3925 my $str=$self->{IPTCRAW};
3930 @ar=split(/8BIM/,$str);
3935 @sar=split(/\034\002/);
3936 foreach $item (@sar) {
3937 if ($item =~ m/^x/) {
3938 $caption = _clean($item);
3941 if ($item =~ m/^P/) {
3942 $photogr = _clean($item);
3945 if ($item =~ m/^i/) {
3946 $headln = _clean($item);
3949 if ($item =~ m/^n/) {
3950 $credit = _clean($item);
3956 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3963 or die "Only C language supported";
3965 require Imager::ExtUtils;
3966 return Imager::ExtUtils->inline_config;
3969 # threads shouldn't try to close raw Imager objects
3970 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3973 # this serves two purposes:
3974 # - a class method to load the file support modules included with Image
3975 # (or were included, once the library dependent modules are split out)
3976 # - something for Module::ScanDeps to analyze
3977 # https://rt.cpan.org/Ticket/Display.html?id=6566
3979 eval { require Imager::File::GIF };
3980 eval { require Imager::File::JPEG };
3981 eval { require Imager::File::PNG };
3982 eval { require Imager::File::SGI };
3983 eval { require Imager::File::TIFF };
3984 eval { require Imager::File::ICO };
3985 eval { require Imager::Font::W32 };
3986 eval { require Imager::Font::FT2 };
3987 eval { require Imager::Font::T1 };
3990 # backward compatibility for %formats
3991 package Imager::FORMATS;
3993 use constant IX_FORMATS => 0;
3994 use constant IX_LIST => 1;
3995 use constant IX_INDEX => 2;
3996 use constant IX_CLASSES => 3;
3999 my ($class, $formats, $classes) = @_;
4001 return bless [ $formats, [ ], 0, $classes ], $class;
4005 my ($self, $key) = @_;
4007 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4009 if (eval { require $file; 1 }) {
4015 $self->[IX_FORMATS]{$key} = $value;
4021 my ($self, $key) = @_;
4023 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4025 $self->[IX_CLASSES]{$key} or return undef;
4027 return $self->_check($key);
4031 die "%Imager::formats is not user monifiable";
4035 die "%Imager::formats is not user monifiable";
4039 die "%Imager::formats is not user monifiable";
4043 my ($self, $key) = @_;
4045 if (exists $self->[IX_FORMATS]{$key}) {
4046 my $value = $self->[IX_FORMATS]{$key}
4051 $self->_check($key) or return 1==0;
4059 unless (@{$self->[IX_LIST]}) {
4061 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4062 keys %{$self->[IX_FORMATS]};
4064 for my $key (keys %{$self->[IX_CLASSES]}) {
4065 $self->[IX_FORMATS]{$key} and next;
4067 and push @{$self->[IX_LIST]}, $key;
4071 @{$self->[IX_LIST]} or return;
4072 $self->[IX_INDEX] = 1;
4073 return $self->[IX_LIST][0];
4079 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4082 return $self->[IX_LIST][$self->[IX_INDEX]++];
4088 return scalar @{$self->[IX_LIST]};
4093 # Below is the stub of documentation for your module. You better edit it!
4097 Imager - Perl extension for Generating 24 bit Images
4107 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4112 # see Imager::Files for information on the read() method
4113 my $img = Imager->new(file=>$file)
4114 or die Imager->errstr();
4116 $file =~ s/\.[^.]*$//;
4118 # Create smaller version
4119 # documented in Imager::Transformations
4120 my $thumb = $img->scale(scalefactor=>.3);
4122 # Autostretch individual channels
4123 $thumb->filter(type=>'autolevels');
4125 # try to save in one of these formats
4128 for $format ( qw( png gif jpeg tiff ppm ) ) {
4129 # Check if given format is supported
4130 if ($Imager::formats{$format}) {
4131 $file.="_low.$format";
4132 print "Storing image as: $file\n";
4133 # documented in Imager::Files
4134 $thumb->write(file=>$file) or
4142 Imager is a module for creating and altering images. It can read and
4143 write various image formats, draw primitive shapes like lines,and
4144 polygons, blend multiple images together in various ways, scale, crop,
4145 render text and more.
4147 =head2 Overview of documentation
4153 Imager - This document - Synopsis, Example, Table of Contents and
4158 L<Imager::Tutorial> - a brief introduction to Imager.
4162 L<Imager::Cookbook> - how to do various things with Imager.
4166 L<Imager::ImageTypes> - Basics of constructing image objects with
4167 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4168 8/16/double bits/channel, color maps, channel masks, image tags, color
4169 quantization. Also discusses basic image information methods.
4173 L<Imager::Files> - IO interaction, reading/writing images, format
4178 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4183 L<Imager::Color> - Color specification.
4187 L<Imager::Fill> - Fill pattern specification.
4191 L<Imager::Font> - General font rendering, bounding boxes and font
4196 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4197 blending, pasting, convert and map.
4201 L<Imager::Engines> - Programmable transformations through
4202 C<transform()>, C<transform2()> and C<matrix_transform()>.
4206 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4211 L<Imager::Expr> - Expressions for evaluation engine used by
4216 L<Imager::Matrix2d> - Helper class for affine transformations.
4220 L<Imager::Fountain> - Helper for making gradient profiles.
4224 L<Imager::API> - using Imager's C API
4228 L<Imager::APIRef> - API function reference
4232 L<Imager::Inline> - using Imager's C API from Inline::C
4236 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4240 =head2 Basic Overview
4242 An Image object is created with C<$img = Imager-E<gt>new()>.
4245 $img=Imager->new(); # create empty image
4246 $img->read(file=>'lena.png',type=>'png') or # read image from file
4247 die $img->errstr(); # give an explanation
4248 # if something failed
4250 or if you want to create an empty image:
4252 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4254 This example creates a completely black image of width 400 and height
4257 =head1 ERROR HANDLING
4259 In general a method will return false when it fails, if it does use
4260 the C<errstr()> method to find out why:
4266 Returns the last error message in that context.
4268 If the last error you received was from calling an object method, such
4269 as read, call errstr() as an object method to find out why:
4271 my $image = Imager->new;
4272 $image->read(file => 'somefile.gif')
4273 or die $image->errstr;
4275 If it was a class method then call errstr() as a class method:
4277 my @imgs = Imager->read_multi(file => 'somefile.gif')
4278 or die Imager->errstr;
4280 Note that in some cases object methods are implemented in terms of
4281 class methods so a failing object method may set both.
4285 The C<Imager-E<gt>new> method is described in detail in
4286 L<Imager::ImageTypes>.
4290 Where to find information on methods for Imager class objects.
4292 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4295 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4297 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4300 arc() - L<Imager::Draw/arc()> - draw a filled arc
4302 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4305 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4307 circle() - L<Imager::Draw/circle()> - draw a filled circle
4309 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4312 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4313 colors in an image's palette (paletted images only)
4315 combine() - L<Imager::Transformations/combine()> - combine channels
4316 from one or more images.
4318 combines() - L<Imager::Draw/combines()> - return a list of the
4319 different combine type keywords
4321 compose() - L<Imager::Transformations/compose()> - compose one image
4324 convert() - L<Imager::Transformations/"Color transformations"> -
4325 transform the color space
4327 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4330 crop() - L<Imager::Transformations/crop()> - extract part of an image
4332 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4333 used to guess the output file format based on the output file name
4335 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4337 difference() - L<Imager::Filters/"Image Difference"> - produce a
4338 difference images from two input images.
4340 errstr() - L</"Basic Overview"> - the error from the last failed
4343 filter() - L<Imager::Filters> - image filtering
4345 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4346 palette, if it has one
4348 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4351 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4354 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4355 samples per pixel for an image
4357 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4358 different colors used by an image (works for direct color images)
4360 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4361 palette, if it has one
4363 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4365 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4367 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4369 getheight() - L<Imager::ImageTypes/getwidth()> - height of the image in
4372 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4374 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4377 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4378 row or partial row of pixels.
4380 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4381 row or partial row of pixels.
4383 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4386 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4389 init() - L<Imager::ImageTypes/init()>
4391 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4392 image write functions should write the image in their bilevel (blank
4393 and white, no gray levels) format
4395 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4398 line() - L<Imager::Draw/line()> - draw an interval
4400 load_plugin() - L<Imager::Filters/load_plugin()>
4402 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4405 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4408 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4410 matrix_transform() - L<Imager::Engines/matrix_transform()>
4412 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4414 NC() - L<Imager::Handy/NC()>
4416 NCF() - L<Imager::Handy/NCF()>
4418 new() - L<Imager::ImageTypes/new()>
4420 newcolor() - L<Imager::Handy/newcolor()>
4422 newcolour() - L<Imager::Handy/newcolour()>
4424 newfont() - L<Imager::Handy/newfont()>
4426 NF() - L<Imager::Handy/NF()>
4428 open() - L<Imager::Files> - an alias for read()
4430 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4434 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4437 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4440 polygon() - L<Imager::Draw/polygon()>
4442 polyline() - L<Imager::Draw/polyline()>
4444 preload() - L<Imager::Files/preload()>
4446 read() - L<Imager::Files> - read a single image from an image file
4448 read_multi() - L<Imager::Files> - read multiple images from an image
4451 read_types() - L<Imager::Files/read_types()> - list image types Imager
4454 register_filter() - L<Imager::Filters/register_filter()>
4456 register_reader() - L<Imager::Files/register_reader()>
4458 register_writer() - L<Imager::Files/register_writer()>
4460 rotate() - L<Imager::Transformations/rotate()>
4462 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4463 onto an image and use the alpha channel
4465 scale() - L<Imager::Transformations/scale()>
4467 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4469 scaleX() - L<Imager::Transformations/scaleX()>
4471 scaleY() - L<Imager::Transformations/scaleY()>
4473 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4476 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4478 setmask() - L<Imager::ImageTypes/setmask()>
4480 setpixel() - L<Imager::Draw/setpixel()>
4482 setsamples() - L<Imager::Draw/setsamples()>
4484 setscanline() - L<Imager::Draw/setscanline()>
4486 settag() - L<Imager::ImageTypes/settag()>
4488 string() - L<Imager::Draw/string()> - draw text on an image
4490 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4492 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4494 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4496 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4498 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4499 double per sample image.
4501 transform() - L<Imager::Engines/"transform()">
4503 transform2() - L<Imager::Engines/"transform2()">
4505 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4507 unload_plugin() - L<Imager::Filters/unload_plugin()>
4509 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4512 write() - L<Imager::Files> - write an image to a file
4514 write_multi() - L<Imager::Files> - write multiple image to an image
4517 write_types() - L<Imager::Files/read_types()> - list image types Imager
4520 =head1 CONCEPT INDEX
4522 animated GIF - L<Imager::Files/"Writing an animated GIF">
4524 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4525 L<Imager::ImageTypes/"Common Tags">.
4527 blend - alpha blending one image onto another
4528 L<Imager::Transformations/rubthrough()>
4530 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4532 boxes, drawing - L<Imager::Draw/box()>
4534 changes between image - L<Imager::Filters/"Image Difference">
4536 channels, combine into one image - L<Imager::Transformations/combine()>
4538 color - L<Imager::Color>
4540 color names - L<Imager::Color>, L<Imager::Color::Table>
4542 combine modes - L<Imager::Draw/"Combine Types">
4544 compare images - L<Imager::Filters/"Image Difference">
4546 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4548 convolution - L<Imager::Filters/conv>
4550 cropping - L<Imager::Transformations/crop()>
4552 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4554 C<diff> images - L<Imager::Filters/"Image Difference">
4556 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4557 L<Imager::Cookbook/"Image spatial resolution">
4559 drawing boxes - L<Imager::Draw/box()>
4561 drawing lines - L<Imager::Draw/line()>
4563 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4565 error message - L</"ERROR HANDLING">
4567 files, font - L<Imager::Font>
4569 files, image - L<Imager::Files>
4571 filling, types of fill - L<Imager::Fill>
4573 filling, boxes - L<Imager::Draw/box()>
4575 filling, flood fill - L<Imager::Draw/flood_fill()>
4577 flood fill - L<Imager::Draw/flood_fill()>
4579 fonts - L<Imager::Font>
4581 fonts, drawing with - L<Imager::Draw/string()>,
4582 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4584 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4586 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4588 fountain fill - L<Imager::Fill/"Fountain fills">,
4589 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4590 L<Imager::Filters/gradgen>
4592 GIF files - L<Imager::Files/"GIF">
4594 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4596 gradient fill - L<Imager::Fill/"Fountain fills">,
4597 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4598 L<Imager::Filters/gradgen>
4600 gray scale, convert image to - L<Imager::Transformations/convert()>
4602 gaussian blur - L<Imager::Filters/gaussian>
4604 hatch fills - L<Imager::Fill/"Hatched fills">
4606 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4608 invert image - L<Imager::Filters/hardinvert>,
4609 L<Imager::Filters/hardinvertall>
4611 JPEG - L<Imager::Files/"JPEG">
4613 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4615 lines, drawing - L<Imager::Draw/line()>
4617 matrix - L<Imager::Matrix2d>,
4618 L<Imager::Engines/"Matrix Transformations">,
4619 L<Imager::Font/transform()>
4621 metadata, image - L<Imager::ImageTypes/"Tags">
4623 mosaic - L<Imager::Filters/mosaic>
4625 noise, filter - L<Imager::Filters/noise>
4627 noise, rendered - L<Imager::Filters/turbnoise>,
4628 L<Imager::Filters/radnoise>
4630 paste - L<Imager::Transformations/paste()>,
4631 L<Imager::Transformations/rubthrough()>
4633 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4634 L<Imager::ImageTypes/new()>
4636 =for stopwords posterize
4638 posterize - L<Imager::Filters/postlevels>
4640 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4642 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4644 rectangles, drawing - L<Imager::Draw/box()>
4646 resizing an image - L<Imager::Transformations/scale()>,
4647 L<Imager::Transformations/crop()>
4649 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4651 saving an image - L<Imager::Files>
4653 scaling - L<Imager::Transformations/scale()>
4655 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4657 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4659 size, image - L<Imager::ImageTypes/getwidth()>,
4660 L<Imager::ImageTypes/getheight()>
4662 size, text - L<Imager::Font/bounding_box()>
4664 tags, image metadata - L<Imager::ImageTypes/"Tags">
4666 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4667 L<Imager::Font::Wrap>
4669 text, wrapping text in an area - L<Imager::Font::Wrap>
4671 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4673 tiles, color - L<Imager::Filters/mosaic>
4675 transparent images - L<Imager::ImageTypes>,
4676 L<Imager::Cookbook/"Transparent PNG">
4678 =for stopwords unsharp
4680 unsharp mask - L<Imager::Filters/unsharpmask>
4682 watermark - L<Imager::Filters/watermark>
4684 writing an image to a file - L<Imager::Files>
4688 Imager doesn't support perl threads.
4690 Imager has limited code to prevent double frees if you create images,
4691 colors etc, and then create a thread, but has no code to prevent two
4692 threads entering Imager's error handling code, and none is likely to
4697 The best place to get help with Imager is the mailing list.
4699 To subscribe send a message with C<subscribe> in the body to:
4701 imager-devel+request@molar.is
4707 L<http://www.molar.is/en/lists/imager-devel/>
4711 where you can also find the mailing list archive.
4713 You can report bugs by pointing your browser at:
4717 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4721 or by sending an email to:
4725 bug-Imager@rt.cpan.org
4729 Please remember to include the versions of Imager, perl, supporting
4730 libraries, and any relevant code. If you have specific images that
4731 cause the problems, please include those too.
4733 If you don't want to publish your email address on a mailing list you
4734 can use CPAN::Forum:
4736 http://www.cpanforum.com/dist/Imager
4738 You will need to register to post.
4740 =head1 CONTRIBUTING TO IMAGER
4746 If you like or dislike Imager, you can add a public review of Imager
4749 http://cpanratings.perl.org/dist/Imager
4751 =for stopwords Bitcard
4753 This requires a Bitcard account (http://www.bitcard.org).
4755 You can also send email to the maintainer below.
4757 If you send me a bug report via email, it will be copied to Request
4762 I accept patches, preferably against the main branch in subversion.
4763 You should include an explanation of the reason for why the patch is
4766 Your patch should include regression tests where possible, otherwise
4767 it will be delayed until I get a chance to write them.
4771 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
4773 Arnar M. Hrafnkelsson is the original author of Imager.
4775 Many others have contributed to Imager, please see the C<README> for a
4780 Imager is licensed under the same terms as perl itself.
4783 makeblendedfont Fontforge
4785 A test font, FT2/fontfiles/MMOne.pfb, contains a Postscript operator
4786 definition copyrighted by Adobe. See F<adobe.txt> in the source for
4787 license information.
4791 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4792 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4793 L<Imager::Font>(3), L<Imager::Transformations>(3),
4794 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4795 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4797 L<http://imager.perl.org/>
4799 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4801 Other perl imaging modules include:
4803 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).