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'");
3420 my %opts = ( x => 0, offset => 0, @_ );
3422 unless ($self->{IMG}) {
3423 $self->_set_error('setsamples: empty input image');
3427 my $data = $opts{data};
3428 unless(defined $data) {
3429 $self->_set_error('setsamples: data parameter missing');
3433 my $type = $opts{type};
3434 defined $type or $type = '8bit';
3436 my $width = defined $opts{width} ? $opts{width}
3437 : $self->getwidth() - $opts{x};
3440 if ($type eq '8bit') {
3441 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3442 $data, $opts{offset}, $width);
3444 elsif ($type eq 'float') {
3445 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3446 $data, $opts{offset}, $width);
3448 elsif ($type =~ /^([0-9]+)bit$/) {
3451 unless (ref $data) {
3452 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3456 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3457 $opts{channels}, $data, $opts{offset},
3461 $self->_set_error('setsamples: type parameter invalid');
3465 unless (defined $count) {
3466 $self->_set_error(Imager->_error_as_msg);
3473 # make an identity matrix of the given size
3477 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3478 for my $c (0 .. ($size-1)) {
3479 $matrix->[$c][$c] = 1;
3484 # general function to convert an image
3486 my ($self, %opts) = @_;
3489 unless (defined wantarray) {
3490 my @caller = caller;
3491 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3495 # the user can either specify a matrix or preset
3496 # the matrix overrides the preset
3497 if (!exists($opts{matrix})) {
3498 unless (exists($opts{preset})) {
3499 $self->{ERRSTR} = "convert() needs a matrix or preset";
3503 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3504 # convert to greyscale, keeping the alpha channel if any
3505 if ($self->getchannels == 3) {
3506 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3508 elsif ($self->getchannels == 4) {
3509 # preserve the alpha channel
3510 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3515 $matrix = _identity($self->getchannels);
3518 elsif ($opts{preset} eq 'noalpha') {
3519 # strip the alpha channel
3520 if ($self->getchannels == 2 or $self->getchannels == 4) {
3521 $matrix = _identity($self->getchannels);
3522 pop(@$matrix); # lose the alpha entry
3525 $matrix = _identity($self->getchannels);
3528 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3530 $matrix = [ [ 1 ] ];
3532 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3533 $matrix = [ [ 0, 1 ] ];
3535 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3536 $matrix = [ [ 0, 0, 1 ] ];
3538 elsif ($opts{preset} eq 'alpha') {
3539 if ($self->getchannels == 2 or $self->getchannels == 4) {
3540 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3543 # the alpha is just 1 <shrug>
3544 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3547 elsif ($opts{preset} eq 'rgb') {
3548 if ($self->getchannels == 1) {
3549 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3551 elsif ($self->getchannels == 2) {
3552 # preserve the alpha channel
3553 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3556 $matrix = _identity($self->getchannels);
3559 elsif ($opts{preset} eq 'addalpha') {
3560 if ($self->getchannels == 1) {
3561 $matrix = _identity(2);
3563 elsif ($self->getchannels == 3) {
3564 $matrix = _identity(4);
3567 $matrix = _identity($self->getchannels);
3571 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3577 $matrix = $opts{matrix};
3580 my $new = Imager->new;
3581 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3582 unless ($new->{IMG}) {
3583 # most likely a bad matrix
3584 $self->{ERRSTR} = _error_as_msg();
3590 # combine channels from multiple input images, a class method
3592 my ($class, %opts) = @_;
3594 my $src = delete $opts{src};
3596 $class->_set_error("src parameter missing");
3601 for my $img (@$src) {
3602 unless (eval { $img->isa("Imager") }) {
3603 $class->_set_error("src must contain image objects");
3606 unless ($img->{IMG}) {
3607 $class->_set_error("empty input image");
3610 push @imgs, $img->{IMG};
3613 if (my $channels = delete $opts{channels}) {
3614 $result = i_combine(\@imgs, $channels);
3617 $result = i_combine(\@imgs);
3620 $class->_set_error($class->_error_as_msg);
3624 my $img = $class->new;
3625 $img->{IMG} = $result;
3631 # general function to map an image through lookup tables
3634 my ($self, %opts) = @_;
3635 my @chlist = qw( red green blue alpha );
3637 if (!exists($opts{'maps'})) {
3638 # make maps from channel maps
3640 for $chnum (0..$#chlist) {
3641 if (exists $opts{$chlist[$chnum]}) {
3642 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3643 } elsif (exists $opts{'all'}) {
3644 $opts{'maps'}[$chnum] = $opts{'all'};
3648 if ($opts{'maps'} and $self->{IMG}) {
3649 i_map($self->{IMG}, $opts{'maps'} );
3655 my ($self, %opts) = @_;
3657 defined $opts{mindist} or $opts{mindist} = 0;
3659 defined $opts{other}
3660 or return $self->_set_error("No 'other' parameter supplied");
3661 defined $opts{other}{IMG}
3662 or return $self->_set_error("No image data in 'other' image");
3665 or return $self->_set_error("No image data");
3667 my $result = Imager->new;
3668 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3670 or return $self->_set_error($self->_error_as_msg());
3675 # destructive border - image is shrunk by one pixel all around
3678 my ($self,%opts)=@_;
3679 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3680 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3684 # Get the width of an image
3689 if (my $raw = $self->{IMG}) {
3690 return i_img_get_width($raw);
3693 $self->{ERRSTR} = 'image is empty'; return undef;
3697 # Get the height of an image
3702 if (my $raw = $self->{IMG}) {
3703 return i_img_get_height($raw);
3706 $self->{ERRSTR} = 'image is empty'; return undef;
3710 # Get number of channels in an image
3714 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3715 return i_img_getchannels($self->{IMG});
3722 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3723 return i_img_getmask($self->{IMG});
3731 if (!defined($self->{IMG})) {
3732 $self->{ERRSTR} = 'image is empty';
3735 unless (defined $opts{mask}) {
3736 $self->_set_error("mask parameter required");
3739 i_img_setmask( $self->{IMG} , $opts{mask} );
3744 # Get number of colors in an image
3748 my %opts=('maxcolors'=>2**30,@_);
3749 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3750 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3751 return ($rc==-1? undef : $rc);
3754 # Returns a reference to a hash. The keys are colour named (packed) and the
3755 # values are the number of pixels in this colour.
3756 sub getcolorusagehash {
3759 my %opts = ( maxcolors => 2**30, @_ );
3760 my $max_colors = $opts{maxcolors};
3761 unless (defined $max_colors && $max_colors > 0) {
3762 $self->_set_error('maxcolors must be a positive integer');
3766 unless (defined $self->{IMG}) {
3767 $self->_set_error('empty input image');
3771 my $channels= $self->getchannels;
3772 # We don't want to look at the alpha channel, because some gifs using it
3773 # doesn't define it for every colour (but only for some)
3774 $channels -= 1 if $channels == 2 or $channels == 4;
3776 my $height = $self->getheight;
3777 for my $y (0 .. $height - 1) {
3778 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3779 while (length $colors) {
3780 $color_use{ substr($colors, 0, $channels, '') }++;
3782 keys %color_use > $max_colors
3788 # This will return a ordered array of the colour usage. Kind of the sorted
3789 # version of the values of the hash returned by getcolorusagehash.
3790 # You might want to add safety checks and change the names, etc...
3794 my %opts = ( maxcolors => 2**30, @_ );
3795 my $max_colors = $opts{maxcolors};
3796 unless (defined $max_colors && $max_colors > 0) {
3797 $self->_set_error('maxcolors must be a positive integer');
3801 unless (defined $self->{IMG}) {
3802 $self->_set_error('empty input image');
3806 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3809 # draw string to an image
3813 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3815 my %input=('x'=>0, 'y'=>0, @_);
3816 defined($input{string}) or $input{string} = $input{text};
3818 unless(defined $input{string}) {
3819 $self->{ERRSTR}="missing required parameter 'string'";
3823 unless($input{font}) {
3824 $self->{ERRSTR}="missing required parameter 'font'";
3828 unless ($input{font}->draw(image=>$self, %input)) {
3840 unless ($self->{IMG}) {
3841 $self->{ERRSTR}='empty input image';
3850 my %input=('x'=>0, 'y'=>0, @_);
3851 defined $input{string}
3852 or $input{string} = $input{text};
3854 unless(exists $input{string}) {
3855 $self->_set_error("missing required parameter 'string'");
3859 unless($input{font}) {
3860 $self->_set_error("missing required parameter 'font'");
3865 unless (@result = $input{font}->align(image=>$img, %input)) {
3869 return wantarray ? @result : $result[0];
3872 my @file_limit_names = qw/width height bytes/;
3874 sub set_file_limits {
3881 @values{@file_limit_names} = (0) x @file_limit_names;
3884 @values{@file_limit_names} = i_get_image_file_limits();
3887 for my $key (keys %values) {
3888 defined $opts{$key} and $values{$key} = $opts{$key};
3891 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3894 sub get_file_limits {
3895 i_get_image_file_limits();
3898 my @check_args = qw(width height channels sample_size);
3900 sub check_file_limits {
3910 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
3911 $opts{sample_size} = length(pack("d", 0));
3914 for my $name (@check_args) {
3915 unless (defined $opts{$name}) {
3916 $class->_set_error("check_file_limits: $name must be defined");
3919 unless ($opts{$name} == int($opts{$name})) {
3920 $class->_set_error("check_file_limits: $name must be a positive integer");
3925 my $result = i_int_check_image_file_limits(@opts{@check_args});
3927 $class->_set_error($class->_error_as_msg());
3933 # Shortcuts that can be exported
3935 sub newcolor { Imager::Color->new(@_); }
3936 sub newfont { Imager::Font->new(@_); }
3938 require Imager::Color::Float;
3939 return Imager::Color::Float->new(@_);
3942 *NC=*newcolour=*newcolor;
3949 #### Utility routines
3952 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3956 my ($self, $msg) = @_;
3959 $self->{ERRSTR} = $msg;
3967 # Default guess for the type of an image from extension
3969 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
3973 ( map { $_ => $_ } @simple_types ),
3979 pnm => "pnm", # technically wrong, but historically it works in Imager
3992 sub def_guess_type {
3995 my ($ext) = $name =~ /\.([^.]+)$/
3998 my $type = $ext_types{$ext}
4005 return @combine_types;
4008 # get the minimum of a list
4012 for(@_) { if ($_<$mx) { $mx=$_; }}
4016 # get the maximum of a list
4020 for(@_) { if ($_>$mx) { $mx=$_; }}
4024 # string stuff for iptc headers
4028 $str = substr($str,3);
4029 $str =~ s/[\n\r]//g;
4036 # A little hack to parse iptc headers.
4041 my($caption,$photogr,$headln,$credit);
4043 my $str=$self->{IPTCRAW};
4048 @ar=split(/8BIM/,$str);
4053 @sar=split(/\034\002/);
4054 foreach $item (@sar) {
4055 if ($item =~ m/^x/) {
4056 $caption = _clean($item);
4059 if ($item =~ m/^P/) {
4060 $photogr = _clean($item);
4063 if ($item =~ m/^i/) {
4064 $headln = _clean($item);
4067 if ($item =~ m/^n/) {
4068 $credit = _clean($item);
4074 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4081 or die "Only C language supported";
4083 require Imager::ExtUtils;
4084 return Imager::ExtUtils->inline_config;
4087 # threads shouldn't try to close raw Imager objects
4088 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4091 # this serves two purposes:
4092 # - a class method to load the file support modules included with Imager
4093 # (or were included, once the library dependent modules are split out)
4094 # - something for Module::ScanDeps to analyze
4095 # https://rt.cpan.org/Ticket/Display.html?id=6566
4097 eval { require Imager::File::GIF };
4098 eval { require Imager::File::JPEG };
4099 eval { require Imager::File::PNG };
4100 eval { require Imager::File::SGI };
4101 eval { require Imager::File::TIFF };
4102 eval { require Imager::File::ICO };
4103 eval { require Imager::Font::W32 };
4104 eval { require Imager::Font::FT2 };
4105 eval { require Imager::Font::T1 };
4108 # backward compatibility for %formats
4109 package Imager::FORMATS;
4111 use constant IX_FORMATS => 0;
4112 use constant IX_LIST => 1;
4113 use constant IX_INDEX => 2;
4114 use constant IX_CLASSES => 3;
4117 my ($class, $formats, $classes) = @_;
4119 return bless [ $formats, [ ], 0, $classes ], $class;
4123 my ($self, $key) = @_;
4125 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4128 my $loaded = Imager::_load_file($file, \$error);
4133 if ($error =~ /^Can't locate /) {
4134 $error = "Can't locate $file";
4136 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4139 $self->[IX_FORMATS]{$key} = $value;
4145 my ($self, $key) = @_;
4147 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4149 $self->[IX_CLASSES]{$key} or return undef;
4151 return $self->_check($key);
4155 die "%Imager::formats is not user monifiable";
4159 die "%Imager::formats is not user monifiable";
4163 die "%Imager::formats is not user monifiable";
4167 my ($self, $key) = @_;
4169 if (exists $self->[IX_FORMATS]{$key}) {
4170 my $value = $self->[IX_FORMATS]{$key}
4175 $self->_check($key) or return 1==0;
4183 unless (@{$self->[IX_LIST]}) {
4185 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4186 keys %{$self->[IX_FORMATS]};
4188 for my $key (keys %{$self->[IX_CLASSES]}) {
4189 $self->[IX_FORMATS]{$key} and next;
4191 and push @{$self->[IX_LIST]}, $key;
4195 @{$self->[IX_LIST]} or return;
4196 $self->[IX_INDEX] = 1;
4197 return $self->[IX_LIST][0];
4203 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4206 return $self->[IX_LIST][$self->[IX_INDEX]++];
4212 return scalar @{$self->[IX_LIST]};
4217 # Below is the stub of documentation for your module. You better edit it!
4221 Imager - Perl extension for Generating 24 bit Images
4231 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4236 # see Imager::Files for information on the read() method
4237 my $img = Imager->new(file=>$file)
4238 or die Imager->errstr();
4240 $file =~ s/\.[^.]*$//;
4242 # Create smaller version
4243 # documented in Imager::Transformations
4244 my $thumb = $img->scale(scalefactor=>.3);
4246 # Autostretch individual channels
4247 $thumb->filter(type=>'autolevels');
4249 # try to save in one of these formats
4252 for $format ( qw( png gif jpeg tiff ppm ) ) {
4253 # Check if given format is supported
4254 if ($Imager::formats{$format}) {
4255 $file.="_low.$format";
4256 print "Storing image as: $file\n";
4257 # documented in Imager::Files
4258 $thumb->write(file=>$file) or
4266 Imager is a module for creating and altering images. It can read and
4267 write various image formats, draw primitive shapes like lines,and
4268 polygons, blend multiple images together in various ways, scale, crop,
4269 render text and more.
4271 =head2 Overview of documentation
4277 Imager - This document - Synopsis, Example, Table of Contents and
4282 L<Imager::Tutorial> - a brief introduction to Imager.
4286 L<Imager::Cookbook> - how to do various things with Imager.
4290 L<Imager::ImageTypes> - Basics of constructing image objects with
4291 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4292 8/16/double bits/channel, color maps, channel masks, image tags, color
4293 quantization. Also discusses basic image information methods.
4297 L<Imager::Files> - IO interaction, reading/writing images, format
4302 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4307 L<Imager::Color> - Color specification.
4311 L<Imager::Fill> - Fill pattern specification.
4315 L<Imager::Font> - General font rendering, bounding boxes and font
4320 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4321 blending, pasting, convert and map.
4325 L<Imager::Engines> - Programmable transformations through
4326 C<transform()>, C<transform2()> and C<matrix_transform()>.
4330 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4335 L<Imager::Expr> - Expressions for evaluation engine used by
4340 L<Imager::Matrix2d> - Helper class for affine transformations.
4344 L<Imager::Fountain> - Helper for making gradient profiles.
4348 L<Imager::API> - using Imager's C API
4352 L<Imager::APIRef> - API function reference
4356 L<Imager::Inline> - using Imager's C API from Inline::C
4360 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4364 L<Imager::Security> - brief security notes.
4368 =head2 Basic Overview
4370 An Image object is created with C<$img = Imager-E<gt>new()>.
4373 $img=Imager->new(); # create empty image
4374 $img->read(file=>'lena.png',type=>'png') or # read image from file
4375 die $img->errstr(); # give an explanation
4376 # if something failed
4378 or if you want to create an empty image:
4380 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4382 This example creates a completely black image of width 400 and height
4385 =head1 ERROR HANDLING
4387 In general a method will return false when it fails, if it does use
4388 the C<errstr()> method to find out why:
4394 Returns the last error message in that context.
4396 If the last error you received was from calling an object method, such
4397 as read, call errstr() as an object method to find out why:
4399 my $image = Imager->new;
4400 $image->read(file => 'somefile.gif')
4401 or die $image->errstr;
4403 If it was a class method then call errstr() as a class method:
4405 my @imgs = Imager->read_multi(file => 'somefile.gif')
4406 or die Imager->errstr;
4408 Note that in some cases object methods are implemented in terms of
4409 class methods so a failing object method may set both.
4413 The C<Imager-E<gt>new> method is described in detail in
4414 L<Imager::ImageTypes>.
4418 Where to find information on methods for Imager class objects.
4420 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4423 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4425 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4428 arc() - L<Imager::Draw/arc()> - draw a filled arc
4430 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4433 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4435 check_file_limits() - L<Imager::Files/check_file_limits()>
4437 circle() - L<Imager::Draw/circle()> - draw a filled circle
4439 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4442 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4443 colors in an image's palette (paletted images only)
4445 combine() - L<Imager::Transformations/combine()> - combine channels
4446 from one or more images.
4448 combines() - L<Imager::Draw/combines()> - return a list of the
4449 different combine type keywords
4451 compose() - L<Imager::Transformations/compose()> - compose one image
4454 convert() - L<Imager::Transformations/convert()> - transform the color
4457 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4460 crop() - L<Imager::Transformations/crop()> - extract part of an image
4462 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4463 used to guess the output file format based on the output file name
4465 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4467 difference() - L<Imager::Filters/difference()> - produce a difference
4468 images from two input images.
4470 errstr() - L</errstr()> - the error from the last failed operation.
4472 filter() - L<Imager::Filters/filter()> - image filtering
4474 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4475 palette, if it has one
4477 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4480 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4483 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4484 samples per pixel for an image
4486 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4487 different colors used by an image (works for direct color images)
4489 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4490 palette, if it has one
4492 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4494 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4496 get_file_limits() - L<Imager::Files/get_file_limits()>
4498 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4501 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4503 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4506 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4507 row or partial row of pixels.
4509 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4510 row or partial row of pixels.
4512 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4515 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4518 init() - L<Imager::ImageTypes/init()>
4520 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4521 image write functions should write the image in their bilevel (blank
4522 and white, no gray levels) format
4524 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4527 line() - L<Imager::Draw/line()> - draw an interval
4529 load_plugin() - L<Imager::Filters/load_plugin()>
4531 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4534 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4535 color palette from one or more input images.
4537 map() - L<Imager::Transformations/map()> - remap color
4540 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4542 matrix_transform() - L<Imager::Engines/matrix_transform()>
4544 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4546 NC() - L<Imager::Handy/NC()>
4548 NCF() - L<Imager::Handy/NCF()>
4550 new() - L<Imager::ImageTypes/new()>
4552 newcolor() - L<Imager::Handy/newcolor()>
4554 newcolour() - L<Imager::Handy/newcolour()>
4556 newfont() - L<Imager::Handy/newfont()>
4558 NF() - L<Imager::Handy/NF()>
4560 open() - L<Imager::Files/read()> - an alias for read()
4562 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4566 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4569 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4572 polygon() - L<Imager::Draw/polygon()>
4574 polyline() - L<Imager::Draw/polyline()>
4576 preload() - L<Imager::Files/preload()>
4578 read() - L<Imager::Files/read()> - read a single image from an image file
4580 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4583 read_types() - L<Imager::Files/read_types()> - list image types Imager
4586 register_filter() - L<Imager::Filters/register_filter()>
4588 register_reader() - L<Imager::Files/register_reader()>
4590 register_writer() - L<Imager::Files/register_writer()>
4592 rotate() - L<Imager::Transformations/rotate()>
4594 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4595 onto an image and use the alpha channel
4597 scale() - L<Imager::Transformations/scale()>
4599 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4601 scaleX() - L<Imager::Transformations/scaleX()>
4603 scaleY() - L<Imager::Transformations/scaleY()>
4605 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4608 set_file_limits() - L<Imager::Files/set_file_limits()>
4610 setmask() - L<Imager::ImageTypes/setmask()>
4612 setpixel() - L<Imager::Draw/setpixel()>
4614 setsamples() - L<Imager::Draw/setsamples()>
4616 setscanline() - L<Imager::Draw/setscanline()>
4618 settag() - L<Imager::ImageTypes/settag()>
4620 string() - L<Imager::Draw/string()> - draw text on an image
4622 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4624 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4626 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4628 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4630 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4631 double per sample image.
4633 transform() - L<Imager::Engines/"transform()">
4635 transform2() - L<Imager::Engines/"transform2()">
4637 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4639 unload_plugin() - L<Imager::Filters/unload_plugin()>
4641 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4644 write() - L<Imager::Files/write()> - write an image to a file
4646 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4649 write_types() - L<Imager::Files/read_types()> - list image types Imager
4652 =head1 CONCEPT INDEX
4654 animated GIF - L<Imager::Files/"Writing an animated GIF">
4656 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4657 L<Imager::ImageTypes/"Common Tags">.
4659 blend - alpha blending one image onto another
4660 L<Imager::Transformations/rubthrough()>
4662 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4664 boxes, drawing - L<Imager::Draw/box()>
4666 changes between image - L<Imager::Filters/"Image Difference">
4668 channels, combine into one image - L<Imager::Transformations/combine()>
4670 color - L<Imager::Color>
4672 color names - L<Imager::Color>, L<Imager::Color::Table>
4674 combine modes - L<Imager::Draw/"Combine Types">
4676 compare images - L<Imager::Filters/"Image Difference">
4678 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4680 convolution - L<Imager::Filters/conv>
4682 cropping - L<Imager::Transformations/crop()>
4684 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4686 C<diff> images - L<Imager::Filters/"Image Difference">
4688 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4689 L<Imager::Cookbook/"Image spatial resolution">
4691 drawing boxes - L<Imager::Draw/box()>
4693 drawing lines - L<Imager::Draw/line()>
4695 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4697 error message - L</"ERROR HANDLING">
4699 files, font - L<Imager::Font>
4701 files, image - L<Imager::Files>
4703 filling, types of fill - L<Imager::Fill>
4705 filling, boxes - L<Imager::Draw/box()>
4707 filling, flood fill - L<Imager::Draw/flood_fill()>
4709 flood fill - L<Imager::Draw/flood_fill()>
4711 fonts - L<Imager::Font>
4713 fonts, drawing with - L<Imager::Draw/string()>,
4714 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4716 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4718 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4720 fountain fill - L<Imager::Fill/"Fountain fills">,
4721 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4722 L<Imager::Filters/gradgen>
4724 GIF files - L<Imager::Files/"GIF">
4726 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4728 gradient fill - L<Imager::Fill/"Fountain fills">,
4729 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4730 L<Imager::Filters/gradgen>
4732 gray scale, convert image to - L<Imager::Transformations/convert()>
4734 gaussian blur - L<Imager::Filters/gaussian>
4736 hatch fills - L<Imager::Fill/"Hatched fills">
4738 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4740 invert image - L<Imager::Filters/hardinvert>,
4741 L<Imager::Filters/hardinvertall>
4743 JPEG - L<Imager::Files/"JPEG">
4745 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4747 lines, drawing - L<Imager::Draw/line()>
4749 matrix - L<Imager::Matrix2d>,
4750 L<Imager::Engines/"Matrix Transformations">,
4751 L<Imager::Font/transform()>
4753 metadata, image - L<Imager::ImageTypes/"Tags">
4755 mosaic - L<Imager::Filters/mosaic>
4757 noise, filter - L<Imager::Filters/noise>
4759 noise, rendered - L<Imager::Filters/turbnoise>,
4760 L<Imager::Filters/radnoise>
4762 paste - L<Imager::Transformations/paste()>,
4763 L<Imager::Transformations/rubthrough()>
4765 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4766 L<Imager::ImageTypes/new()>
4768 =for stopwords posterize
4770 posterize - L<Imager::Filters/postlevels>
4772 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4774 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4776 rectangles, drawing - L<Imager::Draw/box()>
4778 resizing an image - L<Imager::Transformations/scale()>,
4779 L<Imager::Transformations/crop()>
4781 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4783 saving an image - L<Imager::Files>
4785 scaling - L<Imager::Transformations/scale()>
4787 security - L<Imager::Security>
4789 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4791 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4793 size, image - L<Imager::ImageTypes/getwidth()>,
4794 L<Imager::ImageTypes/getheight()>
4796 size, text - L<Imager::Font/bounding_box()>
4798 tags, image metadata - L<Imager::ImageTypes/"Tags">
4800 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4801 L<Imager::Font::Wrap>
4803 text, wrapping text in an area - L<Imager::Font::Wrap>
4805 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4807 tiles, color - L<Imager::Filters/mosaic>
4809 transparent images - L<Imager::ImageTypes>,
4810 L<Imager::Cookbook/"Transparent PNG">
4812 =for stopwords unsharp
4814 unsharp mask - L<Imager::Filters/unsharpmask>
4816 watermark - L<Imager::Filters/watermark>
4818 writing an image to a file - L<Imager::Files>
4822 Imager doesn't support perl threads.
4824 Imager has limited code to prevent double frees if you create images,
4825 colors etc, and then create a thread, but has no code to prevent two
4826 threads entering Imager's error handling code, and none is likely to
4831 The best place to get help with Imager is the mailing list.
4833 To subscribe send a message with C<subscribe> in the body to:
4835 imager-devel+request@molar.is
4841 L<http://www.molar.is/en/lists/imager-devel/>
4845 where you can also find the mailing list archive.
4847 You can report bugs by pointing your browser at:
4851 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4855 or by sending an email to:
4859 bug-Imager@rt.cpan.org
4863 Please remember to include the versions of Imager, perl, supporting
4864 libraries, and any relevant code. If you have specific images that
4865 cause the problems, please include those too.
4867 If you don't want to publish your email address on a mailing list you
4868 can use CPAN::Forum:
4870 http://www.cpanforum.com/dist/Imager
4872 You will need to register to post.
4874 =head1 CONTRIBUTING TO IMAGER
4880 If you like or dislike Imager, you can add a public review of Imager
4883 http://cpanratings.perl.org/dist/Imager
4885 =for stopwords Bitcard
4887 This requires a Bitcard account (http://www.bitcard.org).
4889 You can also send email to the maintainer below.
4891 If you send me a bug report via email, it will be copied to Request
4896 I accept patches, preferably against the master branch in git. Please
4897 include an explanation of the reason for why the patch is needed or
4900 Your patch should include regression tests where possible, otherwise
4901 it will be delayed until I get a chance to write them.
4903 To browse Imager's git repository:
4905 http://git.imager.perl.org/imager.git
4909 https://github.com/tonycoz/imager
4913 git clone git://git.imager.perl.org/imager.git
4917 git clone git://github.com/tonycoz/imager.git
4921 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
4923 Arnar M. Hrafnkelsson is the original author of Imager.
4925 Many others have contributed to Imager, please see the C<README> for a
4930 Imager is licensed under the same terms as perl itself.
4933 makeblendedfont Fontforge
4935 A test font, generated by the Debian packaged Fontforge,
4936 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
4937 copyrighted by Adobe. See F<adobe.txt> in the source for license
4942 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4943 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4944 L<Imager::Font>(3), L<Imager::Transformations>(3),
4945 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4946 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4948 L<http://imager.perl.org/>
4950 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4952 Other perl imaging modules include:
4954 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3),
4955 L<Prima::Image>, L<IPA>.
4957 If you're trying to use Imager for array processing, you should
4958 probably using L<PDL>.