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::Tutorial> - a brief introduction to Imager.
4430 L<Imager::Cookbook> - how to do various things with Imager.
4434 L<Imager::ImageTypes> - Basics of constructing image objects with
4435 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4436 8/16/double bits/channel, color maps, channel masks, image tags, color
4437 quantization. Also discusses basic image information methods.
4441 L<Imager::Files> - IO interaction, reading/writing images, format
4446 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4451 L<Imager::Color> - Color specification.
4455 L<Imager::Fill> - Fill pattern specification.
4459 L<Imager::Font> - General font rendering, bounding boxes and font
4464 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4465 blending, pasting, convert and map.
4469 L<Imager::Engines> - Programmable transformations through
4470 C<transform()>, C<transform2()> and C<matrix_transform()>.
4474 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4479 L<Imager::Expr> - Expressions for evaluation engine used by
4484 L<Imager::Matrix2d> - Helper class for affine transformations.
4488 L<Imager::Fountain> - Helper for making gradient profiles.
4492 L<Imager::API> - using Imager's C API
4496 L<Imager::APIRef> - API function reference
4500 L<Imager::Inline> - using Imager's C API from Inline::C
4504 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4508 L<Imager::Security> - brief security notes.
4512 L<Imager::Threads> - brief information on working with threads.
4516 =head2 Basic Overview
4518 An Image object is created with C<$img = Imager-E<gt>new()>.
4521 $img=Imager->new(); # create empty image
4522 $img->read(file=>'lena.png',type=>'png') or # read image from file
4523 die $img->errstr(); # give an explanation
4524 # if something failed
4526 or if you want to create an empty image:
4528 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4530 This example creates a completely black image of width 400 and height
4533 =head1 ERROR HANDLING
4535 In general a method will return false when it fails, if it does use
4536 the C<errstr()> method to find out why:
4542 Returns the last error message in that context.
4544 If the last error you received was from calling an object method, such
4545 as read, call errstr() as an object method to find out why:
4547 my $image = Imager->new;
4548 $image->read(file => 'somefile.gif')
4549 or die $image->errstr;
4551 If it was a class method then call errstr() as a class method:
4553 my @imgs = Imager->read_multi(file => 'somefile.gif')
4554 or die Imager->errstr;
4556 Note that in some cases object methods are implemented in terms of
4557 class methods so a failing object method may set both.
4561 The C<Imager-E<gt>new> method is described in detail in
4562 L<Imager::ImageTypes>.
4566 Where to find information on methods for Imager class objects.
4568 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4571 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4573 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4576 arc() - L<Imager::Draw/arc()> - draw a filled arc
4578 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4581 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4583 check_file_limits() - L<Imager::Files/check_file_limits()>
4585 circle() - L<Imager::Draw/circle()> - draw a filled circle
4587 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4590 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4591 colors in an image's palette (paletted images only)
4593 combine() - L<Imager::Transformations/combine()> - combine channels
4594 from one or more images.
4596 combines() - L<Imager::Draw/combines()> - return a list of the
4597 different combine type keywords
4599 compose() - L<Imager::Transformations/compose()> - compose one image
4602 convert() - L<Imager::Transformations/convert()> - transform the color
4605 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4608 crop() - L<Imager::Transformations/crop()> - extract part of an image
4610 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4611 used to guess the output file format based on the output file name
4613 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4615 difference() - L<Imager::Filters/difference()> - produce a difference
4616 images from two input images.
4618 errstr() - L</errstr()> - the error from the last failed operation.
4620 filter() - L<Imager::Filters/filter()> - image filtering
4622 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4623 palette, if it has one
4625 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4628 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4631 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4632 samples per pixel for an image
4634 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4635 different colors used by an image (works for direct color images)
4637 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4638 palette, if it has one
4640 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4642 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4644 get_file_limits() - L<Imager::Files/get_file_limits()>
4646 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4649 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4651 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4654 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4655 row or partial row of pixels.
4657 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4658 row or partial row of pixels.
4660 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4663 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4666 init() - L<Imager::ImageTypes/init()>
4668 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4669 image write functions should write the image in their bilevel (blank
4670 and white, no gray levels) format
4672 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4675 line() - L<Imager::Draw/line()> - draw an interval
4677 load_plugin() - L<Imager::Filters/load_plugin()>
4679 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4682 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4683 color palette from one or more input images.
4685 map() - L<Imager::Transformations/map()> - remap color
4688 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4690 matrix_transform() - L<Imager::Engines/matrix_transform()>
4692 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4694 NC() - L<Imager::Handy/NC()>
4696 NCF() - L<Imager::Handy/NCF()>
4698 new() - L<Imager::ImageTypes/new()>
4700 newcolor() - L<Imager::Handy/newcolor()>
4702 newcolour() - L<Imager::Handy/newcolour()>
4704 newfont() - L<Imager::Handy/newfont()>
4706 NF() - L<Imager::Handy/NF()>
4708 open() - L<Imager::Files/read()> - an alias for read()
4710 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4714 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4717 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4720 polygon() - L<Imager::Draw/polygon()>
4722 polyline() - L<Imager::Draw/polyline()>
4724 preload() - L<Imager::Files/preload()>
4726 read() - L<Imager::Files/read()> - read a single image from an image file
4728 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4731 read_types() - L<Imager::Files/read_types()> - list image types Imager
4734 register_filter() - L<Imager::Filters/register_filter()>
4736 register_reader() - L<Imager::Files/register_reader()>
4738 register_writer() - L<Imager::Files/register_writer()>
4740 rotate() - L<Imager::Transformations/rotate()>
4742 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4743 onto an image and use the alpha channel
4745 scale() - L<Imager::Transformations/scale()>
4747 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4749 scaleX() - L<Imager::Transformations/scaleX()>
4751 scaleY() - L<Imager::Transformations/scaleY()>
4753 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4756 set_file_limits() - L<Imager::Files/set_file_limits()>
4758 setmask() - L<Imager::ImageTypes/setmask()>
4760 setpixel() - L<Imager::Draw/setpixel()>
4762 setsamples() - L<Imager::Draw/setsamples()>
4764 setscanline() - L<Imager::Draw/setscanline()>
4766 settag() - L<Imager::ImageTypes/settag()>
4768 string() - L<Imager::Draw/string()> - draw text on an image
4770 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4772 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4774 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4776 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4778 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4779 double per sample image.
4781 transform() - L<Imager::Engines/"transform()">
4783 transform2() - L<Imager::Engines/"transform2()">
4785 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4787 unload_plugin() - L<Imager::Filters/unload_plugin()>
4789 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4792 write() - L<Imager::Files/write()> - write an image to a file
4794 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4797 write_types() - L<Imager::Files/read_types()> - list image types Imager
4800 =head1 CONCEPT INDEX
4802 animated GIF - L<Imager::Files/"Writing an animated GIF">
4804 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4805 L<Imager::ImageTypes/"Common Tags">.
4807 blend - alpha blending one image onto another
4808 L<Imager::Transformations/rubthrough()>
4810 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4812 boxes, drawing - L<Imager::Draw/box()>
4814 changes between image - L<Imager::Filters/"Image Difference">
4816 channels, combine into one image - L<Imager::Transformations/combine()>
4818 color - L<Imager::Color>
4820 color names - L<Imager::Color>, L<Imager::Color::Table>
4822 combine modes - L<Imager::Draw/"Combine Types">
4824 compare images - L<Imager::Filters/"Image Difference">
4826 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4828 convolution - L<Imager::Filters/conv>
4830 cropping - L<Imager::Transformations/crop()>
4832 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4834 C<diff> images - L<Imager::Filters/"Image Difference">
4836 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4837 L<Imager::Cookbook/"Image spatial resolution">
4839 drawing boxes - L<Imager::Draw/box()>
4841 drawing lines - L<Imager::Draw/line()>
4843 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4845 error message - L</"ERROR HANDLING">
4847 files, font - L<Imager::Font>
4849 files, image - L<Imager::Files>
4851 filling, types of fill - L<Imager::Fill>
4853 filling, boxes - L<Imager::Draw/box()>
4855 filling, flood fill - L<Imager::Draw/flood_fill()>
4857 flood fill - L<Imager::Draw/flood_fill()>
4859 fonts - L<Imager::Font>
4861 fonts, drawing with - L<Imager::Draw/string()>,
4862 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4864 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4866 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4868 fountain fill - L<Imager::Fill/"Fountain fills">,
4869 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4870 L<Imager::Filters/gradgen>
4872 GIF files - L<Imager::Files/"GIF">
4874 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4876 gradient fill - L<Imager::Fill/"Fountain fills">,
4877 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4878 L<Imager::Filters/gradgen>
4880 gray scale, convert image to - L<Imager::Transformations/convert()>
4882 gaussian blur - L<Imager::Filters/gaussian>
4884 hatch fills - L<Imager::Fill/"Hatched fills">
4886 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4888 invert image - L<Imager::Filters/hardinvert>,
4889 L<Imager::Filters/hardinvertall>
4891 JPEG - L<Imager::Files/"JPEG">
4893 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4895 lines, drawing - L<Imager::Draw/line()>
4897 matrix - L<Imager::Matrix2d>,
4898 L<Imager::Engines/"Matrix Transformations">,
4899 L<Imager::Font/transform()>
4901 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
4903 mosaic - L<Imager::Filters/mosaic>
4905 noise, filter - L<Imager::Filters/noise>
4907 noise, rendered - L<Imager::Filters/turbnoise>,
4908 L<Imager::Filters/radnoise>
4910 paste - L<Imager::Transformations/paste()>,
4911 L<Imager::Transformations/rubthrough()>
4913 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4914 L<Imager::ImageTypes/new()>
4916 =for stopwords posterize
4918 posterize - L<Imager::Filters/postlevels>
4920 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4922 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4924 rectangles, drawing - L<Imager::Draw/box()>
4926 resizing an image - L<Imager::Transformations/scale()>,
4927 L<Imager::Transformations/crop()>
4929 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4931 saving an image - L<Imager::Files>
4933 scaling - L<Imager::Transformations/scale()>
4935 security - L<Imager::Security>
4937 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4939 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4941 size, image - L<Imager::ImageTypes/getwidth()>,
4942 L<Imager::ImageTypes/getheight()>
4944 size, text - L<Imager::Font/bounding_box()>
4946 tags, image metadata - L<Imager::ImageTypes/"Tags">
4948 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4949 L<Imager::Font::Wrap>
4951 text, wrapping text in an area - L<Imager::Font::Wrap>
4953 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4955 threads - L<Imager::Threads>
4957 tiles, color - L<Imager::Filters/mosaic>
4959 transparent images - L<Imager::ImageTypes>,
4960 L<Imager::Cookbook/"Transparent PNG">
4962 =for stopwords unsharp
4964 unsharp mask - L<Imager::Filters/unsharpmask>
4966 watermark - L<Imager::Filters/watermark>
4968 writing an image to a file - L<Imager::Files>
4972 The best place to get help with Imager is the mailing list.
4974 To subscribe send a message with C<subscribe> in the body to:
4976 imager-devel+request@molar.is
4982 L<http://www.molar.is/en/lists/imager-devel/>
4986 where you can also find the mailing list archive.
4988 You can report bugs by pointing your browser at:
4992 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4996 or by sending an email to:
5000 bug-Imager@rt.cpan.org
5004 Please remember to include the versions of Imager, perl, supporting
5005 libraries, and any relevant code. If you have specific images that
5006 cause the problems, please include those too.
5008 If you don't want to publish your email address on a mailing list you
5009 can use CPAN::Forum:
5011 http://www.cpanforum.com/dist/Imager
5013 You will need to register to post.
5015 =head1 CONTRIBUTING TO IMAGER
5021 If you like or dislike Imager, you can add a public review of Imager
5024 http://cpanratings.perl.org/dist/Imager
5026 =for stopwords Bitcard
5028 This requires a Bitcard account (http://www.bitcard.org).
5030 You can also send email to the maintainer below.
5032 If you send me a bug report via email, it will be copied to Request
5037 I accept patches, preferably against the master branch in git. Please
5038 include an explanation of the reason for why the patch is needed or
5041 Your patch should include regression tests where possible, otherwise
5042 it will be delayed until I get a chance to write them.
5044 To browse Imager's git repository:
5046 http://git.imager.perl.org/imager.git
5050 https://github.com/tonycoz/imager
5054 git clone git://git.imager.perl.org/imager.git
5058 git clone git://github.com/tonycoz/imager.git
5062 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5064 Arnar M. Hrafnkelsson is the original author of Imager.
5066 Many others have contributed to Imager, please see the C<README> for a
5071 Imager is licensed under the same terms as perl itself.
5074 makeblendedfont Fontforge
5076 A test font, generated by the Debian packaged Fontforge,
5077 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5078 copyrighted by Adobe. See F<adobe.txt> in the source for license
5083 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5084 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5085 L<Imager::Font>(3), L<Imager::Transformations>(3),
5086 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5087 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5089 L<http://imager.perl.org/>
5091 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5093 Other perl imaging modules include:
5095 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3),
5096 L<Prima::Image>, L<IPA>.
5098 For manipulating image metadata see L<Image::ExifTool>.
5100 If you're trying to use Imager for array processing, you should
5101 probably using L<PDL>.