4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
108 # registered file readers
111 # registered file writers
114 # modules we attempted to autoload
115 my %attempted_to_load;
117 # errors from loading files
118 my %file_load_errors;
120 # what happened when we tried to load
121 my %reader_load_errors;
122 my %writer_load_errors;
124 # library keys that are image file formats
125 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
127 # image pixel combine types
129 qw/none normal multiply dissolve add subtract diff lighten darken
130 hue saturation value color/;
132 @combine_types{@combine_types} = 0 .. $#combine_types;
133 $combine_types{mult} = $combine_types{multiply};
134 $combine_types{'sub'} = $combine_types{subtract};
135 $combine_types{sat} = $combine_types{saturation};
137 # this will be used to store global defaults at some point
142 my $ex_version = eval $Exporter::VERSION;
143 if ($ex_version < 5.57) {
148 XSLoader::load(Imager => $VERSION);
154 png => "Imager::File::PNG",
155 gif => "Imager::File::GIF",
156 tiff => "Imager::File::TIFF",
157 jpeg => "Imager::File::JPEG",
158 w32 => "Imager::Font::W32",
159 ft2 => "Imager::Font::FT2",
160 t1 => "Imager::Font::T1",
163 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
166 for(i_list_formats()) { $formats_low{$_}++; }
168 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
172 # the members of the subhashes under %filters are:
173 # callseq - a list of the parameters to the underlying filter in the
174 # order they are passed
175 # callsub - a code ref that takes a named parameter list and calls the
177 # defaults - a hash of default values
178 # names - defines names for value of given parameters so if the names
179 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
180 # foo parameter, the filter will receive 1 for the foo
183 callseq => ['image','intensity'],
184 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
188 callseq => ['image', 'amount', 'subtype'],
189 defaults => { amount=>3,subtype=>0 },
190 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
193 $filters{hardinvert} ={
194 callseq => ['image'],
196 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
199 $filters{hardinvertall} =
201 callseq => ['image'],
203 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
206 $filters{autolevels} ={
207 callseq => ['image','lsat','usat','skew'],
208 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
209 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
212 $filters{turbnoise} ={
213 callseq => ['image'],
214 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
215 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
218 $filters{radnoise} ={
219 callseq => ['image'],
220 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
221 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
226 callseq => ['image', 'coef'],
231 i_conv($hsh{image},$hsh{coef})
232 or die Imager->_error_as_msg() . "\n";
238 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
239 defaults => { dist => 0 },
243 my @colors = @{$hsh{colors}};
246 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
250 $filters{nearest_color} =
252 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
257 # make sure the segments are specified with colors
259 for my $color (@{$hsh{colors}}) {
260 my $new_color = _color($color)
261 or die $Imager::ERRSTR."\n";
262 push @colors, $new_color;
265 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
267 or die Imager->_error_as_msg() . "\n";
270 $filters{gaussian} = {
271 callseq => [ 'image', 'stddev' ],
273 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
277 callseq => [ qw(image size) ],
278 defaults => { size => 20 },
279 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
283 callseq => [ qw(image bump elevation lightx lighty st) ],
284 defaults => { elevation=>0, st=> 2 },
287 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
288 $hsh{lightx}, $hsh{lighty}, $hsh{st});
291 $filters{bumpmap_complex} =
293 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
310 for my $cname (qw/Ia Il Is/) {
311 my $old = $hsh{$cname};
312 my $new_color = _color($old)
313 or die $Imager::ERRSTR, "\n";
314 $hsh{$cname} = $new_color;
316 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
317 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
318 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
322 $filters{postlevels} =
324 callseq => [ qw(image levels) ],
325 defaults => { levels => 10 },
326 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
328 $filters{watermark} =
330 callseq => [ qw(image wmark tx ty pixdiff) ],
331 defaults => { pixdiff=>10, tx=>0, ty=>0 },
335 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
341 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
343 ftype => { linear => 0,
349 repeat => { none => 0,
364 multiply => 2, mult => 2,
367 subtract => 5, 'sub' => 5,
377 defaults => { ftype => 0, repeat => 0, combine => 0,
378 super_sample => 0, ssample_param => 4,
391 # make sure the segments are specified with colors
393 for my $segment (@{$hsh{segments}}) {
394 my @new_segment = @$segment;
396 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
397 push @segments, \@new_segment;
400 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
401 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
402 $hsh{ssample_param}, \@segments)
403 or die Imager->_error_as_msg() . "\n";
406 $filters{unsharpmask} =
408 callseq => [ qw(image stddev scale) ],
409 defaults => { stddev=>2.0, scale=>1.0 },
413 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
417 $FORMATGUESS=\&def_guess_type;
427 # NOTE: this might be moved to an import override later on
432 if ($_[$i] eq '-log-stderr') {
440 goto &Exporter::import;
444 Imager->open_log(log => $_[0], level => $_[1]);
449 my %parms=(loglevel=>1,@_);
451 if (exists $parms{'warn_obsolete'}) {
452 $warn_obsolete = $parms{'warn_obsolete'};
456 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
460 if (exists $parms{'t1log'}) {
462 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
463 Imager->_set_error(Imager->_error_as_msg);
477 my (%opts) = ( loglevel => 1, @_ );
479 $is_logging = i_init_log($opts{log}, $opts{loglevel});
480 unless ($is_logging) {
481 Imager->_set_error(Imager->_error_as_msg());
485 Imager->log("Imager $VERSION starting\n", 1);
491 i_init_log(undef, -1);
496 my ($class, $message, $level) = @_;
498 defined $level or $level = 1;
500 i_log_entry($message, $level);
510 print "shutdown code\n";
511 # for(keys %instances) { $instances{$_}->DESTROY(); }
512 malloc_state(); # how do decide if this should be used? -- store something from the import
513 print "Imager exiting\n";
517 # Load a filter plugin
522 my ($DSO_handle,$str)=DSO_open($filename);
523 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
524 my %funcs=DSO_funclist($DSO_handle);
525 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
527 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
529 $DSOs{$filename}=[$DSO_handle,\%funcs];
532 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
533 $DEBUG && print "eval string:\n",$evstr,"\n";
545 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
546 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
547 for(keys %{$funcref}) {
549 $DEBUG && print "unloading: $_\n";
551 my $rc=DSO_close($DSO_handle);
552 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
556 # take the results of i_error() and make a message out of it
558 return join(": ", map $_->[0], i_errors());
561 # this function tries to DWIM for color parameters
562 # color objects are used as is
563 # simple scalars are simply treated as single parameters to Imager::Color->new
564 # hashrefs are treated as named argument lists to Imager::Color->new
565 # arrayrefs are treated as list arguments to Imager::Color->new iff any
567 # other arrayrefs are treated as list arguments to Imager::Color::Float
571 # perl 5.6.0 seems to do weird things to $arg if we don't make an
572 # explicitly stringified copy
573 # I vaguely remember a bug on this on p5p, but couldn't find it
574 # through bugs.perl.org (I had trouble getting it to find any bugs)
575 my $copy = $arg . "";
579 if (UNIVERSAL::isa($arg, "Imager::Color")
580 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
584 if ($copy =~ /^HASH\(/) {
585 $result = Imager::Color->new(%$arg);
587 elsif ($copy =~ /^ARRAY\(/) {
588 $result = Imager::Color->new(@$arg);
591 $Imager::ERRSTR = "Not a color";
596 # assume Imager::Color::new knows how to handle it
597 $result = Imager::Color->new($arg);
604 my ($self, $combine, $default) = @_;
606 if (!defined $combine && ref $self) {
607 $combine = $self->{combine};
609 defined $combine or $combine = $defaults{combine};
610 defined $combine or $combine = $default;
612 if (exists $combine_types{$combine}) {
613 $combine = $combine_types{$combine};
620 my ($self, $method) = @_;
622 $self->{IMG} and return 1;
624 my $msg = 'empty input image';
625 $msg = "$method: $msg" if $method;
626 $self->_set_error($msg);
631 # returns first defined parameter
634 return $_ if defined $_;
640 # Methods to be called on objects.
643 # Create a new Imager object takes very few parameters.
644 # usually you call this method and then call open from
645 # the resulting object
652 $self->{IMG}=undef; # Just to indicate what exists
653 $self->{ERRSTR}=undef; #
654 $self->{DEBUG}=$DEBUG;
655 $self->{DEBUG} and print "Initialized Imager\n";
656 if (defined $hsh{xsize} || defined $hsh{ysize}) {
657 unless ($self->img_set(%hsh)) {
658 $Imager::ERRSTR = $self->{ERRSTR};
662 elsif (defined $hsh{file} ||
665 defined $hsh{callback} ||
666 defined $hsh{readcb} ||
667 defined $hsh{data}) {
668 # allow $img = Imager->new(file => $filename)
671 # type is already used as a parameter to new(), rename it for the
673 if ($hsh{filetype}) {
674 $extras{type} = $hsh{filetype};
676 unless ($self->read(%hsh, %extras)) {
677 $Imager::ERRSTR = $self->{ERRSTR};
685 # Copy an entire image with no changes
686 # - if an image has magic the copy of it will not be magical
690 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
692 unless (defined wantarray) {
694 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
698 my $newcopy=Imager->new();
699 $newcopy->{IMG} = i_copy($self->{IMG});
708 unless ($self->{IMG}) {
709 $self->_set_error('empty input image');
712 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
713 my $src = $input{img} || $input{src};
715 $self->_set_error("no source image");
718 $input{left}=0 if $input{left} <= 0;
719 $input{top}=0 if $input{top} <= 0;
721 my($r,$b)=i_img_info($src->{IMG});
722 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
723 my ($src_right, $src_bottom);
724 if ($input{src_coords}) {
725 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
728 if (defined $input{src_maxx}) {
729 $src_right = $input{src_maxx};
731 elsif (defined $input{width}) {
732 if ($input{width} <= 0) {
733 $self->_set_error("paste: width must me positive");
736 $src_right = $src_left + $input{width};
741 if (defined $input{src_maxy}) {
742 $src_bottom = $input{src_maxy};
744 elsif (defined $input{height}) {
745 if ($input{height} < 0) {
746 $self->_set_error("paste: height must be positive");
749 $src_bottom = $src_top + $input{height};
756 $src_right > $r and $src_right = $r;
757 $src_bottom > $b and $src_bottom = $b;
759 if ($src_right <= $src_left
760 || $src_bottom < $src_top) {
761 $self->_set_error("nothing to paste");
765 i_copyto($self->{IMG}, $src->{IMG},
766 $src_left, $src_top, $src_right, $src_bottom,
767 $input{left}, $input{top});
769 return $self; # What should go here??
772 # Crop an image - i.e. return a new image that is smaller
776 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
778 unless (defined wantarray) {
780 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
786 my ($w, $h, $l, $r, $b, $t) =
787 @hsh{qw(width height left right bottom top)};
789 # work through the various possibilities
794 elsif (!defined $r) {
795 $r = $self->getwidth;
807 $l = int(0.5+($self->getwidth()-$w)/2);
812 $r = $self->getwidth;
818 elsif (!defined $b) {
819 $b = $self->getheight;
831 $t=int(0.5+($self->getheight()-$h)/2);
836 $b = $self->getheight;
839 ($l,$r)=($r,$l) if $l>$r;
840 ($t,$b)=($b,$t) if $t>$b;
843 $r > $self->getwidth and $r = $self->getwidth;
845 $b > $self->getheight and $b = $self->getheight;
847 if ($l == $r || $t == $b) {
848 $self->_set_error("resulting image would have no content");
851 if( $r < $l or $b < $t ) {
852 $self->_set_error("attempting to crop outside of the image");
855 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
857 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
862 my ($self, %opts) = @_;
864 $self->{IMG} or return $self->_set_error("Not a valid image");
866 my $x = $opts{xsize} || $self->getwidth;
867 my $y = $opts{ysize} || $self->getheight;
868 my $channels = $opts{channels} || $self->getchannels;
870 my $out = Imager->new;
871 if ($channels == $self->getchannels) {
872 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
875 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
877 unless ($out->{IMG}) {
878 $self->{ERRSTR} = $self->_error_as_msg;
885 # Sets an image to a certain size and channel number
886 # if there was previously data in the image it is discarded
891 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
893 if (defined($self->{IMG})) {
894 # let IIM_DESTROY destroy it, it's possible this image is
895 # referenced from a virtual image (like masked)
896 #i_img_destroy($self->{IMG});
900 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
901 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
902 $hsh{maxcolors} || 256);
904 elsif ($hsh{bits} eq 'double') {
905 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
907 elsif ($hsh{bits} == 16) {
908 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
911 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
915 unless ($self->{IMG}) {
916 $self->{ERRSTR} = Imager->_error_as_msg();
923 # created a masked version of the current image
927 $self or return undef;
928 my %opts = (left => 0,
930 right => $self->getwidth,
931 bottom => $self->getheight,
933 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
935 my $result = Imager->new;
936 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
937 $opts{top}, $opts{right} - $opts{left},
938 $opts{bottom} - $opts{top});
939 unless ($result->{IMG}) {
940 $self->_set_error(Imager->_error_as_msg);
944 # keep references to the mask and base images so they don't
946 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
951 # convert an RGB image into a paletted image
955 if (@_ != 1 && !ref $_[0]) {
962 unless (defined wantarray) {
964 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
971 my $result = Imager->new;
972 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
973 $self->_set_error(Imager->_error_as_msg);
981 my ($class, $quant, @images) = @_;
984 Imager->_set_error("make_palette: supply at least one image");
988 for my $img (@images) {
989 unless ($img->{IMG}) {
990 Imager->_set_error("make_palette: image $index is empty");
996 return i_img_make_palette($quant, map $_->{IMG}, @images);
999 # convert a paletted (or any image) to an 8-bit/channel RGB image
1003 unless (defined wantarray) {
1004 my @caller = caller;
1005 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1012 my $result = Imager->new;
1013 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1014 $self->_set_error(Imager->_error_as_msg());
1021 # convert a paletted (or any image) to a 16-bit/channel RGB image
1025 unless (defined wantarray) {
1026 my @caller = caller;
1027 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1034 my $result = Imager->new;
1035 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1036 $self->_set_error(Imager->_error_as_msg());
1043 # convert a paletted (or any image) to an double/channel RGB image
1047 unless (defined wantarray) {
1048 my @caller = caller;
1049 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1056 my $result = Imager->new;
1057 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1058 $self->_set_error(Imager->_error_as_msg());
1067 my %opts = (colors=>[], @_);
1069 unless ($self->{IMG}) {
1070 $self->_set_error("empty input image");
1074 my @colors = @{$opts{colors}}
1077 for my $color (@colors) {
1078 $color = _color($color);
1080 $self->_set_error($Imager::ERRSTR);
1085 return i_addcolors($self->{IMG}, @colors);
1090 my %opts = (start=>0, colors=>[], @_);
1092 unless ($self->{IMG}) {
1093 $self->_set_error("empty input image");
1097 my @colors = @{$opts{colors}}
1100 for my $color (@colors) {
1101 $color = _color($color);
1103 $self->_set_error($Imager::ERRSTR);
1108 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1114 if (!exists $opts{start} && !exists $opts{count}) {
1117 $opts{count} = $self->colorcount;
1119 elsif (!exists $opts{count}) {
1122 elsif (!exists $opts{start}) {
1127 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1131 i_colorcount($_[0]{IMG});
1135 i_maxcolors($_[0]{IMG});
1141 $opts{color} or return undef;
1143 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1148 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1149 if ($bits && $bits == length(pack("d", 1)) * 8) {
1158 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1164 $self->{IMG} and i_img_virtual($self->{IMG});
1170 $self->{IMG} or return;
1172 return i_img_is_monochrome($self->{IMG});
1176 my ($self, %opts) = @_;
1178 $self->{IMG} or return;
1180 if (defined $opts{name}) {
1184 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1185 push @result, (i_tags_get($self->{IMG}, $found))[1];
1188 return wantarray ? @result : $result[0];
1190 elsif (defined $opts{code}) {
1194 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1195 push @result, (i_tags_get($self->{IMG}, $found))[1];
1202 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1205 return i_tags_count($self->{IMG});
1214 return -1 unless $self->{IMG};
1216 if (defined $opts{value}) {
1217 if ($opts{value} =~ /^\d+$/) {
1219 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1222 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1225 elsif (defined $opts{data}) {
1226 # force addition as a string
1227 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1230 $self->{ERRSTR} = "No value supplied";
1234 elsif ($opts{code}) {
1235 if (defined $opts{value}) {
1236 if ($opts{value} =~ /^\d+$/) {
1238 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1241 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1244 elsif (defined $opts{data}) {
1245 # force addition as a string
1246 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1249 $self->{ERRSTR} = "No value supplied";
1262 return 0 unless $self->{IMG};
1264 if (defined $opts{'index'}) {
1265 return i_tags_delete($self->{IMG}, $opts{'index'});
1267 elsif (defined $opts{name}) {
1268 return i_tags_delbyname($self->{IMG}, $opts{name});
1270 elsif (defined $opts{code}) {
1271 return i_tags_delbycode($self->{IMG}, $opts{code});
1274 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1280 my ($self, %opts) = @_;
1283 $self->deltag(name=>$opts{name});
1284 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1286 elsif (defined $opts{code}) {
1287 $self->deltag(code=>$opts{code});
1288 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1296 sub _get_reader_io {
1297 my ($self, $input) = @_;
1300 return $input->{io}, undef;
1302 elsif ($input->{fd}) {
1303 return io_new_fd($input->{fd});
1305 elsif ($input->{fh}) {
1306 my $fd = fileno($input->{fh});
1307 unless (defined $fd) {
1308 $self->_set_error("Handle in fh option not opened");
1311 return io_new_fd($fd);
1313 elsif ($input->{file}) {
1314 my $file = IO::File->new($input->{file}, "r");
1316 $self->_set_error("Could not open $input->{file}: $!");
1320 return (io_new_fd(fileno($file)), $file);
1322 elsif ($input->{data}) {
1323 return io_new_buffer($input->{data});
1325 elsif ($input->{callback} || $input->{readcb}) {
1326 if (!$input->{seekcb}) {
1327 $self->_set_error("Need a seekcb parameter");
1329 if ($input->{maxbuffer}) {
1330 return io_new_cb($input->{writecb},
1331 $input->{callback} || $input->{readcb},
1332 $input->{seekcb}, $input->{closecb},
1333 $input->{maxbuffer});
1336 return io_new_cb($input->{writecb},
1337 $input->{callback} || $input->{readcb},
1338 $input->{seekcb}, $input->{closecb});
1342 $self->_set_error("file/fd/fh/data/callback parameter missing");
1347 sub _get_writer_io {
1348 my ($self, $input) = @_;
1350 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1357 elsif ($input->{fd}) {
1358 $io = io_new_fd($input->{fd});
1360 elsif ($input->{fh}) {
1361 my $fd = fileno($input->{fh});
1362 unless (defined $fd) {
1363 $self->_set_error("Handle in fh option not opened");
1367 my $oldfh = select($input->{fh});
1368 # flush anything that's buffered, and make sure anything else is flushed
1371 $io = io_new_fd($fd);
1373 elsif ($input->{file}) {
1374 my $fh = new IO::File($input->{file},"w+");
1376 $self->_set_error("Could not open file $input->{file}: $!");
1379 binmode($fh) or die;
1380 $io = io_new_fd(fileno($fh));
1383 elsif ($input->{data}) {
1384 $io = io_new_bufchain();
1386 elsif ($input->{callback} || $input->{writecb}) {
1387 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1390 $io = io_new_cb($input->{callback} || $input->{writecb},
1392 $input->{seekcb}, $input->{closecb});
1395 $self->_set_error("file/fd/fh/data/callback parameter missing");
1399 unless ($buffered) {
1400 $io->set_buffered(0);
1403 return ($io, @extras);
1406 # Read an image from file
1412 if (defined($self->{IMG})) {
1413 # let IIM_DESTROY do the destruction, since the image may be
1414 # referenced from elsewhere
1415 #i_img_destroy($self->{IMG});
1416 undef($self->{IMG});
1419 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1421 my $type = $input{'type'};
1423 $type = i_test_format_probe($IO, -1);
1426 if ($input{file} && !$type) {
1428 $type = $FORMATGUESS->($input{file});
1432 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1433 $input{file} and $msg .= " or file name";
1434 $self->_set_error($msg);
1438 _reader_autoload($type);
1440 if ($readers{$type} && $readers{$type}{single}) {
1441 return $readers{$type}{single}->($self, $IO, %input);
1444 unless ($formats_low{$type}) {
1445 my $read_types = join ', ', sort Imager->read_types();
1446 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1450 my $allow_incomplete = $input{allow_incomplete};
1451 defined $allow_incomplete or $allow_incomplete = 0;
1453 if ( $type eq 'pnm' ) {
1454 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1455 if ( !defined($self->{IMG}) ) {
1456 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1459 $self->{DEBUG} && print "loading a pnm file\n";
1463 if ( $type eq 'bmp' ) {
1464 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1465 if ( !defined($self->{IMG}) ) {
1466 $self->{ERRSTR}=$self->_error_as_msg();
1469 $self->{DEBUG} && print "loading a bmp file\n";
1472 if ( $type eq 'tga' ) {
1473 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1474 if ( !defined($self->{IMG}) ) {
1475 $self->{ERRSTR}=$self->_error_as_msg();
1478 $self->{DEBUG} && print "loading a tga file\n";
1481 if ( $type eq 'raw' ) {
1482 unless ( $input{xsize} && $input{ysize} ) {
1483 $self->_set_error('missing xsize or ysize parameter for raw');
1487 my $interleave = _first($input{raw_interleave}, $input{interleave});
1488 unless (defined $interleave) {
1489 my @caller = caller;
1490 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1493 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1494 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1496 $self->{IMG} = i_readraw_wiol( $IO,
1502 if ( !defined($self->{IMG}) ) {
1503 $self->{ERRSTR}=$self->_error_as_msg();
1506 $self->{DEBUG} && print "loading a raw file\n";
1512 sub register_reader {
1513 my ($class, %opts) = @_;
1516 or die "register_reader called with no type parameter\n";
1518 my $type = $opts{type};
1520 defined $opts{single} || defined $opts{multiple}
1521 or die "register_reader called with no single or multiple parameter\n";
1523 $readers{$type} = { };
1524 if ($opts{single}) {
1525 $readers{$type}{single} = $opts{single};
1527 if ($opts{multiple}) {
1528 $readers{$type}{multiple} = $opts{multiple};
1534 sub register_writer {
1535 my ($class, %opts) = @_;
1538 or die "register_writer called with no type parameter\n";
1540 my $type = $opts{type};
1542 defined $opts{single} || defined $opts{multiple}
1543 or die "register_writer called with no single or multiple parameter\n";
1545 $writers{$type} = { };
1546 if ($opts{single}) {
1547 $writers{$type}{single} = $opts{single};
1549 if ($opts{multiple}) {
1550 $writers{$type}{multiple} = $opts{multiple};
1561 grep($file_formats{$_}, keys %formats),
1562 qw(ico sgi), # formats not handled directly, but supplied with Imager
1573 grep($file_formats{$_}, keys %formats),
1574 qw(ico sgi), # formats not handled directly, but supplied with Imager
1581 my ($file, $error) = @_;
1583 if ($attempted_to_load{$file}) {
1584 if ($file_load_errors{$file}) {
1585 $$error = $file_load_errors{$file};
1593 local $SIG{__DIE__};
1595 ++$attempted_to_load{$file};
1603 my $work = $@ || "Unknown error";
1605 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1606 $work =~ s/\n/\\n/g;
1607 $work =~ s/\s*\.?\z/ loading $file/;
1608 $file_load_errors{$file} = $work;
1615 # probes for an Imager::File::whatever module
1616 sub _reader_autoload {
1619 return if $formats_low{$type} || $readers{$type};
1621 return unless $type =~ /^\w+$/;
1623 my $file = "Imager/File/\U$type\E.pm";
1626 my $loaded = _load_file($file, \$error);
1627 if (!$loaded && $error =~ /^Can't locate /) {
1628 my $filer = "Imager/File/\U$type\EReader.pm";
1629 $loaded = _load_file($filer, \$error);
1630 if ($error =~ /^Can't locate /) {
1631 $error = "Can't locate $file or $filer";
1635 $reader_load_errors{$type} = $error;
1639 # probes for an Imager::File::whatever module
1640 sub _writer_autoload {
1643 return if $formats_low{$type} || $writers{$type};
1645 return unless $type =~ /^\w+$/;
1647 my $file = "Imager/File/\U$type\E.pm";
1650 my $loaded = _load_file($file, \$error);
1651 if (!$loaded && $error =~ /^Can't locate /) {
1652 my $filew = "Imager/File/\U$type\EWriter.pm";
1653 $loaded = _load_file($filew, \$error);
1654 if ($error =~ /^Can't locate /) {
1655 $error = "Can't locate $file or $filew";
1659 $writer_load_errors{$type} = $error;
1663 sub _fix_gif_positions {
1664 my ($opts, $opt, $msg, @imgs) = @_;
1666 my $positions = $opts->{'gif_positions'};
1668 for my $pos (@$positions) {
1669 my ($x, $y) = @$pos;
1670 my $img = $imgs[$index++];
1671 $img->settag(name=>'gif_left', value=>$x);
1672 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1674 $$msg .= "replaced with the gif_left and gif_top tags";
1679 gif_each_palette=>'gif_local_map',
1680 interlace => 'gif_interlace',
1681 gif_delays => 'gif_delay',
1682 gif_positions => \&_fix_gif_positions,
1683 gif_loop_count => 'gif_loop',
1686 # options that should be converted to colors
1687 my %color_opts = map { $_ => 1 } qw/i_background/;
1690 my ($self, $opts, $prefix, @imgs) = @_;
1692 for my $opt (keys %$opts) {
1694 if ($obsolete_opts{$opt}) {
1695 my $new = $obsolete_opts{$opt};
1696 my $msg = "Obsolete option $opt ";
1698 $new->($opts, $opt, \$msg, @imgs);
1701 $msg .= "replaced with the $new tag ";
1704 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1705 warn $msg if $warn_obsolete && $^W;
1707 next unless $tagname =~ /^\Q$prefix/;
1708 my $value = $opts->{$opt};
1709 if ($color_opts{$opt}) {
1710 $value = _color($value);
1712 $self->_set_error($Imager::ERRSTR);
1717 if (UNIVERSAL::isa($value, "Imager::Color")) {
1718 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1719 for my $img (@imgs) {
1720 $img->settag(name=>$tagname, value=>$tag);
1723 elsif (ref($value) eq 'ARRAY') {
1724 for my $i (0..$#$value) {
1725 my $val = $value->[$i];
1727 if (UNIVERSAL::isa($val, "Imager::Color")) {
1728 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1730 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1733 $self->_set_error("Unknown reference type " . ref($value) .
1734 " supplied in array for $opt");
1740 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1745 $self->_set_error("Unknown reference type " . ref($value) .
1746 " supplied for $opt");
1751 # set it as a tag for every image
1752 for my $img (@imgs) {
1753 $img->settag(name=>$tagname, value=>$value);
1761 # Write an image to file
1764 my %input=(jpegquality=>75,
1774 $self->_set_opts(\%input, "i_", $self)
1777 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1779 my $type = $input{'type'};
1780 if (!$type and $input{file}) {
1781 $type = $FORMATGUESS->($input{file});
1784 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1788 _writer_autoload($type);
1791 if ($writers{$type} && $writers{$type}{single}) {
1792 ($IO, $fh) = $self->_get_writer_io(\%input)
1795 $writers{$type}{single}->($self, $IO, %input, type => $type)
1799 if (!$formats_low{$type}) {
1800 my $write_types = join ', ', sort Imager->write_types();
1801 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1805 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1808 if ( $type eq 'pnm' ) {
1809 $self->_set_opts(\%input, "pnm_", $self)
1811 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1812 $self->{ERRSTR} = $self->_error_as_msg();
1815 $self->{DEBUG} && print "writing a pnm file\n";
1817 elsif ( $type eq 'raw' ) {
1818 $self->_set_opts(\%input, "raw_", $self)
1820 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1821 $self->{ERRSTR} = $self->_error_as_msg();
1824 $self->{DEBUG} && print "writing a raw file\n";
1826 elsif ( $type eq 'bmp' ) {
1827 $self->_set_opts(\%input, "bmp_", $self)
1829 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1830 $self->{ERRSTR} = $self->_error_as_msg;
1833 $self->{DEBUG} && print "writing a bmp file\n";
1835 elsif ( $type eq 'tga' ) {
1836 $self->_set_opts(\%input, "tga_", $self)
1839 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1840 $self->{ERRSTR}=$self->_error_as_msg();
1843 $self->{DEBUG} && print "writing a tga file\n";
1847 if (exists $input{'data'}) {
1848 my $data = io_slurp($IO);
1850 $self->{ERRSTR}='Could not slurp from buffer';
1853 ${$input{data}} = $data;
1859 my ($class, $opts, @images) = @_;
1861 my $type = $opts->{type};
1863 if (!$type && $opts->{'file'}) {
1864 $type = $FORMATGUESS->($opts->{'file'});
1867 $class->_set_error('type parameter missing and not possible to guess from extension');
1870 # translate to ImgRaw
1871 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1872 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1875 $class->_set_opts($opts, "i_", @images)
1877 my @work = map $_->{IMG}, @images;
1879 _writer_autoload($type);
1882 if ($writers{$type} && $writers{$type}{multiple}) {
1883 ($IO, $file) = $class->_get_writer_io($opts, $type)
1886 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1890 if (!$formats{$type}) {
1891 my $write_types = join ', ', sort Imager->write_types();
1892 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1896 ($IO, $file) = $class->_get_writer_io($opts, $type)
1899 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1903 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1908 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1914 if (exists $opts->{'data'}) {
1915 my $data = io_slurp($IO);
1917 Imager->_set_error('Could not slurp from buffer');
1920 ${$opts->{data}} = $data;
1925 # read multiple images from a file
1927 my ($class, %opts) = @_;
1929 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1932 my $type = $opts{'type'};
1934 $type = i_test_format_probe($IO, -1);
1937 if ($opts{file} && !$type) {
1939 $type = $FORMATGUESS->($opts{file});
1943 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1944 $opts{file} and $msg .= " or file name";
1945 Imager->_set_error($msg);
1949 _reader_autoload($type);
1951 if ($readers{$type} && $readers{$type}{multiple}) {
1952 return $readers{$type}{multiple}->($IO, %opts);
1955 unless ($formats{$type}) {
1956 my $read_types = join ', ', sort Imager->read_types();
1957 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1962 if ($type eq 'pnm') {
1963 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1966 my $img = Imager->new;
1967 if ($img->read(%opts, io => $IO, type => $type)) {
1970 Imager->_set_error($img->errstr);
1975 $ERRSTR = _error_as_msg();
1979 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1983 # Destroy an Imager object
1987 # delete $instances{$self};
1988 if (defined($self->{IMG})) {
1989 # the following is now handled by the XS DESTROY method for
1990 # Imager::ImgRaw object
1991 # Re-enabling this will break virtual images
1992 # tested for in t/t020masked.t
1993 # i_img_destroy($self->{IMG});
1994 undef($self->{IMG});
1996 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2000 # Perform an inplace filter of an image
2001 # that is the image will be overwritten with the data
2007 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2009 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2011 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2012 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2015 if ($filters{$input{'type'}}{names}) {
2016 my $names = $filters{$input{'type'}}{names};
2017 for my $name (keys %$names) {
2018 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2019 $input{$name} = $names->{$name}{$input{$name}};
2023 if (defined($filters{$input{'type'}}{defaults})) {
2024 %hsh=( image => $self->{IMG},
2026 %{$filters{$input{'type'}}{defaults}},
2029 %hsh=( image => $self->{IMG},
2034 my @cs=@{$filters{$input{'type'}}{callseq}};
2037 if (!defined($hsh{$_})) {
2038 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2043 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2044 &{$filters{$input{'type'}}{callsub}}(%hsh);
2047 chomp($self->{ERRSTR} = $@);
2053 $self->{DEBUG} && print "callseq is: @cs\n";
2054 $self->{DEBUG} && print "matching callseq is: @b\n";
2059 sub register_filter {
2061 my %hsh = ( defaults => {}, @_ );
2064 or die "register_filter() with no type\n";
2065 defined $hsh{callsub}
2066 or die "register_filter() with no callsub\n";
2067 defined $hsh{callseq}
2068 or die "register_filter() with no callseq\n";
2070 exists $filters{$hsh{type}}
2073 $filters{$hsh{type}} = \%hsh;
2078 sub scale_calculate {
2081 my %opts = ('type'=>'max', @_);
2083 # none of these should be references
2084 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2085 if (defined $opts{$name} && ref $opts{$name}) {
2086 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2091 my ($x_scale, $y_scale);
2092 my $width = $opts{width};
2093 my $height = $opts{height};
2095 defined $width or $width = $self->getwidth;
2096 defined $height or $height = $self->getheight;
2099 unless (defined $width && defined $height) {
2100 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2105 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2106 $x_scale = $opts{'xscalefactor'};
2107 $y_scale = $opts{'yscalefactor'};
2109 elsif ($opts{'xscalefactor'}) {
2110 $x_scale = $opts{'xscalefactor'};
2111 $y_scale = $opts{'scalefactor'} || $x_scale;
2113 elsif ($opts{'yscalefactor'}) {
2114 $y_scale = $opts{'yscalefactor'};
2115 $x_scale = $opts{'scalefactor'} || $y_scale;
2118 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2121 # work out the scaling
2122 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2123 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2124 $opts{ypixels} / $height );
2125 if ($opts{'type'} eq 'min') {
2126 $x_scale = $y_scale = _min($xpix,$ypix);
2128 elsif ($opts{'type'} eq 'max') {
2129 $x_scale = $y_scale = _max($xpix,$ypix);
2131 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2136 $self->_set_error('invalid value for type parameter');
2139 } elsif ($opts{xpixels}) {
2140 $x_scale = $y_scale = $opts{xpixels} / $width;
2142 elsif ($opts{ypixels}) {
2143 $x_scale = $y_scale = $opts{ypixels}/$height;
2145 elsif ($opts{constrain} && ref $opts{constrain}
2146 && $opts{constrain}->can('constrain')) {
2147 # we've been passed an Image::Math::Constrain object or something
2148 # that looks like one
2150 (undef, undef, $scalefactor)
2151 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2152 unless ($scalefactor) {
2153 $self->_set_error('constrain method failed on constrain parameter');
2156 $x_scale = $y_scale = $scalefactor;
2159 my $new_width = int($x_scale * $width + 0.5);
2160 $new_width > 0 or $new_width = 1;
2161 my $new_height = int($y_scale * $height + 0.5);
2162 $new_height > 0 or $new_height = 1;
2164 return ($x_scale, $y_scale, $new_width, $new_height);
2168 # Scale an image to requested size and return the scaled version
2172 my %opts = (qtype=>'normal' ,@_);
2173 my $img = Imager->new();
2174 my $tmp = Imager->new();
2176 unless (defined wantarray) {
2177 my @caller = caller;
2178 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2182 unless ($self->{IMG}) {
2183 $self->_set_error('empty input image');
2187 my ($x_scale, $y_scale, $new_width, $new_height) =
2188 $self->scale_calculate(%opts)
2191 if ($opts{qtype} eq 'normal') {
2192 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2193 if ( !defined($tmp->{IMG}) ) {
2194 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2197 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2198 if ( !defined($img->{IMG}) ) {
2199 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2205 elsif ($opts{'qtype'} eq 'preview') {
2206 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2207 if ( !defined($img->{IMG}) ) {
2208 $self->{ERRSTR}='unable to scale image';
2213 elsif ($opts{'qtype'} eq 'mixing') {
2214 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2215 unless ($img->{IMG}) {
2216 $self->_set_error(Imager->_error_as_msg);
2222 $self->_set_error('invalid value for qtype parameter');
2227 # Scales only along the X axis
2231 my %opts = ( scalefactor=>0.5, @_ );
2233 unless (defined wantarray) {
2234 my @caller = caller;
2235 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2239 unless ($self->{IMG}) {
2240 $self->{ERRSTR} = 'empty input image';
2244 my $img = Imager->new();
2246 my $scalefactor = $opts{scalefactor};
2248 if ($opts{pixels}) {
2249 $scalefactor = $opts{pixels} / $self->getwidth();
2252 unless ($self->{IMG}) {
2253 $self->{ERRSTR}='empty input image';
2257 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2259 if ( !defined($img->{IMG}) ) {
2260 $self->{ERRSTR} = 'unable to scale image';
2267 # Scales only along the Y axis
2271 my %opts = ( scalefactor => 0.5, @_ );
2273 unless (defined wantarray) {
2274 my @caller = caller;
2275 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2279 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2281 my $img = Imager->new();
2283 my $scalefactor = $opts{scalefactor};
2285 if ($opts{pixels}) {
2286 $scalefactor = $opts{pixels} / $self->getheight();
2289 unless ($self->{IMG}) {
2290 $self->{ERRSTR} = 'empty input image';
2293 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2295 if ( !defined($img->{IMG}) ) {
2296 $self->{ERRSTR} = 'unable to scale image';
2303 # Transform returns a spatial transformation of the input image
2304 # this moves pixels to a new location in the returned image.
2305 # NOTE - should make a utility function to check transforms for
2310 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2312 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2314 # print Dumper(\%opts);
2317 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2319 eval ("use Affix::Infix2Postfix;");
2322 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2325 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2326 {op=>'-',trans=>'Sub'},
2327 {op=>'*',trans=>'Mult'},
2328 {op=>'/',trans=>'Div'},
2329 {op=>'-','type'=>'unary',trans=>'u-'},
2331 {op=>'func','type'=>'unary'}],
2332 'grouping'=>[qw( \( \) )],
2333 'func'=>[qw( sin cos )],
2338 @xt=$I2P->translate($opts{'xexpr'});
2339 @yt=$I2P->translate($opts{'yexpr'});
2341 $numre=$I2P->{'numre'};
2344 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2345 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2346 @{$opts{'parm'}}=@pt;
2349 # print Dumper(\%opts);
2351 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2352 $self->{ERRSTR}='transform: no xopcodes given.';
2356 @op=@{$opts{'xopcodes'}};
2358 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2359 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2362 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2368 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2369 $self->{ERRSTR}='transform: no yopcodes given.';
2373 @op=@{$opts{'yopcodes'}};
2375 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2376 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2379 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2384 if ( !exists $opts{'parm'}) {
2385 $self->{ERRSTR}='transform: no parameter arg given.';
2389 # print Dumper(\@ropx);
2390 # print Dumper(\@ropy);
2391 # print Dumper(\@ropy);
2393 my $img = Imager->new();
2394 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2395 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2401 my ($opts, @imgs) = @_;
2403 require "Imager/Expr.pm";
2405 $opts->{variables} = [ qw(x y) ];
2406 my ($width, $height) = @{$opts}{qw(width height)};
2408 $width ||= $imgs[0]->getwidth();
2409 $height ||= $imgs[0]->getheight();
2411 for my $img (@imgs) {
2412 $opts->{constants}{"w$img_num"} = $img->getwidth();
2413 $opts->{constants}{"h$img_num"} = $img->getheight();
2414 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2415 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2420 $opts->{constants}{w} = $width;
2421 $opts->{constants}{cx} = $width/2;
2424 $Imager::ERRSTR = "No width supplied";
2428 $opts->{constants}{h} = $height;
2429 $opts->{constants}{cy} = $height/2;
2432 $Imager::ERRSTR = "No height supplied";
2435 my $code = Imager::Expr->new($opts);
2437 $Imager::ERRSTR = Imager::Expr::error();
2440 my $channels = $opts->{channels} || 3;
2441 unless ($channels >= 1 && $channels <= 4) {
2442 return Imager->_set_error("channels must be an integer between 1 and 4");
2445 my $img = Imager->new();
2446 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2447 $channels, $code->code(),
2448 $code->nregs(), $code->cregs(),
2449 [ map { $_->{IMG} } @imgs ]);
2450 if (!defined $img->{IMG}) {
2451 $Imager::ERRSTR = Imager->_error_as_msg();
2462 unless ($self->{IMG}) {
2463 $self->{ERRSTR}='empty input image';
2466 unless ($opts{src} && $opts{src}->{IMG}) {
2467 $self->{ERRSTR}='empty input image for src';
2471 %opts = (src_minx => 0,
2473 src_maxx => $opts{src}->getwidth(),
2474 src_maxy => $opts{src}->getheight(),
2478 defined $tx or $tx = $opts{left};
2479 defined $tx or $tx = 0;
2482 defined $ty or $ty = $opts{top};
2483 defined $ty or $ty = 0;
2485 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2486 $opts{src_minx}, $opts{src_miny},
2487 $opts{src_maxx}, $opts{src_maxy})) {
2488 $self->_set_error($self->_error_as_msg());
2505 unless ($self->{IMG}) {
2506 $self->_set_error("compose: empty input image");
2510 unless ($opts{src}) {
2511 $self->_set_error("compose: src parameter missing");
2515 unless ($opts{src}{IMG}) {
2516 $self->_set_error("compose: src parameter empty image");
2519 my $src = $opts{src};
2521 my $left = $opts{left};
2522 defined $left or $left = $opts{tx};
2523 defined $left or $left = 0;
2525 my $top = $opts{top};
2526 defined $top or $top = $opts{ty};
2527 defined $top or $top = 0;
2529 my $src_left = $opts{src_left};
2530 defined $src_left or $src_left = $opts{src_minx};
2531 defined $src_left or $src_left = 0;
2533 my $src_top = $opts{src_top};
2534 defined $src_top or $src_top = $opts{src_miny};
2535 defined $src_top or $src_top = 0;
2537 my $width = $opts{width};
2538 if (!defined $width && defined $opts{src_maxx}) {
2539 $width = $opts{src_maxx} - $src_left;
2541 defined $width or $width = $src->getwidth() - $src_left;
2543 my $height = $opts{height};
2544 if (!defined $height && defined $opts{src_maxy}) {
2545 $height = $opts{src_maxy} - $src_top;
2547 defined $height or $height = $src->getheight() - $src_top;
2549 my $combine = $self->_combine($opts{combine}, 'normal');
2552 unless ($opts{mask}{IMG}) {
2553 $self->_set_error("compose: mask parameter empty image");
2557 my $mask_left = $opts{mask_left};
2558 defined $mask_left or $mask_left = $opts{mask_minx};
2559 defined $mask_left or $mask_left = 0;
2561 my $mask_top = $opts{mask_top};
2562 defined $mask_top or $mask_top = $opts{mask_miny};
2563 defined $mask_top or $mask_top = 0;
2565 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2566 $left, $top, $src_left, $src_top,
2567 $mask_left, $mask_top, $width, $height,
2568 $combine, $opts{opacity})) {
2569 $self->_set_error(Imager->_error_as_msg);
2574 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2575 $width, $height, $combine, $opts{opacity})) {
2576 $self->_set_error(Imager->_error_as_msg);
2587 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2589 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2590 $dir = $xlate{$opts{'dir'}};
2591 return $self if i_flipxy($self->{IMG}, $dir);
2599 unless (defined wantarray) {
2600 my @caller = caller;
2601 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2605 if (defined $opts{right}) {
2606 my $degrees = $opts{right};
2608 $degrees += 360 * int(((-$degrees)+360)/360);
2610 $degrees = $degrees % 360;
2611 if ($degrees == 0) {
2612 return $self->copy();
2614 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2615 my $result = Imager->new();
2616 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2620 $self->{ERRSTR} = $self->_error_as_msg();
2625 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2629 elsif (defined $opts{radians} || defined $opts{degrees}) {
2630 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2632 my $back = $opts{back};
2633 my $result = Imager->new;
2635 $back = _color($back);
2637 $self->_set_error(Imager->errstr);
2641 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2644 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2646 if ($result->{IMG}) {
2650 $self->{ERRSTR} = $self->_error_as_msg();
2655 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2660 sub matrix_transform {
2664 unless (defined wantarray) {
2665 my @caller = caller;
2666 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2670 if ($opts{matrix}) {
2671 my $xsize = $opts{xsize} || $self->getwidth;
2672 my $ysize = $opts{ysize} || $self->getheight;
2674 my $result = Imager->new;
2676 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2677 $opts{matrix}, $opts{back})
2681 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2689 $self->{ERRSTR} = "matrix parameter required";
2695 *yatf = \&matrix_transform;
2697 # These two are supported for legacy code only
2700 return Imager::Color->new(@_);
2704 return Imager::Color::set(@_);
2707 # Draws a box between the specified corner points.
2710 my $raw = $self->{IMG};
2713 $self->{ERRSTR}='empty input image';
2719 my ($xmin, $ymin, $xmax, $ymax);
2720 if (exists $opts{'box'}) {
2721 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2722 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2723 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2724 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2727 defined($xmin = $opts{xmin}) or $xmin = 0;
2728 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2729 defined($ymin = $opts{ymin}) or $ymin = 0;
2730 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2733 if ($opts{filled}) {
2734 my $color = $opts{'color'};
2736 if (defined $color) {
2737 unless (_is_color_object($color)) {
2738 $color = _color($color);
2740 $self->{ERRSTR} = $Imager::ERRSTR;
2746 $color = i_color_new(255,255,255,255);
2749 if ($color->isa("Imager::Color")) {
2750 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2753 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2756 elsif ($opts{fill}) {
2757 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2758 # assume it's a hash ref
2759 require 'Imager/Fill.pm';
2760 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2761 $self->{ERRSTR} = $Imager::ERRSTR;
2765 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2768 my $color = $opts{'color'};
2769 if (defined $color) {
2770 unless (_is_color_object($color)) {
2771 $color = _color($color);
2773 $self->{ERRSTR} = $Imager::ERRSTR;
2779 $color = i_color_new(255, 255, 255, 255);
2782 $self->{ERRSTR} = $Imager::ERRSTR;
2785 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2793 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2794 my $dflcl= [ 255, 255, 255, 255];
2799 'r'=>_min($self->getwidth(),$self->getheight())/3,
2800 'x'=>$self->getwidth()/2,
2801 'y'=>$self->getheight()/2,
2808 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2809 # assume it's a hash ref
2810 require 'Imager/Fill.pm';
2811 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2812 $self->{ERRSTR} = $Imager::ERRSTR;
2816 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2817 $opts{'d2'}, $opts{fill}{fill});
2819 elsif ($opts{filled}) {
2820 my $color = _color($opts{'color'});
2822 $self->{ERRSTR} = $Imager::ERRSTR;
2825 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2826 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2830 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2831 $opts{'d1'}, $opts{'d2'}, $color);
2835 my $color = _color($opts{'color'});
2836 if ($opts{d2} - $opts{d1} >= 360) {
2837 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2840 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2846 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2847 # assume it's a hash ref
2848 require 'Imager/Fill.pm';
2849 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2850 $self->{ERRSTR} = $Imager::ERRSTR;
2854 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2855 $opts{'d2'}, $opts{fill}{fill});
2858 my $color = _color($opts{'color'});
2860 $self->{ERRSTR} = $Imager::ERRSTR;
2863 if ($opts{filled}) {
2864 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2865 $opts{'d1'}, $opts{'d2'}, $color);
2868 if ($opts{d1} == 0 && $opts{d2} == 361) {
2869 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2872 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2878 $self->_set_error($self->_error_as_msg);
2885 # Draws a line from one point to the other
2886 # the endpoint is set if the endp parameter is set which it is by default.
2887 # to turn of the endpoint being set use endp=>0 when calling line.
2891 my $dflcl=i_color_new(0,0,0,0);
2892 my %opts=(color=>$dflcl,
2895 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2897 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2898 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2900 my $color = _color($opts{'color'});
2902 $self->{ERRSTR} = $Imager::ERRSTR;
2906 $opts{antialias} = $opts{aa} if defined $opts{aa};
2907 if ($opts{antialias}) {
2908 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2909 $color, $opts{endp});
2911 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2912 $color, $opts{endp});
2917 # Draws a line between an ordered set of points - It more or less just transforms this
2918 # into a list of lines.
2922 my ($pt,$ls,@points);
2923 my $dflcl=i_color_new(0,0,0,0);
2924 my %opts=(color=>$dflcl,@_);
2926 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2928 if (exists($opts{points})) { @points=@{$opts{points}}; }
2929 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2930 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2933 # print Dumper(\@points);
2935 my $color = _color($opts{'color'});
2937 $self->{ERRSTR} = $Imager::ERRSTR;
2940 $opts{antialias} = $opts{aa} if defined $opts{aa};
2941 if ($opts{antialias}) {
2944 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2951 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2961 my ($pt,$ls,@points);
2962 my $dflcl = i_color_new(0,0,0,0);
2963 my %opts = (color=>$dflcl, @_);
2965 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2967 if (exists($opts{points})) {
2968 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2969 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2972 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2973 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2976 if ($opts{'fill'}) {
2977 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2978 # assume it's a hash ref
2979 require 'Imager/Fill.pm';
2980 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2981 $self->{ERRSTR} = $Imager::ERRSTR;
2985 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2986 $opts{'fill'}{'fill'});
2989 my $color = _color($opts{'color'});
2991 $self->{ERRSTR} = $Imager::ERRSTR;
2994 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3001 # this the multipoint bezier curve
3002 # this is here more for testing that actual usage since
3003 # this is not a good algorithm. Usually the curve would be
3004 # broken into smaller segments and each done individually.
3008 my ($pt,$ls,@points);
3009 my $dflcl=i_color_new(0,0,0,0);
3010 my %opts=(color=>$dflcl,@_);
3012 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3014 if (exists $opts{points}) {
3015 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3016 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3019 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3020 $self->{ERRSTR}='Missing or invalid points.';
3024 my $color = _color($opts{'color'});
3026 $self->{ERRSTR} = $Imager::ERRSTR;
3029 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3035 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3038 unless (exists $opts{'x'} && exists $opts{'y'}) {
3039 $self->{ERRSTR} = "missing seed x and y parameters";
3043 if ($opts{border}) {
3044 my $border = _color($opts{border});
3046 $self->_set_error($Imager::ERRSTR);
3050 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3051 # assume it's a hash ref
3052 require Imager::Fill;
3053 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3054 $self->{ERRSTR} = $Imager::ERRSTR;
3058 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3059 $opts{fill}{fill}, $border);
3062 my $color = _color($opts{'color'});
3064 $self->{ERRSTR} = $Imager::ERRSTR;
3067 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3074 $self->{ERRSTR} = $self->_error_as_msg();
3080 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3081 # assume it's a hash ref
3082 require 'Imager/Fill.pm';
3083 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3084 $self->{ERRSTR} = $Imager::ERRSTR;
3088 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3091 my $color = _color($opts{'color'});
3093 $self->{ERRSTR} = $Imager::ERRSTR;
3096 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3102 $self->{ERRSTR} = $self->_error_as_msg();
3109 my ($self, %opts) = @_;
3111 $self->_valid_image("setpixel")
3114 my $color = $opts{color};
3115 unless (defined $color) {
3116 $color = $self->{fg};
3117 defined $color or $color = NC(255, 255, 255);
3120 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3121 unless ($color = _color($color, 'setpixel')) {
3122 $self->_set_error("setpixel: " . Imager->errstr);
3127 unless (exists $opts{'x'} && exists $opts{'y'}) {
3128 $self->_set_error('setpixel: missing x or y parameter');
3134 if (ref $x || ref $y) {
3135 $x = ref $x ? $x : [ $x ];
3136 $y = ref $y ? $y : [ $y ];
3138 $self->_set_error("setpixel: x is a reference to an empty array");
3142 $self->_set_error("setpixel: y is a reference to an empty array");
3146 # make both the same length, replicating the last element
3148 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3151 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3155 if ($color->isa('Imager::Color')) {
3156 for my $i (0..$#$x) {
3157 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3162 for my $i (0..$#$x) {
3163 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3171 if ($color->isa('Imager::Color')) {
3172 i_ppix($self->{IMG}, $x, $y, $color)
3176 i_ppixf($self->{IMG}, $x, $y, $color)
3187 my %opts = ( "type"=>'8bit', @_);
3189 $self->_valid_image("getpixel")
3192 unless (exists $opts{'x'} && exists $opts{'y'}) {
3193 $self->_set_error('getpixel: missing x or y parameter');
3199 my $type = $opts{'type'};
3200 if (ref $x || ref $y) {
3201 $x = ref $x ? $x : [ $x ];
3202 $y = ref $y ? $y : [ $y ];
3204 $self->_set_error("getpixel: x is a reference to an empty array");
3208 $self->_set_error("getpixel: y is a reference to an empty array");
3212 # make both the same length, replicating the last element
3214 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3217 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3221 if ($type eq '8bit') {
3222 for my $i (0..$#$x) {
3223 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3226 elsif ($type eq 'float' || $type eq 'double') {
3227 for my $i (0..$#$x) {
3228 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3232 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3235 return wantarray ? @result : \@result;
3238 if ($type eq '8bit') {
3239 return i_get_pixel($self->{IMG}, $x, $y);
3241 elsif ($type eq 'float' || $type eq 'double') {
3242 return i_gpixf($self->{IMG}, $x, $y);
3245 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3253 my %opts = ( type => '8bit', x=>0, @_);
3255 $self->_valid_image or return;
3257 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3259 unless (defined $opts{'y'}) {
3260 $self->_set_error("missing y parameter");
3264 if ($opts{type} eq '8bit') {
3265 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3268 elsif ($opts{type} eq 'float') {
3269 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3272 elsif ($opts{type} eq 'index') {
3273 unless (i_img_type($self->{IMG})) {
3274 $self->_set_error("type => index only valid on paletted images");
3277 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3281 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3288 my %opts = ( x=>0, @_);
3290 $self->_valid_image or return;
3292 unless (defined $opts{'y'}) {
3293 $self->_set_error("missing y parameter");
3298 if (ref $opts{pixels} && @{$opts{pixels}}) {
3299 # try to guess the type
3300 if ($opts{pixels}[0]->isa('Imager::Color')) {
3301 $opts{type} = '8bit';
3303 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3304 $opts{type} = 'float';
3307 $self->_set_error("missing type parameter and could not guess from pixels");
3313 $opts{type} = '8bit';
3317 if ($opts{type} eq '8bit') {
3318 if (ref $opts{pixels}) {
3319 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3322 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3325 elsif ($opts{type} eq 'float') {
3326 if (ref $opts{pixels}) {
3327 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3330 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3333 elsif ($opts{type} eq 'index') {
3334 if (ref $opts{pixels}) {
3335 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3338 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3342 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3349 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3351 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3353 unless (defined $opts{'y'}) {
3354 $self->_set_error("missing y parameter");
3358 if ($opts{target}) {
3359 my $target = $opts{target};
3360 my $offset = $opts{offset};
3361 if ($opts{type} eq '8bit') {
3362 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3363 $opts{y}, $opts{channels})
3365 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3366 return scalar(@samples);
3368 elsif ($opts{type} eq 'float') {
3369 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3370 $opts{y}, $opts{channels});
3371 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3372 return scalar(@samples);
3374 elsif ($opts{type} =~ /^(\d+)bit$/) {
3378 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3379 $opts{y}, $bits, $target,
3380 $offset, $opts{channels});
3381 unless (defined $count) {
3382 $self->_set_error(Imager->_error_as_msg);
3389 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3394 if ($opts{type} eq '8bit') {
3395 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3396 $opts{y}, $opts{channels});
3398 elsif ($opts{type} eq 'float') {
3399 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3400 $opts{y}, $opts{channels});
3402 elsif ($opts{type} =~ /^(\d+)bit$/) {
3406 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3407 $opts{y}, $bits, \@data, 0, $opts{channels})
3412 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3421 unless ($self->{IMG}) {
3422 $self->_set_error('setsamples: empty input image');
3426 my %opts = ( x => 0, offset => 0 );
3428 # avoid duplicating the data parameter, it may be a large scalar
3430 while ($i < @_ -1) {
3431 if ($_[$i] eq 'data') {
3435 $opts{$_[$i]} = $_[$i+1];
3441 unless(defined $data_index) {
3442 $self->_set_error('setsamples: data parameter missing');
3445 unless (defined $_[$data_index]) {
3446 $self->_set_error('setsamples: data parameter not defined');
3450 my $type = $opts{type};
3451 defined $type or $type = '8bit';
3453 my $width = defined $opts{width} ? $opts{width}
3454 : $self->getwidth() - $opts{x};
3457 if ($type eq '8bit') {
3458 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3459 $_[$data_index], $opts{offset}, $width);
3461 elsif ($type eq 'float') {
3462 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3463 $_[$data_index], $opts{offset}, $width);
3465 elsif ($type =~ /^([0-9]+)bit$/) {
3468 unless (ref $_[$data_index]) {
3469 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3473 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3474 $opts{channels}, $_[$data_index], $opts{offset},
3478 $self->_set_error('setsamples: type parameter invalid');
3482 unless (defined $count) {
3483 $self->_set_error(Imager->_error_as_msg);
3490 # make an identity matrix of the given size
3494 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3495 for my $c (0 .. ($size-1)) {
3496 $matrix->[$c][$c] = 1;
3501 # general function to convert an image
3503 my ($self, %opts) = @_;
3506 unless (defined wantarray) {
3507 my @caller = caller;
3508 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3512 # the user can either specify a matrix or preset
3513 # the matrix overrides the preset
3514 if (!exists($opts{matrix})) {
3515 unless (exists($opts{preset})) {
3516 $self->{ERRSTR} = "convert() needs a matrix or preset";
3520 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3521 # convert to greyscale, keeping the alpha channel if any
3522 if ($self->getchannels == 3) {
3523 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3525 elsif ($self->getchannels == 4) {
3526 # preserve the alpha channel
3527 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3532 $matrix = _identity($self->getchannels);
3535 elsif ($opts{preset} eq 'noalpha') {
3536 # strip the alpha channel
3537 if ($self->getchannels == 2 or $self->getchannels == 4) {
3538 $matrix = _identity($self->getchannels);
3539 pop(@$matrix); # lose the alpha entry
3542 $matrix = _identity($self->getchannels);
3545 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3547 $matrix = [ [ 1 ] ];
3549 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3550 $matrix = [ [ 0, 1 ] ];
3552 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3553 $matrix = [ [ 0, 0, 1 ] ];
3555 elsif ($opts{preset} eq 'alpha') {
3556 if ($self->getchannels == 2 or $self->getchannels == 4) {
3557 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3560 # the alpha is just 1 <shrug>
3561 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3564 elsif ($opts{preset} eq 'rgb') {
3565 if ($self->getchannels == 1) {
3566 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3568 elsif ($self->getchannels == 2) {
3569 # preserve the alpha channel
3570 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3573 $matrix = _identity($self->getchannels);
3576 elsif ($opts{preset} eq 'addalpha') {
3577 if ($self->getchannels == 1) {
3578 $matrix = _identity(2);
3580 elsif ($self->getchannels == 3) {
3581 $matrix = _identity(4);
3584 $matrix = _identity($self->getchannels);
3588 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3594 $matrix = $opts{matrix};
3597 my $new = Imager->new;
3598 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3599 unless ($new->{IMG}) {
3600 # most likely a bad matrix
3601 i_push_error(0, "convert");
3602 $self->{ERRSTR} = _error_as_msg();
3608 # combine channels from multiple input images, a class method
3610 my ($class, %opts) = @_;
3612 my $src = delete $opts{src};
3614 $class->_set_error("src parameter missing");
3619 for my $img (@$src) {
3620 unless (eval { $img->isa("Imager") }) {
3621 $class->_set_error("src must contain image objects");
3624 unless ($img->{IMG}) {
3625 $class->_set_error("empty input image");
3628 push @imgs, $img->{IMG};
3631 if (my $channels = delete $opts{channels}) {
3632 $result = i_combine(\@imgs, $channels);
3635 $result = i_combine(\@imgs);
3638 $class->_set_error($class->_error_as_msg);
3642 my $img = $class->new;
3643 $img->{IMG} = $result;
3649 # general function to map an image through lookup tables
3652 my ($self, %opts) = @_;
3653 my @chlist = qw( red green blue alpha );
3655 if (!exists($opts{'maps'})) {
3656 # make maps from channel maps
3658 for $chnum (0..$#chlist) {
3659 if (exists $opts{$chlist[$chnum]}) {
3660 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3661 } elsif (exists $opts{'all'}) {
3662 $opts{'maps'}[$chnum] = $opts{'all'};
3666 if ($opts{'maps'} and $self->{IMG}) {
3667 i_map($self->{IMG}, $opts{'maps'} );
3673 my ($self, %opts) = @_;
3675 defined $opts{mindist} or $opts{mindist} = 0;
3677 defined $opts{other}
3678 or return $self->_set_error("No 'other' parameter supplied");
3679 defined $opts{other}{IMG}
3680 or return $self->_set_error("No image data in 'other' image");
3683 or return $self->_set_error("No image data");
3685 my $result = Imager->new;
3686 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3688 or return $self->_set_error($self->_error_as_msg());
3693 # destructive border - image is shrunk by one pixel all around
3696 my ($self,%opts)=@_;
3697 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3698 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3702 # Get the width of an image
3707 if (my $raw = $self->{IMG}) {
3708 return i_img_get_width($raw);
3711 $self->{ERRSTR} = 'image is empty'; return undef;
3715 # Get the height of an image
3720 if (my $raw = $self->{IMG}) {
3721 return i_img_get_height($raw);
3724 $self->{ERRSTR} = 'image is empty'; return undef;
3728 # Get number of channels in an image
3732 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3733 return i_img_getchannels($self->{IMG});
3740 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3741 return i_img_getmask($self->{IMG});
3749 if (!defined($self->{IMG})) {
3750 $self->{ERRSTR} = 'image is empty';
3753 unless (defined $opts{mask}) {
3754 $self->_set_error("mask parameter required");
3757 i_img_setmask( $self->{IMG} , $opts{mask} );
3762 # Get number of colors in an image
3766 my %opts=('maxcolors'=>2**30,@_);
3767 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3768 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3769 return ($rc==-1? undef : $rc);
3772 # Returns a reference to a hash. The keys are colour named (packed) and the
3773 # values are the number of pixels in this colour.
3774 sub getcolorusagehash {
3777 my %opts = ( maxcolors => 2**30, @_ );
3778 my $max_colors = $opts{maxcolors};
3779 unless (defined $max_colors && $max_colors > 0) {
3780 $self->_set_error('maxcolors must be a positive integer');
3784 unless (defined $self->{IMG}) {
3785 $self->_set_error('empty input image');
3789 my $channels= $self->getchannels;
3790 # We don't want to look at the alpha channel, because some gifs using it
3791 # doesn't define it for every colour (but only for some)
3792 $channels -= 1 if $channels == 2 or $channels == 4;
3794 my $height = $self->getheight;
3795 for my $y (0 .. $height - 1) {
3796 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3797 while (length $colors) {
3798 $color_use{ substr($colors, 0, $channels, '') }++;
3800 keys %color_use > $max_colors
3806 # This will return a ordered array of the colour usage. Kind of the sorted
3807 # version of the values of the hash returned by getcolorusagehash.
3808 # You might want to add safety checks and change the names, etc...
3812 my %opts = ( maxcolors => 2**30, @_ );
3813 my $max_colors = $opts{maxcolors};
3814 unless (defined $max_colors && $max_colors > 0) {
3815 $self->_set_error('maxcolors must be a positive integer');
3819 unless (defined $self->{IMG}) {
3820 $self->_set_error('empty input image');
3824 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3827 # draw string to an image
3831 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3833 my %input=('x'=>0, 'y'=>0, @_);
3834 defined($input{string}) or $input{string} = $input{text};
3836 unless(defined $input{string}) {
3837 $self->{ERRSTR}="missing required parameter 'string'";
3841 unless($input{font}) {
3842 $self->{ERRSTR}="missing required parameter 'font'";
3846 unless ($input{font}->draw(image=>$self, %input)) {
3858 unless ($self->{IMG}) {
3859 $self->{ERRSTR}='empty input image';
3868 my %input=('x'=>0, 'y'=>0, @_);
3869 defined $input{string}
3870 or $input{string} = $input{text};
3872 unless(exists $input{string}) {
3873 $self->_set_error("missing required parameter 'string'");
3877 unless($input{font}) {
3878 $self->_set_error("missing required parameter 'font'");
3883 unless (@result = $input{font}->align(image=>$img, %input)) {
3887 return wantarray ? @result : $result[0];
3890 my @file_limit_names = qw/width height bytes/;
3892 sub set_file_limits {
3899 @values{@file_limit_names} = (0) x @file_limit_names;
3902 @values{@file_limit_names} = i_get_image_file_limits();
3905 for my $key (keys %values) {
3906 defined $opts{$key} and $values{$key} = $opts{$key};
3909 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3912 sub get_file_limits {
3913 i_get_image_file_limits();
3916 my @check_args = qw(width height channels sample_size);
3918 sub check_file_limits {
3928 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
3929 $opts{sample_size} = length(pack("d", 0));
3932 for my $name (@check_args) {
3933 unless (defined $opts{$name}) {
3934 $class->_set_error("check_file_limits: $name must be defined");
3937 unless ($opts{$name} == int($opts{$name})) {
3938 $class->_set_error("check_file_limits: $name must be a positive integer");
3943 my $result = i_int_check_image_file_limits(@opts{@check_args});
3945 $class->_set_error($class->_error_as_msg());
3951 # Shortcuts that can be exported
3953 sub newcolor { Imager::Color->new(@_); }
3954 sub newfont { Imager::Font->new(@_); }
3956 require Imager::Color::Float;
3957 return Imager::Color::Float->new(@_);
3960 *NC=*newcolour=*newcolor;
3967 #### Utility routines
3970 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3974 my ($self, $msg) = @_;
3977 $self->{ERRSTR} = $msg;
3985 # Default guess for the type of an image from extension
3987 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
3991 ( map { $_ => $_ } @simple_types ),
3997 pnm => "pnm", # technically wrong, but historically it works in Imager
4010 sub def_guess_type {
4013 my ($ext) = $name =~ /\.([^.]+)$/
4016 my $type = $ext_types{$ext}
4023 return @combine_types;
4026 # get the minimum of a list
4030 for(@_) { if ($_<$mx) { $mx=$_; }}
4034 # get the maximum of a list
4038 for(@_) { if ($_>$mx) { $mx=$_; }}
4042 # string stuff for iptc headers
4046 $str = substr($str,3);
4047 $str =~ s/[\n\r]//g;
4054 # A little hack to parse iptc headers.
4059 my($caption,$photogr,$headln,$credit);
4061 my $str=$self->{IPTCRAW};
4066 @ar=split(/8BIM/,$str);
4071 @sar=split(/\034\002/);
4072 foreach $item (@sar) {
4073 if ($item =~ m/^x/) {
4074 $caption = _clean($item);
4077 if ($item =~ m/^P/) {
4078 $photogr = _clean($item);
4081 if ($item =~ m/^i/) {
4082 $headln = _clean($item);
4085 if ($item =~ m/^n/) {
4086 $credit = _clean($item);
4092 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4099 or die "Only C language supported";
4101 require Imager::ExtUtils;
4102 return Imager::ExtUtils->inline_config;
4105 # threads shouldn't try to close raw Imager objects
4106 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4109 # this serves two purposes:
4110 # - a class method to load the file support modules included with Imager
4111 # (or were included, once the library dependent modules are split out)
4112 # - something for Module::ScanDeps to analyze
4113 # https://rt.cpan.org/Ticket/Display.html?id=6566
4115 eval { require Imager::File::GIF };
4116 eval { require Imager::File::JPEG };
4117 eval { require Imager::File::PNG };
4118 eval { require Imager::File::SGI };
4119 eval { require Imager::File::TIFF };
4120 eval { require Imager::File::ICO };
4121 eval { require Imager::Font::W32 };
4122 eval { require Imager::Font::FT2 };
4123 eval { require Imager::Font::T1 };
4126 # backward compatibility for %formats
4127 package Imager::FORMATS;
4129 use constant IX_FORMATS => 0;
4130 use constant IX_LIST => 1;
4131 use constant IX_INDEX => 2;
4132 use constant IX_CLASSES => 3;
4135 my ($class, $formats, $classes) = @_;
4137 return bless [ $formats, [ ], 0, $classes ], $class;
4141 my ($self, $key) = @_;
4143 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4146 my $loaded = Imager::_load_file($file, \$error);
4151 if ($error =~ /^Can't locate /) {
4152 $error = "Can't locate $file";
4154 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4157 $self->[IX_FORMATS]{$key} = $value;
4163 my ($self, $key) = @_;
4165 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4167 $self->[IX_CLASSES]{$key} or return undef;
4169 return $self->_check($key);
4173 die "%Imager::formats is not user monifiable";
4177 die "%Imager::formats is not user monifiable";
4181 die "%Imager::formats is not user monifiable";
4185 my ($self, $key) = @_;
4187 if (exists $self->[IX_FORMATS]{$key}) {
4188 my $value = $self->[IX_FORMATS]{$key}
4193 $self->_check($key) or return 1==0;
4201 unless (@{$self->[IX_LIST]}) {
4203 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4204 keys %{$self->[IX_FORMATS]};
4206 for my $key (keys %{$self->[IX_CLASSES]}) {
4207 $self->[IX_FORMATS]{$key} and next;
4209 and push @{$self->[IX_LIST]}, $key;
4213 @{$self->[IX_LIST]} or return;
4214 $self->[IX_INDEX] = 1;
4215 return $self->[IX_LIST][0];
4221 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4224 return $self->[IX_LIST][$self->[IX_INDEX]++];
4230 return scalar @{$self->[IX_LIST]};
4235 # Below is the stub of documentation for your module. You better edit it!
4239 Imager - Perl extension for Generating 24 bit Images
4249 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4254 # see Imager::Files for information on the read() method
4255 my $img = Imager->new(file=>$file)
4256 or die Imager->errstr();
4258 $file =~ s/\.[^.]*$//;
4260 # Create smaller version
4261 # documented in Imager::Transformations
4262 my $thumb = $img->scale(scalefactor=>.3);
4264 # Autostretch individual channels
4265 $thumb->filter(type=>'autolevels');
4267 # try to save in one of these formats
4270 for $format ( qw( png gif jpeg tiff ppm ) ) {
4271 # Check if given format is supported
4272 if ($Imager::formats{$format}) {
4273 $file.="_low.$format";
4274 print "Storing image as: $file\n";
4275 # documented in Imager::Files
4276 $thumb->write(file=>$file) or
4284 Imager is a module for creating and altering images. It can read and
4285 write various image formats, draw primitive shapes like lines,and
4286 polygons, blend multiple images together in various ways, scale, crop,
4287 render text and more.
4289 =head2 Overview of documentation
4295 Imager - This document - Synopsis, Example, Table of Contents and
4300 L<Imager::Tutorial> - a brief introduction to Imager.
4304 L<Imager::Cookbook> - how to do various things with Imager.
4308 L<Imager::ImageTypes> - Basics of constructing image objects with
4309 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4310 8/16/double bits/channel, color maps, channel masks, image tags, color
4311 quantization. Also discusses basic image information methods.
4315 L<Imager::Files> - IO interaction, reading/writing images, format
4320 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4325 L<Imager::Color> - Color specification.
4329 L<Imager::Fill> - Fill pattern specification.
4333 L<Imager::Font> - General font rendering, bounding boxes and font
4338 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4339 blending, pasting, convert and map.
4343 L<Imager::Engines> - Programmable transformations through
4344 C<transform()>, C<transform2()> and C<matrix_transform()>.
4348 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4353 L<Imager::Expr> - Expressions for evaluation engine used by
4358 L<Imager::Matrix2d> - Helper class for affine transformations.
4362 L<Imager::Fountain> - Helper for making gradient profiles.
4366 L<Imager::API> - using Imager's C API
4370 L<Imager::APIRef> - API function reference
4374 L<Imager::Inline> - using Imager's C API from Inline::C
4378 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4382 L<Imager::Security> - brief security notes.
4386 L<Imager::Threads> - brief information on working with threads.
4390 =head2 Basic Overview
4392 An Image object is created with C<$img = Imager-E<gt>new()>.
4395 $img=Imager->new(); # create empty image
4396 $img->read(file=>'lena.png',type=>'png') or # read image from file
4397 die $img->errstr(); # give an explanation
4398 # if something failed
4400 or if you want to create an empty image:
4402 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4404 This example creates a completely black image of width 400 and height
4407 =head1 ERROR HANDLING
4409 In general a method will return false when it fails, if it does use
4410 the C<errstr()> method to find out why:
4416 Returns the last error message in that context.
4418 If the last error you received was from calling an object method, such
4419 as read, call errstr() as an object method to find out why:
4421 my $image = Imager->new;
4422 $image->read(file => 'somefile.gif')
4423 or die $image->errstr;
4425 If it was a class method then call errstr() as a class method:
4427 my @imgs = Imager->read_multi(file => 'somefile.gif')
4428 or die Imager->errstr;
4430 Note that in some cases object methods are implemented in terms of
4431 class methods so a failing object method may set both.
4435 The C<Imager-E<gt>new> method is described in detail in
4436 L<Imager::ImageTypes>.
4440 Where to find information on methods for Imager class objects.
4442 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4445 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4447 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4450 arc() - L<Imager::Draw/arc()> - draw a filled arc
4452 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4455 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4457 check_file_limits() - L<Imager::Files/check_file_limits()>
4459 circle() - L<Imager::Draw/circle()> - draw a filled circle
4461 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4464 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4465 colors in an image's palette (paletted images only)
4467 combine() - L<Imager::Transformations/combine()> - combine channels
4468 from one or more images.
4470 combines() - L<Imager::Draw/combines()> - return a list of the
4471 different combine type keywords
4473 compose() - L<Imager::Transformations/compose()> - compose one image
4476 convert() - L<Imager::Transformations/convert()> - transform the color
4479 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4482 crop() - L<Imager::Transformations/crop()> - extract part of an image
4484 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4485 used to guess the output file format based on the output file name
4487 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4489 difference() - L<Imager::Filters/difference()> - produce a difference
4490 images from two input images.
4492 errstr() - L</errstr()> - the error from the last failed operation.
4494 filter() - L<Imager::Filters/filter()> - image filtering
4496 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4497 palette, if it has one
4499 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4502 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4505 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4506 samples per pixel for an image
4508 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4509 different colors used by an image (works for direct color images)
4511 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4512 palette, if it has one
4514 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4516 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4518 get_file_limits() - L<Imager::Files/get_file_limits()>
4520 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4523 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4525 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4528 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4529 row or partial row of pixels.
4531 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4532 row or partial row of pixels.
4534 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4537 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4540 init() - L<Imager::ImageTypes/init()>
4542 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4543 image write functions should write the image in their bilevel (blank
4544 and white, no gray levels) format
4546 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4549 line() - L<Imager::Draw/line()> - draw an interval
4551 load_plugin() - L<Imager::Filters/load_plugin()>
4553 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4556 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4557 color palette from one or more input images.
4559 map() - L<Imager::Transformations/map()> - remap color
4562 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4564 matrix_transform() - L<Imager::Engines/matrix_transform()>
4566 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4568 NC() - L<Imager::Handy/NC()>
4570 NCF() - L<Imager::Handy/NCF()>
4572 new() - L<Imager::ImageTypes/new()>
4574 newcolor() - L<Imager::Handy/newcolor()>
4576 newcolour() - L<Imager::Handy/newcolour()>
4578 newfont() - L<Imager::Handy/newfont()>
4580 NF() - L<Imager::Handy/NF()>
4582 open() - L<Imager::Files/read()> - an alias for read()
4584 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4588 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4591 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4594 polygon() - L<Imager::Draw/polygon()>
4596 polyline() - L<Imager::Draw/polyline()>
4598 preload() - L<Imager::Files/preload()>
4600 read() - L<Imager::Files/read()> - read a single image from an image file
4602 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4605 read_types() - L<Imager::Files/read_types()> - list image types Imager
4608 register_filter() - L<Imager::Filters/register_filter()>
4610 register_reader() - L<Imager::Files/register_reader()>
4612 register_writer() - L<Imager::Files/register_writer()>
4614 rotate() - L<Imager::Transformations/rotate()>
4616 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4617 onto an image and use the alpha channel
4619 scale() - L<Imager::Transformations/scale()>
4621 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4623 scaleX() - L<Imager::Transformations/scaleX()>
4625 scaleY() - L<Imager::Transformations/scaleY()>
4627 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4630 set_file_limits() - L<Imager::Files/set_file_limits()>
4632 setmask() - L<Imager::ImageTypes/setmask()>
4634 setpixel() - L<Imager::Draw/setpixel()>
4636 setsamples() - L<Imager::Draw/setsamples()>
4638 setscanline() - L<Imager::Draw/setscanline()>
4640 settag() - L<Imager::ImageTypes/settag()>
4642 string() - L<Imager::Draw/string()> - draw text on an image
4644 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4646 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4648 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4650 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4652 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4653 double per sample image.
4655 transform() - L<Imager::Engines/"transform()">
4657 transform2() - L<Imager::Engines/"transform2()">
4659 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4661 unload_plugin() - L<Imager::Filters/unload_plugin()>
4663 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4666 write() - L<Imager::Files/write()> - write an image to a file
4668 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4671 write_types() - L<Imager::Files/read_types()> - list image types Imager
4674 =head1 CONCEPT INDEX
4676 animated GIF - L<Imager::Files/"Writing an animated GIF">
4678 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4679 L<Imager::ImageTypes/"Common Tags">.
4681 blend - alpha blending one image onto another
4682 L<Imager::Transformations/rubthrough()>
4684 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4686 boxes, drawing - L<Imager::Draw/box()>
4688 changes between image - L<Imager::Filters/"Image Difference">
4690 channels, combine into one image - L<Imager::Transformations/combine()>
4692 color - L<Imager::Color>
4694 color names - L<Imager::Color>, L<Imager::Color::Table>
4696 combine modes - L<Imager::Draw/"Combine Types">
4698 compare images - L<Imager::Filters/"Image Difference">
4700 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4702 convolution - L<Imager::Filters/conv>
4704 cropping - L<Imager::Transformations/crop()>
4706 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4708 C<diff> images - L<Imager::Filters/"Image Difference">
4710 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4711 L<Imager::Cookbook/"Image spatial resolution">
4713 drawing boxes - L<Imager::Draw/box()>
4715 drawing lines - L<Imager::Draw/line()>
4717 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4719 error message - L</"ERROR HANDLING">
4721 files, font - L<Imager::Font>
4723 files, image - L<Imager::Files>
4725 filling, types of fill - L<Imager::Fill>
4727 filling, boxes - L<Imager::Draw/box()>
4729 filling, flood fill - L<Imager::Draw/flood_fill()>
4731 flood fill - L<Imager::Draw/flood_fill()>
4733 fonts - L<Imager::Font>
4735 fonts, drawing with - L<Imager::Draw/string()>,
4736 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4738 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4740 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4742 fountain fill - L<Imager::Fill/"Fountain fills">,
4743 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4744 L<Imager::Filters/gradgen>
4746 GIF files - L<Imager::Files/"GIF">
4748 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4750 gradient fill - L<Imager::Fill/"Fountain fills">,
4751 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4752 L<Imager::Filters/gradgen>
4754 gray scale, convert image to - L<Imager::Transformations/convert()>
4756 gaussian blur - L<Imager::Filters/gaussian>
4758 hatch fills - L<Imager::Fill/"Hatched fills">
4760 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4762 invert image - L<Imager::Filters/hardinvert>,
4763 L<Imager::Filters/hardinvertall>
4765 JPEG - L<Imager::Files/"JPEG">
4767 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4769 lines, drawing - L<Imager::Draw/line()>
4771 matrix - L<Imager::Matrix2d>,
4772 L<Imager::Engines/"Matrix Transformations">,
4773 L<Imager::Font/transform()>
4775 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
4777 mosaic - L<Imager::Filters/mosaic>
4779 noise, filter - L<Imager::Filters/noise>
4781 noise, rendered - L<Imager::Filters/turbnoise>,
4782 L<Imager::Filters/radnoise>
4784 paste - L<Imager::Transformations/paste()>,
4785 L<Imager::Transformations/rubthrough()>
4787 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4788 L<Imager::ImageTypes/new()>
4790 =for stopwords posterize
4792 posterize - L<Imager::Filters/postlevels>
4794 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4796 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4798 rectangles, drawing - L<Imager::Draw/box()>
4800 resizing an image - L<Imager::Transformations/scale()>,
4801 L<Imager::Transformations/crop()>
4803 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4805 saving an image - L<Imager::Files>
4807 scaling - L<Imager::Transformations/scale()>
4809 security - L<Imager::Security>
4811 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4813 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4815 size, image - L<Imager::ImageTypes/getwidth()>,
4816 L<Imager::ImageTypes/getheight()>
4818 size, text - L<Imager::Font/bounding_box()>
4820 tags, image metadata - L<Imager::ImageTypes/"Tags">
4822 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4823 L<Imager::Font::Wrap>
4825 text, wrapping text in an area - L<Imager::Font::Wrap>
4827 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4829 threads - L<Imager::Threads>
4831 tiles, color - L<Imager::Filters/mosaic>
4833 transparent images - L<Imager::ImageTypes>,
4834 L<Imager::Cookbook/"Transparent PNG">
4836 =for stopwords unsharp
4838 unsharp mask - L<Imager::Filters/unsharpmask>
4840 watermark - L<Imager::Filters/watermark>
4842 writing an image to a file - L<Imager::Files>
4846 The best place to get help with Imager is the mailing list.
4848 To subscribe send a message with C<subscribe> in the body to:
4850 imager-devel+request@molar.is
4856 L<http://www.molar.is/en/lists/imager-devel/>
4860 where you can also find the mailing list archive.
4862 You can report bugs by pointing your browser at:
4866 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4870 or by sending an email to:
4874 bug-Imager@rt.cpan.org
4878 Please remember to include the versions of Imager, perl, supporting
4879 libraries, and any relevant code. If you have specific images that
4880 cause the problems, please include those too.
4882 If you don't want to publish your email address on a mailing list you
4883 can use CPAN::Forum:
4885 http://www.cpanforum.com/dist/Imager
4887 You will need to register to post.
4889 =head1 CONTRIBUTING TO IMAGER
4895 If you like or dislike Imager, you can add a public review of Imager
4898 http://cpanratings.perl.org/dist/Imager
4900 =for stopwords Bitcard
4902 This requires a Bitcard account (http://www.bitcard.org).
4904 You can also send email to the maintainer below.
4906 If you send me a bug report via email, it will be copied to Request
4911 I accept patches, preferably against the master branch in git. Please
4912 include an explanation of the reason for why the patch is needed or
4915 Your patch should include regression tests where possible, otherwise
4916 it will be delayed until I get a chance to write them.
4918 To browse Imager's git repository:
4920 http://git.imager.perl.org/imager.git
4924 https://github.com/tonycoz/imager
4928 git clone git://git.imager.perl.org/imager.git
4932 git clone git://github.com/tonycoz/imager.git
4936 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
4938 Arnar M. Hrafnkelsson is the original author of Imager.
4940 Many others have contributed to Imager, please see the C<README> for a
4945 Imager is licensed under the same terms as perl itself.
4948 makeblendedfont Fontforge
4950 A test font, generated by the Debian packaged Fontforge,
4951 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
4952 copyrighted by Adobe. See F<adobe.txt> in the source for license
4957 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4958 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4959 L<Imager::Font>(3), L<Imager::Transformations>(3),
4960 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4961 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4963 L<http://imager.perl.org/>
4965 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4967 Other perl imaging modules include:
4969 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3),
4970 L<Prima::Image>, L<IPA>.
4972 For manipulating image metadata see L<Image::ExifTool>.
4974 If you're trying to use Imager for array processing, you should
4975 probably using L<PDL>.