4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
109 # registered file readers
112 # registered file writers
115 # modules we attempted to autoload
116 my %attempted_to_load;
118 # errors from loading files
119 my %file_load_errors;
121 # what happened when we tried to load
122 my %reader_load_errors;
123 my %writer_load_errors;
125 # library keys that are image file formats
126 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
128 # image pixel combine types
130 qw/none normal multiply dissolve add subtract diff lighten darken
131 hue saturation value color/;
133 @combine_types{@combine_types} = 0 .. $#combine_types;
134 $combine_types{mult} = $combine_types{multiply};
135 $combine_types{'sub'} = $combine_types{subtract};
136 $combine_types{sat} = $combine_types{saturation};
138 # this will be used to store global defaults at some point
143 my $ex_version = eval $Exporter::VERSION;
144 if ($ex_version < 5.57) {
149 XSLoader::load(Imager => $VERSION);
155 png => "Imager::File::PNG",
156 gif => "Imager::File::GIF",
157 tiff => "Imager::File::TIFF",
158 jpeg => "Imager::File::JPEG",
159 w32 => "Imager::Font::W32",
160 ft2 => "Imager::Font::FT2",
161 t1 => "Imager::Font::T1",
164 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
167 for(i_list_formats()) { $formats_low{$_}++; }
169 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
173 # the members of the subhashes under %filters are:
174 # callseq - a list of the parameters to the underlying filter in the
175 # order they are passed
176 # callsub - a code ref that takes a named parameter list and calls the
178 # defaults - a hash of default values
179 # names - defines names for value of given parameters so if the names
180 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
181 # foo parameter, the filter will receive 1 for the foo
184 callseq => ['image','intensity'],
185 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
189 callseq => ['image', 'amount', 'subtype'],
190 defaults => { amount=>3,subtype=>0 },
191 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
194 $filters{hardinvert} ={
195 callseq => ['image'],
197 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
200 $filters{hardinvertall} =
202 callseq => ['image'],
204 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
207 $filters{autolevels} ={
208 callseq => ['image','lsat','usat','skew'],
209 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
210 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
213 $filters{turbnoise} ={
214 callseq => ['image'],
215 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
216 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
219 $filters{radnoise} ={
220 callseq => ['image'],
221 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
222 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
227 callseq => ['image', 'coef'],
232 i_conv($hsh{image},$hsh{coef})
233 or die Imager->_error_as_msg() . "\n";
239 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
240 defaults => { dist => 0 },
244 my @colors = @{$hsh{colors}};
247 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
251 $filters{nearest_color} =
253 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
258 # make sure the segments are specified with colors
260 for my $color (@{$hsh{colors}}) {
261 my $new_color = _color($color)
262 or die $Imager::ERRSTR."\n";
263 push @colors, $new_color;
266 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
268 or die Imager->_error_as_msg() . "\n";
271 $filters{gaussian} = {
272 callseq => [ 'image', 'stddev' ],
274 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
278 callseq => [ qw(image size) ],
279 defaults => { size => 20 },
280 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
284 callseq => [ qw(image bump elevation lightx lighty st) ],
285 defaults => { elevation=>0, st=> 2 },
288 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
289 $hsh{lightx}, $hsh{lighty}, $hsh{st});
292 $filters{bumpmap_complex} =
294 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
311 for my $cname (qw/Ia Il Is/) {
312 my $old = $hsh{$cname};
313 my $new_color = _color($old)
314 or die $Imager::ERRSTR, "\n";
315 $hsh{$cname} = $new_color;
317 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
318 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
319 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
323 $filters{postlevels} =
325 callseq => [ qw(image levels) ],
326 defaults => { levels => 10 },
327 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
329 $filters{watermark} =
331 callseq => [ qw(image wmark tx ty pixdiff) ],
332 defaults => { pixdiff=>10, tx=>0, ty=>0 },
336 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
342 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
344 ftype => { linear => 0,
350 repeat => { none => 0,
365 multiply => 2, mult => 2,
368 subtract => 5, 'sub' => 5,
378 defaults => { ftype => 0, repeat => 0, combine => 0,
379 super_sample => 0, ssample_param => 4,
392 # make sure the segments are specified with colors
394 for my $segment (@{$hsh{segments}}) {
395 my @new_segment = @$segment;
397 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
398 push @segments, \@new_segment;
401 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
402 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
403 $hsh{ssample_param}, \@segments)
404 or die Imager->_error_as_msg() . "\n";
407 $filters{unsharpmask} =
409 callseq => [ qw(image stddev scale) ],
410 defaults => { stddev=>2.0, scale=>1.0 },
414 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
418 $FORMATGUESS=\&def_guess_type;
428 # NOTE: this might be moved to an import override later on
433 if ($_[$i] eq '-log-stderr') {
441 goto &Exporter::import;
445 Imager->open_log(log => $_[0], level => $_[1]);
450 my %parms=(loglevel=>1,@_);
452 if (exists $parms{'warn_obsolete'}) {
453 $warn_obsolete = $parms{'warn_obsolete'};
457 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
461 if (exists $parms{'t1log'}) {
463 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
464 Imager->_set_error(Imager->_error_as_msg);
478 my (%opts) = ( loglevel => 1, @_ );
480 $is_logging = i_init_log($opts{log}, $opts{loglevel});
481 unless ($is_logging) {
482 Imager->_set_error(Imager->_error_as_msg());
486 Imager->log("Imager $VERSION starting\n", 1);
492 i_init_log(undef, -1);
497 my ($class, $message, $level) = @_;
499 defined $level or $level = 1;
501 i_log_entry($message, $level);
511 print "shutdown code\n";
512 # for(keys %instances) { $instances{$_}->DESTROY(); }
513 malloc_state(); # how do decide if this should be used? -- store something from the import
514 print "Imager exiting\n";
518 # Load a filter plugin
523 my ($DSO_handle,$str)=DSO_open($filename);
524 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
525 my %funcs=DSO_funclist($DSO_handle);
526 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
528 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
530 $DSOs{$filename}=[$DSO_handle,\%funcs];
533 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
534 $DEBUG && print "eval string:\n",$evstr,"\n";
546 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
547 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
548 for(keys %{$funcref}) {
550 $DEBUG && print "unloading: $_\n";
552 my $rc=DSO_close($DSO_handle);
553 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
557 # take the results of i_error() and make a message out of it
559 return join(": ", map $_->[0], i_errors());
562 # this function tries to DWIM for color parameters
563 # color objects are used as is
564 # simple scalars are simply treated as single parameters to Imager::Color->new
565 # hashrefs are treated as named argument lists to Imager::Color->new
566 # arrayrefs are treated as list arguments to Imager::Color->new iff any
568 # other arrayrefs are treated as list arguments to Imager::Color::Float
572 # perl 5.6.0 seems to do weird things to $arg if we don't make an
573 # explicitly stringified copy
574 # I vaguely remember a bug on this on p5p, but couldn't find it
575 # through bugs.perl.org (I had trouble getting it to find any bugs)
576 my $copy = $arg . "";
580 if (UNIVERSAL::isa($arg, "Imager::Color")
581 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
585 if ($copy =~ /^HASH\(/) {
586 $result = Imager::Color->new(%$arg);
588 elsif ($copy =~ /^ARRAY\(/) {
589 $result = Imager::Color->new(@$arg);
592 $Imager::ERRSTR = "Not a color";
597 # assume Imager::Color::new knows how to handle it
598 $result = Imager::Color->new($arg);
605 my ($self, $combine, $default) = @_;
607 if (!defined $combine && ref $self) {
608 $combine = $self->{combine};
610 defined $combine or $combine = $defaults{combine};
611 defined $combine or $combine = $default;
613 if (exists $combine_types{$combine}) {
614 $combine = $combine_types{$combine};
621 my ($self, $method) = @_;
623 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
625 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
626 $msg = "$method: $msg" if $method;
627 $self->_set_error($msg);
632 # returns first defined parameter
635 return $_ if defined $_;
641 # Methods to be called on objects.
644 # Create a new Imager object takes very few parameters.
645 # usually you call this method and then call open from
646 # the resulting object
653 $self->{IMG}=undef; # Just to indicate what exists
654 $self->{ERRSTR}=undef; #
655 $self->{DEBUG}=$DEBUG;
656 $self->{DEBUG} and print "Initialized Imager\n";
657 if (defined $hsh{xsize} || defined $hsh{ysize}) {
658 unless ($self->img_set(%hsh)) {
659 $Imager::ERRSTR = $self->{ERRSTR};
663 elsif (defined $hsh{file} ||
666 defined $hsh{callback} ||
667 defined $hsh{readcb} ||
668 defined $hsh{data}) {
669 # allow $img = Imager->new(file => $filename)
672 # type is already used as a parameter to new(), rename it for the
674 if ($hsh{filetype}) {
675 $extras{type} = $hsh{filetype};
677 unless ($self->read(%hsh, %extras)) {
678 $Imager::ERRSTR = $self->{ERRSTR};
686 # Copy an entire image with no changes
687 # - if an image has magic the copy of it will not be magical
692 $self->_valid_image("copy")
695 unless (defined wantarray) {
697 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
701 my $newcopy=Imager->new();
702 $newcopy->{IMG} = i_copy($self->{IMG});
711 $self->_valid_image("paste")
714 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
715 my $src = $input{img} || $input{src};
717 $self->_set_error("no source image");
720 unless ($src->_valid_image("paste")) {
721 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
724 $input{left}=0 if $input{left} <= 0;
725 $input{top}=0 if $input{top} <= 0;
727 my($r,$b)=i_img_info($src->{IMG});
728 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
729 my ($src_right, $src_bottom);
730 if ($input{src_coords}) {
731 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
734 if (defined $input{src_maxx}) {
735 $src_right = $input{src_maxx};
737 elsif (defined $input{width}) {
738 if ($input{width} <= 0) {
739 $self->_set_error("paste: width must me positive");
742 $src_right = $src_left + $input{width};
747 if (defined $input{src_maxy}) {
748 $src_bottom = $input{src_maxy};
750 elsif (defined $input{height}) {
751 if ($input{height} < 0) {
752 $self->_set_error("paste: height must be positive");
755 $src_bottom = $src_top + $input{height};
762 $src_right > $r and $src_right = $r;
763 $src_bottom > $b and $src_bottom = $b;
765 if ($src_right <= $src_left
766 || $src_bottom < $src_top) {
767 $self->_set_error("nothing to paste");
771 i_copyto($self->{IMG}, $src->{IMG},
772 $src_left, $src_top, $src_right, $src_bottom,
773 $input{left}, $input{top});
775 return $self; # What should go here??
778 # Crop an image - i.e. return a new image that is smaller
783 $self->_valid_image("crop")
786 unless (defined wantarray) {
788 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
794 my ($w, $h, $l, $r, $b, $t) =
795 @hsh{qw(width height left right bottom top)};
797 # work through the various possibilities
802 elsif (!defined $r) {
803 $r = $self->getwidth;
815 $l = int(0.5+($self->getwidth()-$w)/2);
820 $r = $self->getwidth;
826 elsif (!defined $b) {
827 $b = $self->getheight;
839 $t=int(0.5+($self->getheight()-$h)/2);
844 $b = $self->getheight;
847 ($l,$r)=($r,$l) if $l>$r;
848 ($t,$b)=($b,$t) if $t>$b;
851 $r > $self->getwidth and $r = $self->getwidth;
853 $b > $self->getheight and $b = $self->getheight;
855 if ($l == $r || $t == $b) {
856 $self->_set_error("resulting image would have no content");
859 if( $r < $l or $b < $t ) {
860 $self->_set_error("attempting to crop outside of the image");
863 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
865 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
870 my ($self, %opts) = @_;
875 my $x = $opts{xsize} || $self->getwidth;
876 my $y = $opts{ysize} || $self->getheight;
877 my $channels = $opts{channels} || $self->getchannels;
879 my $out = Imager->new;
880 if ($channels == $self->getchannels) {
881 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
884 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
886 unless ($out->{IMG}) {
887 $self->{ERRSTR} = $self->_error_as_msg;
894 # Sets an image to a certain size and channel number
895 # if there was previously data in the image it is discarded
900 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
902 if (defined($self->{IMG})) {
903 # let IIM_DESTROY destroy it, it's possible this image is
904 # referenced from a virtual image (like masked)
905 #i_img_destroy($self->{IMG});
909 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
910 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
911 $hsh{maxcolors} || 256);
913 elsif ($hsh{bits} eq 'double') {
914 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
916 elsif ($hsh{bits} == 16) {
917 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
920 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
924 unless ($self->{IMG}) {
925 $self->{ERRSTR} = Imager->_error_as_msg();
932 # created a masked version of the current image
936 $self->_valid_image("masked")
939 my %opts = (left => 0,
941 right => $self->getwidth,
942 bottom => $self->getheight,
944 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
946 my $result = Imager->new;
947 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
948 $opts{top}, $opts{right} - $opts{left},
949 $opts{bottom} - $opts{top});
950 unless ($result->{IMG}) {
951 $self->_set_error(Imager->_error_as_msg);
955 # keep references to the mask and base images so they don't
957 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
962 # convert an RGB image into a paletted image
966 if (@_ != 1 && !ref $_[0]) {
973 unless (defined wantarray) {
975 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
979 $self->_valid_image("to_paletted")
982 my $result = Imager->new;
983 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
984 $self->_set_error(Imager->_error_as_msg);
992 my ($class, $quant, @images) = @_;
995 Imager->_set_error("make_palette: supply at least one image");
999 for my $img (@images) {
1000 unless ($img->{IMG}) {
1001 Imager->_set_error("make_palette: image $index is empty");
1007 return i_img_make_palette($quant, map $_->{IMG}, @images);
1010 # convert a paletted (or any image) to an 8-bit/channel RGB image
1014 unless (defined wantarray) {
1015 my @caller = caller;
1016 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1020 $self->_valid_image("to_rgb8")
1023 my $result = Imager->new;
1024 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1025 $self->_set_error(Imager->_error_as_msg());
1032 # convert a paletted (or any image) to a 16-bit/channel RGB image
1036 unless (defined wantarray) {
1037 my @caller = caller;
1038 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1042 $self->_valid_image("to_rgb16")
1045 my $result = Imager->new;
1046 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1047 $self->_set_error(Imager->_error_as_msg());
1054 # convert a paletted (or any image) to an double/channel RGB image
1058 unless (defined wantarray) {
1059 my @caller = caller;
1060 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1064 $self->_valid_image("to_rgb_double")
1067 my $result = Imager->new;
1068 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1069 $self->_set_error(Imager->_error_as_msg());
1078 my %opts = (colors=>[], @_);
1080 $self->_valid_image("addcolors")
1083 my @colors = @{$opts{colors}}
1086 for my $color (@colors) {
1087 $color = _color($color);
1089 $self->_set_error($Imager::ERRSTR);
1094 return i_addcolors($self->{IMG}, @colors);
1099 my %opts = (start=>0, colors=>[], @_);
1101 $self->_valid_image("setcolors")
1104 my @colors = @{$opts{colors}}
1107 for my $color (@colors) {
1108 $color = _color($color);
1110 $self->_set_error($Imager::ERRSTR);
1115 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1122 $self->_valid_image("getcolors")
1125 if (!exists $opts{start} && !exists $opts{count}) {
1128 $opts{count} = $self->colorcount;
1130 elsif (!exists $opts{count}) {
1133 elsif (!exists $opts{start}) {
1137 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1143 $self->_valid_image("colorcount")
1146 return i_colorcount($self->{IMG});
1152 $self->_valid_image("maxcolors")
1155 i_maxcolors($self->{IMG});
1162 $self->_valid_image("findcolor")
1165 unless ($opts{color}) {
1166 $self->_set_error("findcolor: no color parameter");
1170 my $color = _color($opts{color})
1173 return i_findcolor($self->{IMG}, $color);
1179 $self->_valid_image("bits")
1182 my $bits = i_img_bits($self->{IMG});
1183 if ($bits && $bits == length(pack("d", 1)) * 8) {
1192 $self->_valid_image("type")
1195 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1201 $self->_valid_image("virtual")
1204 return i_img_virtual($self->{IMG});
1210 $self->_valid_image("is_bilevel")
1213 return i_img_is_monochrome($self->{IMG});
1217 my ($self, %opts) = @_;
1219 $self->_valid_image("tags")
1222 if (defined $opts{name}) {
1226 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1227 push @result, (i_tags_get($self->{IMG}, $found))[1];
1230 return wantarray ? @result : $result[0];
1232 elsif (defined $opts{code}) {
1236 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1237 push @result, (i_tags_get($self->{IMG}, $found))[1];
1244 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1247 return i_tags_count($self->{IMG});
1256 $self->_valid_image("addtag")
1260 if (defined $opts{value}) {
1261 if ($opts{value} =~ /^\d+$/) {
1263 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1266 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1269 elsif (defined $opts{data}) {
1270 # force addition as a string
1271 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1274 $self->{ERRSTR} = "No value supplied";
1278 elsif ($opts{code}) {
1279 if (defined $opts{value}) {
1280 if ($opts{value} =~ /^\d+$/) {
1282 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1285 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1288 elsif (defined $opts{data}) {
1289 # force addition as a string
1290 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1293 $self->{ERRSTR} = "No value supplied";
1306 $self->_valid_image("deltag")
1309 if (defined $opts{'index'}) {
1310 return i_tags_delete($self->{IMG}, $opts{'index'});
1312 elsif (defined $opts{name}) {
1313 return i_tags_delbyname($self->{IMG}, $opts{name});
1315 elsif (defined $opts{code}) {
1316 return i_tags_delbycode($self->{IMG}, $opts{code});
1319 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1325 my ($self, %opts) = @_;
1327 $self->_valid_image("settag")
1331 $self->deltag(name=>$opts{name});
1332 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1334 elsif (defined $opts{code}) {
1335 $self->deltag(code=>$opts{code});
1336 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1344 sub _get_reader_io {
1345 my ($self, $input) = @_;
1348 return $input->{io}, undef;
1350 elsif ($input->{fd}) {
1351 return io_new_fd($input->{fd});
1353 elsif ($input->{fh}) {
1354 unless (Scalar::Util::openhandle($input->{fh})) {
1355 $self->_set_error("Handle in fh option not opened");
1358 return Imager::IO->new_fh($input->{fh});
1360 elsif ($input->{file}) {
1361 my $file = IO::File->new($input->{file}, "r");
1363 $self->_set_error("Could not open $input->{file}: $!");
1367 return (io_new_fd(fileno($file)), $file);
1369 elsif ($input->{data}) {
1370 return io_new_buffer($input->{data});
1372 elsif ($input->{callback} || $input->{readcb}) {
1373 if (!$input->{seekcb}) {
1374 $self->_set_error("Need a seekcb parameter");
1376 if ($input->{maxbuffer}) {
1377 return io_new_cb($input->{writecb},
1378 $input->{callback} || $input->{readcb},
1379 $input->{seekcb}, $input->{closecb},
1380 $input->{maxbuffer});
1383 return io_new_cb($input->{writecb},
1384 $input->{callback} || $input->{readcb},
1385 $input->{seekcb}, $input->{closecb});
1389 $self->_set_error("file/fd/fh/data/callback parameter missing");
1394 sub _get_writer_io {
1395 my ($self, $input) = @_;
1397 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1404 elsif ($input->{fd}) {
1405 $io = io_new_fd($input->{fd});
1407 elsif ($input->{fh}) {
1408 unless (Scalar::Util::openhandle($input->{fh})) {
1409 $self->_set_error("Handle in fh option not opened");
1412 $io = Imager::IO->new_fh($input->{fh});
1414 elsif ($input->{file}) {
1415 my $fh = new IO::File($input->{file},"w+");
1417 $self->_set_error("Could not open file $input->{file}: $!");
1420 binmode($fh) or die;
1421 $io = io_new_fd(fileno($fh));
1424 elsif ($input->{data}) {
1425 $io = io_new_bufchain();
1427 elsif ($input->{callback} || $input->{writecb}) {
1428 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1431 $io = io_new_cb($input->{callback} || $input->{writecb},
1433 $input->{seekcb}, $input->{closecb});
1436 $self->_set_error("file/fd/fh/data/callback parameter missing");
1440 unless ($buffered) {
1441 $io->set_buffered(0);
1444 return ($io, @extras);
1447 # Read an image from file
1453 if (defined($self->{IMG})) {
1454 # let IIM_DESTROY do the destruction, since the image may be
1455 # referenced from elsewhere
1456 #i_img_destroy($self->{IMG});
1457 undef($self->{IMG});
1460 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1462 my $type = $input{'type'};
1464 $type = i_test_format_probe($IO, -1);
1467 if ($input{file} && !$type) {
1469 $type = $FORMATGUESS->($input{file});
1473 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1474 $input{file} and $msg .= " or file name";
1475 $self->_set_error($msg);
1479 _reader_autoload($type);
1481 if ($readers{$type} && $readers{$type}{single}) {
1482 return $readers{$type}{single}->($self, $IO, %input);
1485 unless ($formats_low{$type}) {
1486 my $read_types = join ', ', sort Imager->read_types();
1487 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1491 my $allow_incomplete = $input{allow_incomplete};
1492 defined $allow_incomplete or $allow_incomplete = 0;
1494 if ( $type eq 'pnm' ) {
1495 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1496 if ( !defined($self->{IMG}) ) {
1497 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1500 $self->{DEBUG} && print "loading a pnm file\n";
1504 if ( $type eq 'bmp' ) {
1505 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1506 if ( !defined($self->{IMG}) ) {
1507 $self->{ERRSTR}=$self->_error_as_msg();
1510 $self->{DEBUG} && print "loading a bmp file\n";
1513 if ( $type eq 'tga' ) {
1514 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1515 if ( !defined($self->{IMG}) ) {
1516 $self->{ERRSTR}=$self->_error_as_msg();
1519 $self->{DEBUG} && print "loading a tga file\n";
1522 if ( $type eq 'raw' ) {
1523 unless ( $input{xsize} && $input{ysize} ) {
1524 $self->_set_error('missing xsize or ysize parameter for raw');
1528 my $interleave = _first($input{raw_interleave}, $input{interleave});
1529 unless (defined $interleave) {
1530 my @caller = caller;
1531 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1534 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1535 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1537 $self->{IMG} = i_readraw_wiol( $IO,
1543 if ( !defined($self->{IMG}) ) {
1544 $self->{ERRSTR}=$self->_error_as_msg();
1547 $self->{DEBUG} && print "loading a raw file\n";
1553 sub register_reader {
1554 my ($class, %opts) = @_;
1557 or die "register_reader called with no type parameter\n";
1559 my $type = $opts{type};
1561 defined $opts{single} || defined $opts{multiple}
1562 or die "register_reader called with no single or multiple parameter\n";
1564 $readers{$type} = { };
1565 if ($opts{single}) {
1566 $readers{$type}{single} = $opts{single};
1568 if ($opts{multiple}) {
1569 $readers{$type}{multiple} = $opts{multiple};
1575 sub register_writer {
1576 my ($class, %opts) = @_;
1579 or die "register_writer called with no type parameter\n";
1581 my $type = $opts{type};
1583 defined $opts{single} || defined $opts{multiple}
1584 or die "register_writer called with no single or multiple parameter\n";
1586 $writers{$type} = { };
1587 if ($opts{single}) {
1588 $writers{$type}{single} = $opts{single};
1590 if ($opts{multiple}) {
1591 $writers{$type}{multiple} = $opts{multiple};
1602 grep($file_formats{$_}, keys %formats),
1603 qw(ico sgi), # formats not handled directly, but supplied with Imager
1614 grep($file_formats{$_}, keys %formats),
1615 qw(ico sgi), # formats not handled directly, but supplied with Imager
1622 my ($file, $error) = @_;
1624 if ($attempted_to_load{$file}) {
1625 if ($file_load_errors{$file}) {
1626 $$error = $file_load_errors{$file};
1634 local $SIG{__DIE__};
1636 ++$attempted_to_load{$file};
1644 my $work = $@ || "Unknown error";
1646 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1647 $work =~ s/\n/\\n/g;
1648 $work =~ s/\s*\.?\z/ loading $file/;
1649 $file_load_errors{$file} = $work;
1656 # probes for an Imager::File::whatever module
1657 sub _reader_autoload {
1660 return if $formats_low{$type} || $readers{$type};
1662 return unless $type =~ /^\w+$/;
1664 my $file = "Imager/File/\U$type\E.pm";
1667 my $loaded = _load_file($file, \$error);
1668 if (!$loaded && $error =~ /^Can't locate /) {
1669 my $filer = "Imager/File/\U$type\EReader.pm";
1670 $loaded = _load_file($filer, \$error);
1671 if ($error =~ /^Can't locate /) {
1672 $error = "Can't locate $file or $filer";
1676 $reader_load_errors{$type} = $error;
1680 # probes for an Imager::File::whatever module
1681 sub _writer_autoload {
1684 return if $formats_low{$type} || $writers{$type};
1686 return unless $type =~ /^\w+$/;
1688 my $file = "Imager/File/\U$type\E.pm";
1691 my $loaded = _load_file($file, \$error);
1692 if (!$loaded && $error =~ /^Can't locate /) {
1693 my $filew = "Imager/File/\U$type\EWriter.pm";
1694 $loaded = _load_file($filew, \$error);
1695 if ($error =~ /^Can't locate /) {
1696 $error = "Can't locate $file or $filew";
1700 $writer_load_errors{$type} = $error;
1704 sub _fix_gif_positions {
1705 my ($opts, $opt, $msg, @imgs) = @_;
1707 my $positions = $opts->{'gif_positions'};
1709 for my $pos (@$positions) {
1710 my ($x, $y) = @$pos;
1711 my $img = $imgs[$index++];
1712 $img->settag(name=>'gif_left', value=>$x);
1713 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1715 $$msg .= "replaced with the gif_left and gif_top tags";
1720 gif_each_palette=>'gif_local_map',
1721 interlace => 'gif_interlace',
1722 gif_delays => 'gif_delay',
1723 gif_positions => \&_fix_gif_positions,
1724 gif_loop_count => 'gif_loop',
1727 # options that should be converted to colors
1728 my %color_opts = map { $_ => 1 } qw/i_background/;
1731 my ($self, $opts, $prefix, @imgs) = @_;
1733 for my $opt (keys %$opts) {
1735 if ($obsolete_opts{$opt}) {
1736 my $new = $obsolete_opts{$opt};
1737 my $msg = "Obsolete option $opt ";
1739 $new->($opts, $opt, \$msg, @imgs);
1742 $msg .= "replaced with the $new tag ";
1745 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1746 warn $msg if $warn_obsolete && $^W;
1748 next unless $tagname =~ /^\Q$prefix/;
1749 my $value = $opts->{$opt};
1750 if ($color_opts{$opt}) {
1751 $value = _color($value);
1753 $self->_set_error($Imager::ERRSTR);
1758 if (UNIVERSAL::isa($value, "Imager::Color")) {
1759 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1760 for my $img (@imgs) {
1761 $img->settag(name=>$tagname, value=>$tag);
1764 elsif (ref($value) eq 'ARRAY') {
1765 for my $i (0..$#$value) {
1766 my $val = $value->[$i];
1768 if (UNIVERSAL::isa($val, "Imager::Color")) {
1769 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1771 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1774 $self->_set_error("Unknown reference type " . ref($value) .
1775 " supplied in array for $opt");
1781 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1786 $self->_set_error("Unknown reference type " . ref($value) .
1787 " supplied for $opt");
1792 # set it as a tag for every image
1793 for my $img (@imgs) {
1794 $img->settag(name=>$tagname, value=>$value);
1802 # Write an image to file
1805 my %input=(jpegquality=>75,
1815 $self->_valid_image("write")
1818 $self->_set_opts(\%input, "i_", $self)
1821 my $type = $input{'type'};
1822 if (!$type and $input{file}) {
1823 $type = $FORMATGUESS->($input{file});
1826 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1830 _writer_autoload($type);
1833 if ($writers{$type} && $writers{$type}{single}) {
1834 ($IO, $fh) = $self->_get_writer_io(\%input)
1837 $writers{$type}{single}->($self, $IO, %input, type => $type)
1841 if (!$formats_low{$type}) {
1842 my $write_types = join ', ', sort Imager->write_types();
1843 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1847 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1850 if ( $type eq 'pnm' ) {
1851 $self->_set_opts(\%input, "pnm_", $self)
1853 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1854 $self->{ERRSTR} = $self->_error_as_msg();
1857 $self->{DEBUG} && print "writing a pnm file\n";
1859 elsif ( $type eq 'raw' ) {
1860 $self->_set_opts(\%input, "raw_", $self)
1862 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1863 $self->{ERRSTR} = $self->_error_as_msg();
1866 $self->{DEBUG} && print "writing a raw file\n";
1868 elsif ( $type eq 'bmp' ) {
1869 $self->_set_opts(\%input, "bmp_", $self)
1871 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1872 $self->{ERRSTR} = $self->_error_as_msg;
1875 $self->{DEBUG} && print "writing a bmp file\n";
1877 elsif ( $type eq 'tga' ) {
1878 $self->_set_opts(\%input, "tga_", $self)
1881 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1882 $self->{ERRSTR}=$self->_error_as_msg();
1885 $self->{DEBUG} && print "writing a tga file\n";
1889 if (exists $input{'data'}) {
1890 my $data = io_slurp($IO);
1892 $self->{ERRSTR}='Could not slurp from buffer';
1895 ${$input{data}} = $data;
1901 my ($class, $opts, @images) = @_;
1903 my $type = $opts->{type};
1905 if (!$type && $opts->{'file'}) {
1906 $type = $FORMATGUESS->($opts->{'file'});
1909 $class->_set_error('type parameter missing and not possible to guess from extension');
1912 # translate to ImgRaw
1914 for my $img (@images) {
1915 unless ($img->_valid_image("write_multi")) {
1916 $class->_set_error($img->errstr . " (image $index)");
1921 $class->_set_opts($opts, "i_", @images)
1923 my @work = map $_->{IMG}, @images;
1925 _writer_autoload($type);
1928 if ($writers{$type} && $writers{$type}{multiple}) {
1929 ($IO, $file) = $class->_get_writer_io($opts, $type)
1932 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1936 if (!$formats{$type}) {
1937 my $write_types = join ', ', sort Imager->write_types();
1938 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1942 ($IO, $file) = $class->_get_writer_io($opts, $type)
1945 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1949 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1954 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1960 if (exists $opts->{'data'}) {
1961 my $data = io_slurp($IO);
1963 Imager->_set_error('Could not slurp from buffer');
1966 ${$opts->{data}} = $data;
1971 # read multiple images from a file
1973 my ($class, %opts) = @_;
1975 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1978 my $type = $opts{'type'};
1980 $type = i_test_format_probe($IO, -1);
1983 if ($opts{file} && !$type) {
1985 $type = $FORMATGUESS->($opts{file});
1989 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1990 $opts{file} and $msg .= " or file name";
1991 Imager->_set_error($msg);
1995 _reader_autoload($type);
1997 if ($readers{$type} && $readers{$type}{multiple}) {
1998 return $readers{$type}{multiple}->($IO, %opts);
2001 unless ($formats{$type}) {
2002 my $read_types = join ', ', sort Imager->read_types();
2003 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2008 if ($type eq 'pnm') {
2009 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2012 my $img = Imager->new;
2013 if ($img->read(%opts, io => $IO, type => $type)) {
2016 Imager->_set_error($img->errstr);
2021 $ERRSTR = _error_as_msg();
2025 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2029 # Destroy an Imager object
2033 # delete $instances{$self};
2034 if (defined($self->{IMG})) {
2035 # the following is now handled by the XS DESTROY method for
2036 # Imager::ImgRaw object
2037 # Re-enabling this will break virtual images
2038 # tested for in t/t020masked.t
2039 # i_img_destroy($self->{IMG});
2040 undef($self->{IMG});
2042 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2046 # Perform an inplace filter of an image
2047 # that is the image will be overwritten with the data
2054 $self->_valid_image("filter")
2057 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2059 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2060 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2063 if ($filters{$input{'type'}}{names}) {
2064 my $names = $filters{$input{'type'}}{names};
2065 for my $name (keys %$names) {
2066 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2067 $input{$name} = $names->{$name}{$input{$name}};
2071 if (defined($filters{$input{'type'}}{defaults})) {
2072 %hsh=( image => $self->{IMG},
2074 %{$filters{$input{'type'}}{defaults}},
2077 %hsh=( image => $self->{IMG},
2082 my @cs=@{$filters{$input{'type'}}{callseq}};
2085 if (!defined($hsh{$_})) {
2086 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2091 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2092 &{$filters{$input{'type'}}{callsub}}(%hsh);
2095 chomp($self->{ERRSTR} = $@);
2101 $self->{DEBUG} && print "callseq is: @cs\n";
2102 $self->{DEBUG} && print "matching callseq is: @b\n";
2107 sub register_filter {
2109 my %hsh = ( defaults => {}, @_ );
2112 or die "register_filter() with no type\n";
2113 defined $hsh{callsub}
2114 or die "register_filter() with no callsub\n";
2115 defined $hsh{callseq}
2116 or die "register_filter() with no callseq\n";
2118 exists $filters{$hsh{type}}
2121 $filters{$hsh{type}} = \%hsh;
2126 sub scale_calculate {
2129 my %opts = ('type'=>'max', @_);
2131 # none of these should be references
2132 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2133 if (defined $opts{$name} && ref $opts{$name}) {
2134 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2139 my ($x_scale, $y_scale);
2140 my $width = $opts{width};
2141 my $height = $opts{height};
2143 defined $width or $width = $self->getwidth;
2144 defined $height or $height = $self->getheight;
2147 unless (defined $width && defined $height) {
2148 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2153 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2154 $x_scale = $opts{'xscalefactor'};
2155 $y_scale = $opts{'yscalefactor'};
2157 elsif ($opts{'xscalefactor'}) {
2158 $x_scale = $opts{'xscalefactor'};
2159 $y_scale = $opts{'scalefactor'} || $x_scale;
2161 elsif ($opts{'yscalefactor'}) {
2162 $y_scale = $opts{'yscalefactor'};
2163 $x_scale = $opts{'scalefactor'} || $y_scale;
2166 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2169 # work out the scaling
2170 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2171 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2172 $opts{ypixels} / $height );
2173 if ($opts{'type'} eq 'min') {
2174 $x_scale = $y_scale = _min($xpix,$ypix);
2176 elsif ($opts{'type'} eq 'max') {
2177 $x_scale = $y_scale = _max($xpix,$ypix);
2179 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2184 $self->_set_error('invalid value for type parameter');
2187 } elsif ($opts{xpixels}) {
2188 $x_scale = $y_scale = $opts{xpixels} / $width;
2190 elsif ($opts{ypixels}) {
2191 $x_scale = $y_scale = $opts{ypixels}/$height;
2193 elsif ($opts{constrain} && ref $opts{constrain}
2194 && $opts{constrain}->can('constrain')) {
2195 # we've been passed an Image::Math::Constrain object or something
2196 # that looks like one
2198 (undef, undef, $scalefactor)
2199 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2200 unless ($scalefactor) {
2201 $self->_set_error('constrain method failed on constrain parameter');
2204 $x_scale = $y_scale = $scalefactor;
2207 my $new_width = int($x_scale * $width + 0.5);
2208 $new_width > 0 or $new_width = 1;
2209 my $new_height = int($y_scale * $height + 0.5);
2210 $new_height > 0 or $new_height = 1;
2212 return ($x_scale, $y_scale, $new_width, $new_height);
2216 # Scale an image to requested size and return the scaled version
2220 my %opts = (qtype=>'normal' ,@_);
2221 my $img = Imager->new();
2222 my $tmp = Imager->new();
2224 unless (defined wantarray) {
2225 my @caller = caller;
2226 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2230 $self->_valid_image("scale")
2233 my ($x_scale, $y_scale, $new_width, $new_height) =
2234 $self->scale_calculate(%opts)
2237 if ($opts{qtype} eq 'normal') {
2238 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2239 if ( !defined($tmp->{IMG}) ) {
2240 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2243 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2244 if ( !defined($img->{IMG}) ) {
2245 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2251 elsif ($opts{'qtype'} eq 'preview') {
2252 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2253 if ( !defined($img->{IMG}) ) {
2254 $self->{ERRSTR}='unable to scale image';
2259 elsif ($opts{'qtype'} eq 'mixing') {
2260 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2261 unless ($img->{IMG}) {
2262 $self->_set_error(Imager->_error_as_msg);
2268 $self->_set_error('invalid value for qtype parameter');
2273 # Scales only along the X axis
2277 my %opts = ( scalefactor=>0.5, @_ );
2279 unless (defined wantarray) {
2280 my @caller = caller;
2281 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2285 $self->_valid_image("scaleX")
2288 my $img = Imager->new();
2290 my $scalefactor = $opts{scalefactor};
2292 if ($opts{pixels}) {
2293 $scalefactor = $opts{pixels} / $self->getwidth();
2296 unless ($self->{IMG}) {
2297 $self->{ERRSTR}='empty input image';
2301 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2303 if ( !defined($img->{IMG}) ) {
2304 $self->{ERRSTR} = 'unable to scale image';
2311 # Scales only along the Y axis
2315 my %opts = ( scalefactor => 0.5, @_ );
2317 unless (defined wantarray) {
2318 my @caller = caller;
2319 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2323 $self->_valid_image("scaleY")
2326 my $img = Imager->new();
2328 my $scalefactor = $opts{scalefactor};
2330 if ($opts{pixels}) {
2331 $scalefactor = $opts{pixels} / $self->getheight();
2334 unless ($self->{IMG}) {
2335 $self->{ERRSTR} = 'empty input image';
2338 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2340 if ( !defined($img->{IMG}) ) {
2341 $self->{ERRSTR} = 'unable to scale image';
2348 # Transform returns a spatial transformation of the input image
2349 # this moves pixels to a new location in the returned image.
2350 # NOTE - should make a utility function to check transforms for
2356 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2358 # print Dumper(\%opts);
2361 $self->_valid_image("transform")
2364 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2366 eval ("use Affix::Infix2Postfix;");
2369 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2372 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2373 {op=>'-',trans=>'Sub'},
2374 {op=>'*',trans=>'Mult'},
2375 {op=>'/',trans=>'Div'},
2376 {op=>'-','type'=>'unary',trans=>'u-'},
2378 {op=>'func','type'=>'unary'}],
2379 'grouping'=>[qw( \( \) )],
2380 'func'=>[qw( sin cos )],
2385 @xt=$I2P->translate($opts{'xexpr'});
2386 @yt=$I2P->translate($opts{'yexpr'});
2388 $numre=$I2P->{'numre'};
2391 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2392 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2393 @{$opts{'parm'}}=@pt;
2396 # print Dumper(\%opts);
2398 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2399 $self->{ERRSTR}='transform: no xopcodes given.';
2403 @op=@{$opts{'xopcodes'}};
2405 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2406 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2409 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2415 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2416 $self->{ERRSTR}='transform: no yopcodes given.';
2420 @op=@{$opts{'yopcodes'}};
2422 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2423 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2426 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2431 if ( !exists $opts{'parm'}) {
2432 $self->{ERRSTR}='transform: no parameter arg given.';
2436 # print Dumper(\@ropx);
2437 # print Dumper(\@ropy);
2438 # print Dumper(\@ropy);
2440 my $img = Imager->new();
2441 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2442 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2448 my ($opts, @imgs) = @_;
2450 require "Imager/Expr.pm";
2452 $opts->{variables} = [ qw(x y) ];
2453 my ($width, $height) = @{$opts}{qw(width height)};
2456 for my $img (@imgs) {
2457 unless ($img->_valid_image("transform2")) {
2458 Imager->_set_error($img->errstr . " (input image $index)");
2464 $width ||= $imgs[0]->getwidth();
2465 $height ||= $imgs[0]->getheight();
2467 for my $img (@imgs) {
2468 $opts->{constants}{"w$img_num"} = $img->getwidth();
2469 $opts->{constants}{"h$img_num"} = $img->getheight();
2470 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2471 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2476 $opts->{constants}{w} = $width;
2477 $opts->{constants}{cx} = $width/2;
2480 $Imager::ERRSTR = "No width supplied";
2484 $opts->{constants}{h} = $height;
2485 $opts->{constants}{cy} = $height/2;
2488 $Imager::ERRSTR = "No height supplied";
2491 my $code = Imager::Expr->new($opts);
2493 $Imager::ERRSTR = Imager::Expr::error();
2496 my $channels = $opts->{channels} || 3;
2497 unless ($channels >= 1 && $channels <= 4) {
2498 return Imager->_set_error("channels must be an integer between 1 and 4");
2501 my $img = Imager->new();
2502 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2503 $channels, $code->code(),
2504 $code->nregs(), $code->cregs(),
2505 [ map { $_->{IMG} } @imgs ]);
2506 if (!defined $img->{IMG}) {
2507 $Imager::ERRSTR = Imager->_error_as_msg();
2518 $self->_valid_image("rubthrough")
2521 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2522 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2526 %opts = (src_minx => 0,
2528 src_maxx => $opts{src}->getwidth(),
2529 src_maxy => $opts{src}->getheight(),
2533 defined $tx or $tx = $opts{left};
2534 defined $tx or $tx = 0;
2537 defined $ty or $ty = $opts{top};
2538 defined $ty or $ty = 0;
2540 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2541 $opts{src_minx}, $opts{src_miny},
2542 $opts{src_maxx}, $opts{src_maxy})) {
2543 $self->_set_error($self->_error_as_msg());
2560 $self->_valid_image("compose")
2563 unless ($opts{src}) {
2564 $self->_set_error("compose: src parameter missing");
2568 unless ($opts{src}->_valid_image("compose")) {
2569 $self->_set_error($opts{src}->errstr . " (for src)");
2572 my $src = $opts{src};
2574 my $left = $opts{left};
2575 defined $left or $left = $opts{tx};
2576 defined $left or $left = 0;
2578 my $top = $opts{top};
2579 defined $top or $top = $opts{ty};
2580 defined $top or $top = 0;
2582 my $src_left = $opts{src_left};
2583 defined $src_left or $src_left = $opts{src_minx};
2584 defined $src_left or $src_left = 0;
2586 my $src_top = $opts{src_top};
2587 defined $src_top or $src_top = $opts{src_miny};
2588 defined $src_top or $src_top = 0;
2590 my $width = $opts{width};
2591 if (!defined $width && defined $opts{src_maxx}) {
2592 $width = $opts{src_maxx} - $src_left;
2594 defined $width or $width = $src->getwidth() - $src_left;
2596 my $height = $opts{height};
2597 if (!defined $height && defined $opts{src_maxy}) {
2598 $height = $opts{src_maxy} - $src_top;
2600 defined $height or $height = $src->getheight() - $src_top;
2602 my $combine = $self->_combine($opts{combine}, 'normal');
2605 unless ($opts{mask}->_valid_image("compose")) {
2606 $self->_set_error($opts{mask}->errstr . " (for mask)");
2610 my $mask_left = $opts{mask_left};
2611 defined $mask_left or $mask_left = $opts{mask_minx};
2612 defined $mask_left or $mask_left = 0;
2614 my $mask_top = $opts{mask_top};
2615 defined $mask_top or $mask_top = $opts{mask_miny};
2616 defined $mask_top or $mask_top = 0;
2618 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2619 $left, $top, $src_left, $src_top,
2620 $mask_left, $mask_top, $width, $height,
2621 $combine, $opts{opacity})) {
2622 $self->_set_error(Imager->_error_as_msg);
2627 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2628 $width, $height, $combine, $opts{opacity})) {
2629 $self->_set_error(Imager->_error_as_msg);
2641 $self->_valid_image("flip")
2644 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2646 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2647 $dir = $xlate{$opts{'dir'}};
2648 return $self if i_flipxy($self->{IMG}, $dir);
2656 unless (defined wantarray) {
2657 my @caller = caller;
2658 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2662 $self->_valid_image("rotate")
2665 if (defined $opts{right}) {
2666 my $degrees = $opts{right};
2668 $degrees += 360 * int(((-$degrees)+360)/360);
2670 $degrees = $degrees % 360;
2671 if ($degrees == 0) {
2672 return $self->copy();
2674 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2675 my $result = Imager->new();
2676 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2680 $self->{ERRSTR} = $self->_error_as_msg();
2685 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2689 elsif (defined $opts{radians} || defined $opts{degrees}) {
2690 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2692 my $back = $opts{back};
2693 my $result = Imager->new;
2695 $back = _color($back);
2697 $self->_set_error(Imager->errstr);
2701 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2704 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2706 if ($result->{IMG}) {
2710 $self->{ERRSTR} = $self->_error_as_msg();
2715 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2720 sub matrix_transform {
2724 $self->_valid_image("matrix_transform")
2727 unless (defined wantarray) {
2728 my @caller = caller;
2729 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2733 if ($opts{matrix}) {
2734 my $xsize = $opts{xsize} || $self->getwidth;
2735 my $ysize = $opts{ysize} || $self->getheight;
2737 my $result = Imager->new;
2739 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2740 $opts{matrix}, $opts{back})
2744 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2752 $self->{ERRSTR} = "matrix parameter required";
2758 *yatf = \&matrix_transform;
2760 # These two are supported for legacy code only
2763 return Imager::Color->new(@_);
2767 return Imager::Color::set(@_);
2770 # Draws a box between the specified corner points.
2773 my $raw = $self->{IMG};
2775 $self->_valid_image("box")
2780 my ($xmin, $ymin, $xmax, $ymax);
2781 if (exists $opts{'box'}) {
2782 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2783 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2784 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2785 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2788 defined($xmin = $opts{xmin}) or $xmin = 0;
2789 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2790 defined($ymin = $opts{ymin}) or $ymin = 0;
2791 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2794 if ($opts{filled}) {
2795 my $color = $opts{'color'};
2797 if (defined $color) {
2798 unless (_is_color_object($color)) {
2799 $color = _color($color);
2801 $self->{ERRSTR} = $Imager::ERRSTR;
2807 $color = i_color_new(255,255,255,255);
2810 if ($color->isa("Imager::Color")) {
2811 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2814 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2817 elsif ($opts{fill}) {
2818 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2819 # assume it's a hash ref
2820 require 'Imager/Fill.pm';
2821 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2822 $self->{ERRSTR} = $Imager::ERRSTR;
2826 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2829 my $color = $opts{'color'};
2830 if (defined $color) {
2831 unless (_is_color_object($color)) {
2832 $color = _color($color);
2834 $self->{ERRSTR} = $Imager::ERRSTR;
2840 $color = i_color_new(255, 255, 255, 255);
2843 $self->{ERRSTR} = $Imager::ERRSTR;
2846 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2855 $self->_valid_image("arc")
2858 my $dflcl= [ 255, 255, 255, 255];
2863 'r'=>_min($self->getwidth(),$self->getheight())/3,
2864 'x'=>$self->getwidth()/2,
2865 'y'=>$self->getheight()/2,
2872 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2873 # assume it's a hash ref
2874 require 'Imager/Fill.pm';
2875 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2876 $self->{ERRSTR} = $Imager::ERRSTR;
2880 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2881 $opts{'d2'}, $opts{fill}{fill});
2883 elsif ($opts{filled}) {
2884 my $color = _color($opts{'color'});
2886 $self->{ERRSTR} = $Imager::ERRSTR;
2889 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2890 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2894 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2895 $opts{'d1'}, $opts{'d2'}, $color);
2899 my $color = _color($opts{'color'});
2900 if ($opts{d2} - $opts{d1} >= 360) {
2901 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2904 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2910 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2911 # assume it's a hash ref
2912 require 'Imager/Fill.pm';
2913 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2914 $self->{ERRSTR} = $Imager::ERRSTR;
2918 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2919 $opts{'d2'}, $opts{fill}{fill});
2922 my $color = _color($opts{'color'});
2924 $self->{ERRSTR} = $Imager::ERRSTR;
2927 if ($opts{filled}) {
2928 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2929 $opts{'d1'}, $opts{'d2'}, $color);
2932 if ($opts{d1} == 0 && $opts{d2} == 361) {
2933 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2936 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2942 $self->_set_error($self->_error_as_msg);
2949 # Draws a line from one point to the other
2950 # the endpoint is set if the endp parameter is set which it is by default.
2951 # to turn of the endpoint being set use endp=>0 when calling line.
2955 my $dflcl=i_color_new(0,0,0,0);
2956 my %opts=(color=>$dflcl,
2960 $self->_valid_image("line")
2963 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2964 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2966 my $color = _color($opts{'color'});
2968 $self->{ERRSTR} = $Imager::ERRSTR;
2972 $opts{antialias} = $opts{aa} if defined $opts{aa};
2973 if ($opts{antialias}) {
2974 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2975 $color, $opts{endp});
2977 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2978 $color, $opts{endp});
2983 # Draws a line between an ordered set of points - It more or less just transforms this
2984 # into a list of lines.
2988 my ($pt,$ls,@points);
2989 my $dflcl=i_color_new(0,0,0,0);
2990 my %opts=(color=>$dflcl,@_);
2992 $self->_valid_image("polyline")
2995 if (exists($opts{points})) { @points=@{$opts{points}}; }
2996 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2997 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3000 # print Dumper(\@points);
3002 my $color = _color($opts{'color'});
3004 $self->{ERRSTR} = $Imager::ERRSTR;
3007 $opts{antialias} = $opts{aa} if defined $opts{aa};
3008 if ($opts{antialias}) {
3011 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3018 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3028 my ($pt,$ls,@points);
3029 my $dflcl = i_color_new(0,0,0,0);
3030 my %opts = (color=>$dflcl, @_);
3032 $self->_valid_image("polygon")
3035 if (exists($opts{points})) {
3036 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3037 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3040 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3041 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3044 if ($opts{'fill'}) {
3045 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3046 # assume it's a hash ref
3047 require 'Imager/Fill.pm';
3048 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3049 $self->{ERRSTR} = $Imager::ERRSTR;
3053 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
3054 $opts{'fill'}{'fill'});
3057 my $color = _color($opts{'color'});
3059 $self->{ERRSTR} = $Imager::ERRSTR;
3062 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3069 # this the multipoint bezier curve
3070 # this is here more for testing that actual usage since
3071 # this is not a good algorithm. Usually the curve would be
3072 # broken into smaller segments and each done individually.
3076 my ($pt,$ls,@points);
3077 my $dflcl=i_color_new(0,0,0,0);
3078 my %opts=(color=>$dflcl,@_);
3080 $self->_valid_image("polybezier")
3083 if (exists $opts{points}) {
3084 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3085 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3088 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3089 $self->{ERRSTR}='Missing or invalid points.';
3093 my $color = _color($opts{'color'});
3095 $self->{ERRSTR} = $Imager::ERRSTR;
3098 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3104 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3107 $self->_valid_image("flood_fill")
3110 unless (exists $opts{'x'} && exists $opts{'y'}) {
3111 $self->{ERRSTR} = "missing seed x and y parameters";
3115 if ($opts{border}) {
3116 my $border = _color($opts{border});
3118 $self->_set_error($Imager::ERRSTR);
3122 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3123 # assume it's a hash ref
3124 require Imager::Fill;
3125 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3126 $self->{ERRSTR} = $Imager::ERRSTR;
3130 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3131 $opts{fill}{fill}, $border);
3134 my $color = _color($opts{'color'});
3136 $self->{ERRSTR} = $Imager::ERRSTR;
3139 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3146 $self->{ERRSTR} = $self->_error_as_msg();
3152 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3153 # assume it's a hash ref
3154 require 'Imager/Fill.pm';
3155 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3156 $self->{ERRSTR} = $Imager::ERRSTR;
3160 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3163 my $color = _color($opts{'color'});
3165 $self->{ERRSTR} = $Imager::ERRSTR;
3168 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3174 $self->{ERRSTR} = $self->_error_as_msg();
3181 my ($self, %opts) = @_;
3183 $self->_valid_image("setpixel")
3186 my $color = $opts{color};
3187 unless (defined $color) {
3188 $color = $self->{fg};
3189 defined $color or $color = NC(255, 255, 255);
3192 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3193 unless ($color = _color($color, 'setpixel')) {
3194 $self->_set_error("setpixel: " . Imager->errstr);
3199 unless (exists $opts{'x'} && exists $opts{'y'}) {
3200 $self->_set_error('setpixel: missing x or y parameter');
3206 if (ref $x || ref $y) {
3207 $x = ref $x ? $x : [ $x ];
3208 $y = ref $y ? $y : [ $y ];
3210 $self->_set_error("setpixel: x is a reference to an empty array");
3214 $self->_set_error("setpixel: y is a reference to an empty array");
3218 # make both the same length, replicating the last element
3220 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3223 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3227 if ($color->isa('Imager::Color')) {
3228 for my $i (0..$#$x) {
3229 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3234 for my $i (0..$#$x) {
3235 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3243 if ($color->isa('Imager::Color')) {
3244 i_ppix($self->{IMG}, $x, $y, $color)
3248 i_ppixf($self->{IMG}, $x, $y, $color)
3259 my %opts = ( "type"=>'8bit', @_);
3261 $self->_valid_image("getpixel")
3264 unless (exists $opts{'x'} && exists $opts{'y'}) {
3265 $self->_set_error('getpixel: missing x or y parameter');
3271 my $type = $opts{'type'};
3272 if (ref $x || ref $y) {
3273 $x = ref $x ? $x : [ $x ];
3274 $y = ref $y ? $y : [ $y ];
3276 $self->_set_error("getpixel: x is a reference to an empty array");
3280 $self->_set_error("getpixel: y is a reference to an empty array");
3284 # make both the same length, replicating the last element
3286 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3289 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3293 if ($type eq '8bit') {
3294 for my $i (0..$#$x) {
3295 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3298 elsif ($type eq 'float' || $type eq 'double') {
3299 for my $i (0..$#$x) {
3300 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3304 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3307 return wantarray ? @result : \@result;
3310 if ($type eq '8bit') {
3311 return i_get_pixel($self->{IMG}, $x, $y);
3313 elsif ($type eq 'float' || $type eq 'double') {
3314 return i_gpixf($self->{IMG}, $x, $y);
3317 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3325 my %opts = ( type => '8bit', x=>0, @_);
3327 $self->_valid_image("getscanline")
3330 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3332 unless (defined $opts{'y'}) {
3333 $self->_set_error("missing y parameter");
3337 if ($opts{type} eq '8bit') {
3338 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3341 elsif ($opts{type} eq 'float') {
3342 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3345 elsif ($opts{type} eq 'index') {
3346 unless (i_img_type($self->{IMG})) {
3347 $self->_set_error("type => index only valid on paletted images");
3350 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3354 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3361 my %opts = ( x=>0, @_);
3363 $self->_valid_image("setscanline")
3366 unless (defined $opts{'y'}) {
3367 $self->_set_error("missing y parameter");
3372 if (ref $opts{pixels} && @{$opts{pixels}}) {
3373 # try to guess the type
3374 if ($opts{pixels}[0]->isa('Imager::Color')) {
3375 $opts{type} = '8bit';
3377 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3378 $opts{type} = 'float';
3381 $self->_set_error("missing type parameter and could not guess from pixels");
3387 $opts{type} = '8bit';
3391 if ($opts{type} eq '8bit') {
3392 if (ref $opts{pixels}) {
3393 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3396 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3399 elsif ($opts{type} eq 'float') {
3400 if (ref $opts{pixels}) {
3401 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3404 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3407 elsif ($opts{type} eq 'index') {
3408 if (ref $opts{pixels}) {
3409 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3412 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3416 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3423 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3425 $self->_valid_image("getsamples")
3428 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3430 unless (defined $opts{'y'}) {
3431 $self->_set_error("missing y parameter");
3435 if ($opts{target}) {
3436 my $target = $opts{target};
3437 my $offset = $opts{offset};
3438 if ($opts{type} eq '8bit') {
3439 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3440 $opts{y}, $opts{channels})
3442 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3443 return scalar(@samples);
3445 elsif ($opts{type} eq 'float') {
3446 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3447 $opts{y}, $opts{channels});
3448 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3449 return scalar(@samples);
3451 elsif ($opts{type} =~ /^(\d+)bit$/) {
3455 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3456 $opts{y}, $bits, $target,
3457 $offset, $opts{channels});
3458 unless (defined $count) {
3459 $self->_set_error(Imager->_error_as_msg);
3466 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3471 if ($opts{type} eq '8bit') {
3472 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3473 $opts{y}, $opts{channels});
3475 elsif ($opts{type} eq 'float') {
3476 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3477 $opts{y}, $opts{channels});
3479 elsif ($opts{type} =~ /^(\d+)bit$/) {
3483 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3484 $opts{y}, $bits, \@data, 0, $opts{channels})
3489 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3498 $self->_valid_image("setsamples")
3501 my %opts = ( x => 0, offset => 0 );
3503 # avoid duplicating the data parameter, it may be a large scalar
3505 while ($i < @_ -1) {
3506 if ($_[$i] eq 'data') {
3510 $opts{$_[$i]} = $_[$i+1];
3516 unless(defined $data_index) {
3517 $self->_set_error('setsamples: data parameter missing');
3520 unless (defined $_[$data_index]) {
3521 $self->_set_error('setsamples: data parameter not defined');
3525 my $type = $opts{type};
3526 defined $type or $type = '8bit';
3528 my $width = defined $opts{width} ? $opts{width}
3529 : $self->getwidth() - $opts{x};
3532 if ($type eq '8bit') {
3533 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3534 $_[$data_index], $opts{offset}, $width);
3536 elsif ($type eq 'float') {
3537 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3538 $_[$data_index], $opts{offset}, $width);
3540 elsif ($type =~ /^([0-9]+)bit$/) {
3543 unless (ref $_[$data_index]) {
3544 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3548 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3549 $opts{channels}, $_[$data_index], $opts{offset},
3553 $self->_set_error('setsamples: type parameter invalid');
3557 unless (defined $count) {
3558 $self->_set_error(Imager->_error_as_msg);
3565 # make an identity matrix of the given size
3569 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3570 for my $c (0 .. ($size-1)) {
3571 $matrix->[$c][$c] = 1;
3576 # general function to convert an image
3578 my ($self, %opts) = @_;
3581 $self->_valid_image("convert")
3584 unless (defined wantarray) {
3585 my @caller = caller;
3586 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3590 # the user can either specify a matrix or preset
3591 # the matrix overrides the preset
3592 if (!exists($opts{matrix})) {
3593 unless (exists($opts{preset})) {
3594 $self->{ERRSTR} = "convert() needs a matrix or preset";
3598 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3599 # convert to greyscale, keeping the alpha channel if any
3600 if ($self->getchannels == 3) {
3601 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3603 elsif ($self->getchannels == 4) {
3604 # preserve the alpha channel
3605 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3610 $matrix = _identity($self->getchannels);
3613 elsif ($opts{preset} eq 'noalpha') {
3614 # strip the alpha channel
3615 if ($self->getchannels == 2 or $self->getchannels == 4) {
3616 $matrix = _identity($self->getchannels);
3617 pop(@$matrix); # lose the alpha entry
3620 $matrix = _identity($self->getchannels);
3623 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3625 $matrix = [ [ 1 ] ];
3627 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3628 $matrix = [ [ 0, 1 ] ];
3630 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3631 $matrix = [ [ 0, 0, 1 ] ];
3633 elsif ($opts{preset} eq 'alpha') {
3634 if ($self->getchannels == 2 or $self->getchannels == 4) {
3635 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3638 # the alpha is just 1 <shrug>
3639 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3642 elsif ($opts{preset} eq 'rgb') {
3643 if ($self->getchannels == 1) {
3644 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3646 elsif ($self->getchannels == 2) {
3647 # preserve the alpha channel
3648 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3651 $matrix = _identity($self->getchannels);
3654 elsif ($opts{preset} eq 'addalpha') {
3655 if ($self->getchannels == 1) {
3656 $matrix = _identity(2);
3658 elsif ($self->getchannels == 3) {
3659 $matrix = _identity(4);
3662 $matrix = _identity($self->getchannels);
3666 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3672 $matrix = $opts{matrix};
3675 my $new = Imager->new;
3676 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3677 unless ($new->{IMG}) {
3678 # most likely a bad matrix
3679 i_push_error(0, "convert");
3680 $self->{ERRSTR} = _error_as_msg();
3686 # combine channels from multiple input images, a class method
3688 my ($class, %opts) = @_;
3690 my $src = delete $opts{src};
3692 $class->_set_error("src parameter missing");
3697 for my $img (@$src) {
3698 unless (eval { $img->isa("Imager") }) {
3699 $class->_set_error("src must contain image objects");
3702 unless ($img->_valid_image("combine")) {
3703 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3706 push @imgs, $img->{IMG};
3709 if (my $channels = delete $opts{channels}) {
3710 $result = i_combine(\@imgs, $channels);
3713 $result = i_combine(\@imgs);
3716 $class->_set_error($class->_error_as_msg);
3720 my $img = $class->new;
3721 $img->{IMG} = $result;
3727 # general function to map an image through lookup tables
3730 my ($self, %opts) = @_;
3731 my @chlist = qw( red green blue alpha );
3733 $self->_valid_image("map")
3736 if (!exists($opts{'maps'})) {
3737 # make maps from channel maps
3739 for $chnum (0..$#chlist) {
3740 if (exists $opts{$chlist[$chnum]}) {
3741 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3742 } elsif (exists $opts{'all'}) {
3743 $opts{'maps'}[$chnum] = $opts{'all'};
3747 if ($opts{'maps'} and $self->{IMG}) {
3748 i_map($self->{IMG}, $opts{'maps'} );
3754 my ($self, %opts) = @_;
3756 $self->_valid_image("difference")
3759 defined $opts{mindist} or $opts{mindist} = 0;
3761 defined $opts{other}
3762 or return $self->_set_error("No 'other' parameter supplied");
3763 unless ($opts{other}->_valid_image("difference")) {
3764 $self->_set_error($opts{other}->errstr . " (other image)");
3768 my $result = Imager->new;
3769 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3771 or return $self->_set_error($self->_error_as_msg());
3776 # destructive border - image is shrunk by one pixel all around
3779 my ($self,%opts)=@_;
3780 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3781 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3785 # Get the width of an image
3790 $self->_valid_image("getwidth")
3793 return i_img_get_width($self->{IMG});
3796 # Get the height of an image
3801 $self->_valid_image("getheight")
3804 return i_img_get_height($self->{IMG});
3807 # Get number of channels in an image
3812 $self->_valid_image("getchannels")
3815 return i_img_getchannels($self->{IMG});
3823 $self->_valid_image("getmask")
3826 return i_img_getmask($self->{IMG});
3835 $self->_valid_image("setmask")
3838 unless (defined $opts{mask}) {
3839 $self->_set_error("mask parameter required");
3843 i_img_setmask( $self->{IMG} , $opts{mask} );
3848 # Get number of colors in an image
3852 my %opts=('maxcolors'=>2**30,@_);
3854 $self->_valid_image("getcolorcount")
3857 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3858 return ($rc==-1? undef : $rc);
3861 # Returns a reference to a hash. The keys are colour named (packed) and the
3862 # values are the number of pixels in this colour.
3863 sub getcolorusagehash {
3866 $self->_valid_image("getcolorusagehash")
3869 my %opts = ( maxcolors => 2**30, @_ );
3870 my $max_colors = $opts{maxcolors};
3871 unless (defined $max_colors && $max_colors > 0) {
3872 $self->_set_error('maxcolors must be a positive integer');
3876 my $channels= $self->getchannels;
3877 # We don't want to look at the alpha channel, because some gifs using it
3878 # doesn't define it for every colour (but only for some)
3879 $channels -= 1 if $channels == 2 or $channels == 4;
3881 my $height = $self->getheight;
3882 for my $y (0 .. $height - 1) {
3883 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3884 while (length $colors) {
3885 $color_use{ substr($colors, 0, $channels, '') }++;
3887 keys %color_use > $max_colors
3893 # This will return a ordered array of the colour usage. Kind of the sorted
3894 # version of the values of the hash returned by getcolorusagehash.
3895 # You might want to add safety checks and change the names, etc...
3899 $self->_valid_image("getcolorusage")
3902 my %opts = ( maxcolors => 2**30, @_ );
3903 my $max_colors = $opts{maxcolors};
3904 unless (defined $max_colors && $max_colors > 0) {
3905 $self->_set_error('maxcolors must be a positive integer');
3909 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3912 # draw string to an image
3917 $self->_valid_image("string")
3920 my %input=('x'=>0, 'y'=>0, @_);
3921 defined($input{string}) or $input{string} = $input{text};
3923 unless(defined $input{string}) {
3924 $self->{ERRSTR}="missing required parameter 'string'";
3928 unless($input{font}) {
3929 $self->{ERRSTR}="missing required parameter 'font'";
3933 unless ($input{font}->draw(image=>$self, %input)) {
3945 $self->_valid_image("align_string")
3954 my %input=('x'=>0, 'y'=>0, @_);
3955 defined $input{string}
3956 or $input{string} = $input{text};
3958 unless(exists $input{string}) {
3959 $self->_set_error("missing required parameter 'string'");
3963 unless($input{font}) {
3964 $self->_set_error("missing required parameter 'font'");
3969 unless (@result = $input{font}->align(image=>$img, %input)) {
3973 return wantarray ? @result : $result[0];
3976 my @file_limit_names = qw/width height bytes/;
3978 sub set_file_limits {
3985 @values{@file_limit_names} = (0) x @file_limit_names;
3988 @values{@file_limit_names} = i_get_image_file_limits();
3991 for my $key (keys %values) {
3992 defined $opts{$key} and $values{$key} = $opts{$key};
3995 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3998 sub get_file_limits {
3999 i_get_image_file_limits();
4002 my @check_args = qw(width height channels sample_size);
4004 sub check_file_limits {
4014 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4015 $opts{sample_size} = length(pack("d", 0));
4018 for my $name (@check_args) {
4019 unless (defined $opts{$name}) {
4020 $class->_set_error("check_file_limits: $name must be defined");
4023 unless ($opts{$name} == int($opts{$name})) {
4024 $class->_set_error("check_file_limits: $name must be a positive integer");
4029 my $result = i_int_check_image_file_limits(@opts{@check_args});
4031 $class->_set_error($class->_error_as_msg());
4037 # Shortcuts that can be exported
4039 sub newcolor { Imager::Color->new(@_); }
4040 sub newfont { Imager::Font->new(@_); }
4042 require Imager::Color::Float;
4043 return Imager::Color::Float->new(@_);
4046 *NC=*newcolour=*newcolor;
4053 #### Utility routines
4056 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4060 my ($self, $msg) = @_;
4063 $self->{ERRSTR} = $msg;
4071 # Default guess for the type of an image from extension
4073 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4077 ( map { $_ => $_ } @simple_types ),
4083 pnm => "pnm", # technically wrong, but historically it works in Imager
4096 sub def_guess_type {
4099 my ($ext) = $name =~ /\.([^.]+)$/
4102 my $type = $ext_types{$ext}
4109 return @combine_types;
4112 # get the minimum of a list
4116 for(@_) { if ($_<$mx) { $mx=$_; }}
4120 # get the maximum of a list
4124 for(@_) { if ($_>$mx) { $mx=$_; }}
4128 # string stuff for iptc headers
4132 $str = substr($str,3);
4133 $str =~ s/[\n\r]//g;
4140 # A little hack to parse iptc headers.
4145 my($caption,$photogr,$headln,$credit);
4147 my $str=$self->{IPTCRAW};
4152 @ar=split(/8BIM/,$str);
4157 @sar=split(/\034\002/);
4158 foreach $item (@sar) {
4159 if ($item =~ m/^x/) {
4160 $caption = _clean($item);
4163 if ($item =~ m/^P/) {
4164 $photogr = _clean($item);
4167 if ($item =~ m/^i/) {
4168 $headln = _clean($item);
4171 if ($item =~ m/^n/) {
4172 $credit = _clean($item);
4178 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4185 or die "Only C language supported";
4187 require Imager::ExtUtils;
4188 return Imager::ExtUtils->inline_config;
4191 # threads shouldn't try to close raw Imager objects
4192 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4195 # this serves two purposes:
4196 # - a class method to load the file support modules included with Imager
4197 # (or were included, once the library dependent modules are split out)
4198 # - something for Module::ScanDeps to analyze
4199 # https://rt.cpan.org/Ticket/Display.html?id=6566
4201 eval { require Imager::File::GIF };
4202 eval { require Imager::File::JPEG };
4203 eval { require Imager::File::PNG };
4204 eval { require Imager::File::SGI };
4205 eval { require Imager::File::TIFF };
4206 eval { require Imager::File::ICO };
4207 eval { require Imager::Font::W32 };
4208 eval { require Imager::Font::FT2 };
4209 eval { require Imager::Font::T1 };
4216 my ($class, $fh) = @_;
4219 return $class->new_cb
4224 return print $fh $_[0];
4228 my $count = CORE::read $fh, $tmp, $_[1];
4236 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4237 unless (CORE::seek $fh, $_[0], $_[1]) {
4248 return $class->_new_perlio($fh);
4252 # backward compatibility for %formats
4253 package Imager::FORMATS;
4255 use constant IX_FORMATS => 0;
4256 use constant IX_LIST => 1;
4257 use constant IX_INDEX => 2;
4258 use constant IX_CLASSES => 3;
4261 my ($class, $formats, $classes) = @_;
4263 return bless [ $formats, [ ], 0, $classes ], $class;
4267 my ($self, $key) = @_;
4269 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4272 my $loaded = Imager::_load_file($file, \$error);
4277 if ($error =~ /^Can't locate /) {
4278 $error = "Can't locate $file";
4280 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4283 $self->[IX_FORMATS]{$key} = $value;
4289 my ($self, $key) = @_;
4291 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4293 $self->[IX_CLASSES]{$key} or return undef;
4295 return $self->_check($key);
4299 die "%Imager::formats is not user monifiable";
4303 die "%Imager::formats is not user monifiable";
4307 die "%Imager::formats is not user monifiable";
4311 my ($self, $key) = @_;
4313 if (exists $self->[IX_FORMATS]{$key}) {
4314 my $value = $self->[IX_FORMATS]{$key}
4319 $self->_check($key) or return 1==0;
4327 unless (@{$self->[IX_LIST]}) {
4329 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4330 keys %{$self->[IX_FORMATS]};
4332 for my $key (keys %{$self->[IX_CLASSES]}) {
4333 $self->[IX_FORMATS]{$key} and next;
4335 and push @{$self->[IX_LIST]}, $key;
4339 @{$self->[IX_LIST]} or return;
4340 $self->[IX_INDEX] = 1;
4341 return $self->[IX_LIST][0];
4347 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4350 return $self->[IX_LIST][$self->[IX_INDEX]++];
4356 return scalar @{$self->[IX_LIST]};
4361 # Below is the stub of documentation for your module. You better edit it!
4365 Imager - Perl extension for Generating 24 bit Images
4375 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4380 # see Imager::Files for information on the read() method
4381 my $img = Imager->new(file=>$file)
4382 or die Imager->errstr();
4384 $file =~ s/\.[^.]*$//;
4386 # Create smaller version
4387 # documented in Imager::Transformations
4388 my $thumb = $img->scale(scalefactor=>.3);
4390 # Autostretch individual channels
4391 $thumb->filter(type=>'autolevels');
4393 # try to save in one of these formats
4396 for $format ( qw( png gif jpeg tiff ppm ) ) {
4397 # Check if given format is supported
4398 if ($Imager::formats{$format}) {
4399 $file.="_low.$format";
4400 print "Storing image as: $file\n";
4401 # documented in Imager::Files
4402 $thumb->write(file=>$file) or
4410 Imager is a module for creating and altering images. It can read and
4411 write various image formats, draw primitive shapes like lines,and
4412 polygons, blend multiple images together in various ways, scale, crop,
4413 render text and more.
4415 =head2 Overview of documentation
4421 Imager - This document - Synopsis, Example, Table of Contents and
4426 L<Imager::Install> - installation notes for Imager.
4430 L<Imager::Tutorial> - a brief introduction to Imager.
4434 L<Imager::Cookbook> - how to do various things with Imager.
4438 L<Imager::ImageTypes> - Basics of constructing image objects with
4439 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4440 8/16/double bits/channel, color maps, channel masks, image tags, color
4441 quantization. Also discusses basic image information methods.
4445 L<Imager::Files> - IO interaction, reading/writing images, format
4450 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4455 L<Imager::Color> - Color specification.
4459 L<Imager::Fill> - Fill pattern specification.
4463 L<Imager::Font> - General font rendering, bounding boxes and font
4468 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4469 blending, pasting, convert and map.
4473 L<Imager::Engines> - Programmable transformations through
4474 C<transform()>, C<transform2()> and C<matrix_transform()>.
4478 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4483 L<Imager::Expr> - Expressions for evaluation engine used by
4488 L<Imager::Matrix2d> - Helper class for affine transformations.
4492 L<Imager::Fountain> - Helper for making gradient profiles.
4496 L<Imager::IO> - Imager I/O abstraction.
4500 L<Imager::API> - using Imager's C API
4504 L<Imager::APIRef> - API function reference
4508 L<Imager::Inline> - using Imager's C API from Inline::C
4512 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4516 L<Imager::Security> - brief security notes.
4520 L<Imager::Threads> - brief information on working with threads.
4524 =head2 Basic Overview
4526 An Image object is created with C<$img = Imager-E<gt>new()>.
4529 $img=Imager->new(); # create empty image
4530 $img->read(file=>'lena.png',type=>'png') or # read image from file
4531 die $img->errstr(); # give an explanation
4532 # if something failed
4534 or if you want to create an empty image:
4536 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4538 This example creates a completely black image of width 400 and height
4541 =head1 ERROR HANDLING
4543 In general a method will return false when it fails, if it does use
4544 the C<errstr()> method to find out why:
4550 Returns the last error message in that context.
4552 If the last error you received was from calling an object method, such
4553 as read, call errstr() as an object method to find out why:
4555 my $image = Imager->new;
4556 $image->read(file => 'somefile.gif')
4557 or die $image->errstr;
4559 If it was a class method then call errstr() as a class method:
4561 my @imgs = Imager->read_multi(file => 'somefile.gif')
4562 or die Imager->errstr;
4564 Note that in some cases object methods are implemented in terms of
4565 class methods so a failing object method may set both.
4569 The C<Imager-E<gt>new> method is described in detail in
4570 L<Imager::ImageTypes>.
4574 Where to find information on methods for Imager class objects.
4576 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4579 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4581 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4584 arc() - L<Imager::Draw/arc()> - draw a filled arc
4586 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4589 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4591 check_file_limits() - L<Imager::Files/check_file_limits()>
4593 circle() - L<Imager::Draw/circle()> - draw a filled circle
4595 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4598 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4599 colors in an image's palette (paletted images only)
4601 combine() - L<Imager::Transformations/combine()> - combine channels
4602 from one or more images.
4604 combines() - L<Imager::Draw/combines()> - return a list of the
4605 different combine type keywords
4607 compose() - L<Imager::Transformations/compose()> - compose one image
4610 convert() - L<Imager::Transformations/convert()> - transform the color
4613 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4616 crop() - L<Imager::Transformations/crop()> - extract part of an image
4618 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4619 used to guess the output file format based on the output file name
4621 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4623 difference() - L<Imager::Filters/difference()> - produce a difference
4624 images from two input images.
4626 errstr() - L</errstr()> - the error from the last failed operation.
4628 filter() - L<Imager::Filters/filter()> - image filtering
4630 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4631 palette, if it has one
4633 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4636 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4639 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4640 samples per pixel for an image
4642 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4643 different colors used by an image (works for direct color images)
4645 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4646 palette, if it has one
4648 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4650 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4652 get_file_limits() - L<Imager::Files/get_file_limits()>
4654 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4657 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4659 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4662 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4663 row or partial row of pixels.
4665 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4666 row or partial row of pixels.
4668 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4671 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4674 init() - L<Imager::ImageTypes/init()>
4676 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4677 image write functions should write the image in their bilevel (blank
4678 and white, no gray levels) format
4680 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4683 line() - L<Imager::Draw/line()> - draw an interval
4685 load_plugin() - L<Imager::Filters/load_plugin()>
4687 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4690 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4691 color palette from one or more input images.
4693 map() - L<Imager::Transformations/map()> - remap color
4696 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4698 matrix_transform() - L<Imager::Engines/matrix_transform()>
4700 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4702 NC() - L<Imager::Handy/NC()>
4704 NCF() - L<Imager::Handy/NCF()>
4706 new() - L<Imager::ImageTypes/new()>
4708 newcolor() - L<Imager::Handy/newcolor()>
4710 newcolour() - L<Imager::Handy/newcolour()>
4712 newfont() - L<Imager::Handy/newfont()>
4714 NF() - L<Imager::Handy/NF()>
4716 open() - L<Imager::Files/read()> - an alias for read()
4718 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4722 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4725 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4728 polygon() - L<Imager::Draw/polygon()>
4730 polyline() - L<Imager::Draw/polyline()>
4732 preload() - L<Imager::Files/preload()>
4734 read() - L<Imager::Files/read()> - read a single image from an image file
4736 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4739 read_types() - L<Imager::Files/read_types()> - list image types Imager
4742 register_filter() - L<Imager::Filters/register_filter()>
4744 register_reader() - L<Imager::Files/register_reader()>
4746 register_writer() - L<Imager::Files/register_writer()>
4748 rotate() - L<Imager::Transformations/rotate()>
4750 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4751 onto an image and use the alpha channel
4753 scale() - L<Imager::Transformations/scale()>
4755 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4757 scaleX() - L<Imager::Transformations/scaleX()>
4759 scaleY() - L<Imager::Transformations/scaleY()>
4761 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4764 set_file_limits() - L<Imager::Files/set_file_limits()>
4766 setmask() - L<Imager::ImageTypes/setmask()>
4768 setpixel() - L<Imager::Draw/setpixel()>
4770 setsamples() - L<Imager::Draw/setsamples()>
4772 setscanline() - L<Imager::Draw/setscanline()>
4774 settag() - L<Imager::ImageTypes/settag()>
4776 string() - L<Imager::Draw/string()> - draw text on an image
4778 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4780 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4782 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4784 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4786 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4787 double per sample image.
4789 transform() - L<Imager::Engines/"transform()">
4791 transform2() - L<Imager::Engines/"transform2()">
4793 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4795 unload_plugin() - L<Imager::Filters/unload_plugin()>
4797 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4800 write() - L<Imager::Files/write()> - write an image to a file
4802 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4805 write_types() - L<Imager::Files/read_types()> - list image types Imager
4808 =head1 CONCEPT INDEX
4810 animated GIF - L<Imager::Files/"Writing an animated GIF">
4812 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4813 L<Imager::ImageTypes/"Common Tags">.
4815 blend - alpha blending one image onto another
4816 L<Imager::Transformations/rubthrough()>
4818 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4820 boxes, drawing - L<Imager::Draw/box()>
4822 changes between image - L<Imager::Filters/"Image Difference">
4824 channels, combine into one image - L<Imager::Transformations/combine()>
4826 color - L<Imager::Color>
4828 color names - L<Imager::Color>, L<Imager::Color::Table>
4830 combine modes - L<Imager::Draw/"Combine Types">
4832 compare images - L<Imager::Filters/"Image Difference">
4834 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4836 convolution - L<Imager::Filters/conv>
4838 cropping - L<Imager::Transformations/crop()>
4840 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4842 C<diff> images - L<Imager::Filters/"Image Difference">
4844 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4845 L<Imager::Cookbook/"Image spatial resolution">
4847 drawing boxes - L<Imager::Draw/box()>
4849 drawing lines - L<Imager::Draw/line()>
4851 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4853 error message - L</"ERROR HANDLING">
4855 files, font - L<Imager::Font>
4857 files, image - L<Imager::Files>
4859 filling, types of fill - L<Imager::Fill>
4861 filling, boxes - L<Imager::Draw/box()>
4863 filling, flood fill - L<Imager::Draw/flood_fill()>
4865 flood fill - L<Imager::Draw/flood_fill()>
4867 fonts - L<Imager::Font>
4869 fonts, drawing with - L<Imager::Draw/string()>,
4870 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4872 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4874 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4876 fountain fill - L<Imager::Fill/"Fountain fills">,
4877 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4878 L<Imager::Filters/gradgen>
4880 GIF files - L<Imager::Files/"GIF">
4882 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4884 gradient fill - L<Imager::Fill/"Fountain fills">,
4885 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4886 L<Imager::Filters/gradgen>
4888 gray scale, convert image to - L<Imager::Transformations/convert()>
4890 gaussian blur - L<Imager::Filters/gaussian>
4892 hatch fills - L<Imager::Fill/"Hatched fills">
4894 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4896 invert image - L<Imager::Filters/hardinvert>,
4897 L<Imager::Filters/hardinvertall>
4899 JPEG - L<Imager::Files/"JPEG">
4901 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4903 lines, drawing - L<Imager::Draw/line()>
4905 matrix - L<Imager::Matrix2d>,
4906 L<Imager::Engines/"Matrix Transformations">,
4907 L<Imager::Font/transform()>
4909 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
4911 mosaic - L<Imager::Filters/mosaic>
4913 noise, filter - L<Imager::Filters/noise>
4915 noise, rendered - L<Imager::Filters/turbnoise>,
4916 L<Imager::Filters/radnoise>
4918 paste - L<Imager::Transformations/paste()>,
4919 L<Imager::Transformations/rubthrough()>
4921 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4922 L<Imager::ImageTypes/new()>
4924 =for stopwords posterize
4926 posterize - L<Imager::Filters/postlevels>
4928 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4930 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4932 rectangles, drawing - L<Imager::Draw/box()>
4934 resizing an image - L<Imager::Transformations/scale()>,
4935 L<Imager::Transformations/crop()>
4937 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4939 saving an image - L<Imager::Files>
4941 scaling - L<Imager::Transformations/scale()>
4943 security - L<Imager::Security>
4945 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4947 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4949 size, image - L<Imager::ImageTypes/getwidth()>,
4950 L<Imager::ImageTypes/getheight()>
4952 size, text - L<Imager::Font/bounding_box()>
4954 tags, image metadata - L<Imager::ImageTypes/"Tags">
4956 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4957 L<Imager::Font::Wrap>
4959 text, wrapping text in an area - L<Imager::Font::Wrap>
4961 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4963 threads - L<Imager::Threads>
4965 tiles, color - L<Imager::Filters/mosaic>
4967 transparent images - L<Imager::ImageTypes>,
4968 L<Imager::Cookbook/"Transparent PNG">
4970 =for stopwords unsharp
4972 unsharp mask - L<Imager::Filters/unsharpmask>
4974 watermark - L<Imager::Filters/watermark>
4976 writing an image to a file - L<Imager::Files>
4980 The best place to get help with Imager is the mailing list.
4982 To subscribe send a message with C<subscribe> in the body to:
4984 imager-devel+request@molar.is
4990 L<http://www.molar.is/en/lists/imager-devel/>
4994 where you can also find the mailing list archive.
4996 You can report bugs by pointing your browser at:
5000 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5004 or by sending an email to:
5008 bug-Imager@rt.cpan.org
5012 Please remember to include the versions of Imager, perl, supporting
5013 libraries, and any relevant code. If you have specific images that
5014 cause the problems, please include those too.
5016 If you don't want to publish your email address on a mailing list you
5017 can use CPAN::Forum:
5019 http://www.cpanforum.com/dist/Imager
5021 You will need to register to post.
5023 =head1 CONTRIBUTING TO IMAGER
5029 If you like or dislike Imager, you can add a public review of Imager
5032 http://cpanratings.perl.org/dist/Imager
5034 =for stopwords Bitcard
5036 This requires a Bitcard account (http://www.bitcard.org).
5038 You can also send email to the maintainer below.
5040 If you send me a bug report via email, it will be copied to Request
5045 I accept patches, preferably against the master branch in git. Please
5046 include an explanation of the reason for why the patch is needed or
5049 Your patch should include regression tests where possible, otherwise
5050 it will be delayed until I get a chance to write them.
5052 To browse Imager's git repository:
5054 http://git.imager.perl.org/imager.git
5058 https://github.com/tonycoz/imager
5062 git clone git://git.imager.perl.org/imager.git
5066 git clone git://github.com/tonycoz/imager.git
5070 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5072 Arnar M. Hrafnkelsson is the original author of Imager.
5074 Many others have contributed to Imager, please see the C<README> for a
5079 Imager is licensed under the same terms as perl itself.
5082 makeblendedfont Fontforge
5084 A test font, generated by the Debian packaged Fontforge,
5085 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5086 copyrighted by Adobe. See F<adobe.txt> in the source for license
5091 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5092 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5093 L<Imager::Font>(3), L<Imager::Transformations>(3),
5094 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5095 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5097 L<http://imager.perl.org/>
5099 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5101 Other perl imaging modules include:
5103 L<GD>(3), L<Image::Magick>(3),
5104 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5105 L<Prima::Image>, L<IPA>.
5107 For manipulating image metadata see L<Image::ExifTool>.
5109 If you're trying to use Imager for array processing, you should
5110 probably using L<PDL>.