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
524 if ($^O eq 'android') {
526 $filename = File::Spec->rel2abs($filename);
529 my ($DSO_handle,$str)=DSO_open($filename);
530 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
531 my %funcs=DSO_funclist($DSO_handle);
532 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
534 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
536 $DSOs{$filename}=[$DSO_handle,\%funcs];
539 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
540 $DEBUG && print "eval string:\n",$evstr,"\n";
552 if ($^O eq 'android') {
554 $filename = File::Spec->rel2abs($filename);
557 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
558 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
559 for(keys %{$funcref}) {
561 $DEBUG && print "unloading: $_\n";
563 my $rc=DSO_close($DSO_handle);
564 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
568 # take the results of i_error() and make a message out of it
570 return join(": ", map $_->[0], i_errors());
573 # this function tries to DWIM for color parameters
574 # color objects are used as is
575 # simple scalars are simply treated as single parameters to Imager::Color->new
576 # hashrefs are treated as named argument lists to Imager::Color->new
577 # arrayrefs are treated as list arguments to Imager::Color->new iff any
579 # other arrayrefs are treated as list arguments to Imager::Color::Float
583 # perl 5.6.0 seems to do weird things to $arg if we don't make an
584 # explicitly stringified copy
585 # I vaguely remember a bug on this on p5p, but couldn't find it
586 # through bugs.perl.org (I had trouble getting it to find any bugs)
587 my $copy = $arg . "";
591 if (UNIVERSAL::isa($arg, "Imager::Color")
592 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
596 if ($copy =~ /^HASH\(/) {
597 $result = Imager::Color->new(%$arg);
599 elsif ($copy =~ /^ARRAY\(/) {
600 $result = Imager::Color->new(@$arg);
603 $Imager::ERRSTR = "Not a color";
608 # assume Imager::Color::new knows how to handle it
609 $result = Imager::Color->new($arg);
616 my ($self, $combine, $default) = @_;
618 if (!defined $combine && ref $self) {
619 $combine = $self->{combine};
621 defined $combine or $combine = $defaults{combine};
622 defined $combine or $combine = $default;
624 if (exists $combine_types{$combine}) {
625 $combine = $combine_types{$combine};
632 my ($self, $method) = @_;
634 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
636 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
637 $msg = "$method: $msg" if $method;
638 $self->_set_error($msg);
643 # returns first defined parameter
646 return $_ if defined $_;
652 # Methods to be called on objects.
655 # Create a new Imager object takes very few parameters.
656 # usually you call this method and then call open from
657 # the resulting object
664 $self->{IMG}=undef; # Just to indicate what exists
665 $self->{ERRSTR}=undef; #
666 $self->{DEBUG}=$DEBUG;
667 $self->{DEBUG} and print "Initialized Imager\n";
668 if (defined $hsh{xsize} || defined $hsh{ysize}) {
669 unless ($self->img_set(%hsh)) {
670 $Imager::ERRSTR = $self->{ERRSTR};
674 elsif (defined $hsh{file} ||
677 defined $hsh{callback} ||
678 defined $hsh{readcb} ||
679 defined $hsh{data}) {
680 # allow $img = Imager->new(file => $filename)
683 # type is already used as a parameter to new(), rename it for the
685 if ($hsh{filetype}) {
686 $extras{type} = $hsh{filetype};
688 unless ($self->read(%hsh, %extras)) {
689 $Imager::ERRSTR = $self->{ERRSTR};
697 # Copy an entire image with no changes
698 # - if an image has magic the copy of it will not be magical
703 $self->_valid_image("copy")
706 unless (defined wantarray) {
708 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
712 my $newcopy=Imager->new();
713 $newcopy->{IMG} = i_copy($self->{IMG});
722 $self->_valid_image("paste")
725 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
726 my $src = $input{img} || $input{src};
728 $self->_set_error("no source image");
731 unless ($src->_valid_image("paste")) {
732 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
735 $input{left}=0 if $input{left} <= 0;
736 $input{top}=0 if $input{top} <= 0;
738 my($r,$b)=i_img_info($src->{IMG});
739 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
740 my ($src_right, $src_bottom);
741 if ($input{src_coords}) {
742 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
745 if (defined $input{src_maxx}) {
746 $src_right = $input{src_maxx};
748 elsif (defined $input{width}) {
749 if ($input{width} <= 0) {
750 $self->_set_error("paste: width must me positive");
753 $src_right = $src_left + $input{width};
758 if (defined $input{src_maxy}) {
759 $src_bottom = $input{src_maxy};
761 elsif (defined $input{height}) {
762 if ($input{height} < 0) {
763 $self->_set_error("paste: height must be positive");
766 $src_bottom = $src_top + $input{height};
773 $src_right > $r and $src_right = $r;
774 $src_bottom > $b and $src_bottom = $b;
776 if ($src_right <= $src_left
777 || $src_bottom < $src_top) {
778 $self->_set_error("nothing to paste");
782 i_copyto($self->{IMG}, $src->{IMG},
783 $src_left, $src_top, $src_right, $src_bottom,
784 $input{left}, $input{top});
786 return $self; # What should go here??
789 # Crop an image - i.e. return a new image that is smaller
794 $self->_valid_image("crop")
797 unless (defined wantarray) {
799 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
805 my ($w, $h, $l, $r, $b, $t) =
806 @hsh{qw(width height left right bottom top)};
808 # work through the various possibilities
813 elsif (!defined $r) {
814 $r = $self->getwidth;
826 $l = int(0.5+($self->getwidth()-$w)/2);
831 $r = $self->getwidth;
837 elsif (!defined $b) {
838 $b = $self->getheight;
850 $t=int(0.5+($self->getheight()-$h)/2);
855 $b = $self->getheight;
858 ($l,$r)=($r,$l) if $l>$r;
859 ($t,$b)=($b,$t) if $t>$b;
862 $r > $self->getwidth and $r = $self->getwidth;
864 $b > $self->getheight and $b = $self->getheight;
866 if ($l == $r || $t == $b) {
867 $self->_set_error("resulting image would have no content");
870 if( $r < $l or $b < $t ) {
871 $self->_set_error("attempting to crop outside of the image");
874 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
876 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
881 my ($self, %opts) = @_;
886 my $x = $opts{xsize} || $self->getwidth;
887 my $y = $opts{ysize} || $self->getheight;
888 my $channels = $opts{channels} || $self->getchannels;
890 my $out = Imager->new;
891 if ($channels == $self->getchannels) {
892 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
895 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
897 unless ($out->{IMG}) {
898 $self->{ERRSTR} = $self->_error_as_msg;
905 # Sets an image to a certain size and channel number
906 # if there was previously data in the image it is discarded
911 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
913 if (defined($self->{IMG})) {
914 # let IIM_DESTROY destroy it, it's possible this image is
915 # referenced from a virtual image (like masked)
916 #i_img_destroy($self->{IMG});
920 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
921 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
922 $hsh{maxcolors} || 256);
924 elsif ($hsh{bits} eq 'double') {
925 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
927 elsif ($hsh{bits} == 16) {
928 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
931 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
935 unless ($self->{IMG}) {
936 $self->{ERRSTR} = Imager->_error_as_msg();
943 # created a masked version of the current image
947 $self->_valid_image("masked")
950 my %opts = (left => 0,
952 right => $self->getwidth,
953 bottom => $self->getheight,
955 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
957 my $result = Imager->new;
958 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
959 $opts{top}, $opts{right} - $opts{left},
960 $opts{bottom} - $opts{top});
961 unless ($result->{IMG}) {
962 $self->_set_error(Imager->_error_as_msg);
966 # keep references to the mask and base images so they don't
968 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
973 # convert an RGB image into a paletted image
977 if (@_ != 1 && !ref $_[0]) {
984 unless (defined wantarray) {
986 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
990 $self->_valid_image("to_paletted")
993 my $result = Imager->new;
994 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
995 $self->_set_error(Imager->_error_as_msg);
1003 my ($class, $quant, @images) = @_;
1006 Imager->_set_error("make_palette: supply at least one image");
1010 for my $img (@images) {
1011 unless ($img->{IMG}) {
1012 Imager->_set_error("make_palette: image $index is empty");
1018 return i_img_make_palette($quant, map $_->{IMG}, @images);
1021 # convert a paletted (or any image) to an 8-bit/channel RGB image
1025 unless (defined wantarray) {
1026 my @caller = caller;
1027 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1031 $self->_valid_image("to_rgb8")
1034 my $result = Imager->new;
1035 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1036 $self->_set_error(Imager->_error_as_msg());
1043 # convert a paletted (or any image) to a 16-bit/channel RGB image
1047 unless (defined wantarray) {
1048 my @caller = caller;
1049 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1053 $self->_valid_image("to_rgb16")
1056 my $result = Imager->new;
1057 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1058 $self->_set_error(Imager->_error_as_msg());
1065 # convert a paletted (or any image) to an double/channel RGB image
1069 unless (defined wantarray) {
1070 my @caller = caller;
1071 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1075 $self->_valid_image("to_rgb_double")
1078 my $result = Imager->new;
1079 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1080 $self->_set_error(Imager->_error_as_msg());
1089 my %opts = (colors=>[], @_);
1091 $self->_valid_image("addcolors")
1094 my @colors = @{$opts{colors}}
1097 for my $color (@colors) {
1098 $color = _color($color);
1100 $self->_set_error($Imager::ERRSTR);
1105 return i_addcolors($self->{IMG}, @colors);
1110 my %opts = (start=>0, colors=>[], @_);
1112 $self->_valid_image("setcolors")
1115 my @colors = @{$opts{colors}}
1118 for my $color (@colors) {
1119 $color = _color($color);
1121 $self->_set_error($Imager::ERRSTR);
1126 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1133 $self->_valid_image("getcolors")
1136 if (!exists $opts{start} && !exists $opts{count}) {
1139 $opts{count} = $self->colorcount;
1141 elsif (!exists $opts{count}) {
1144 elsif (!exists $opts{start}) {
1148 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1154 $self->_valid_image("colorcount")
1157 return i_colorcount($self->{IMG});
1163 $self->_valid_image("maxcolors")
1166 i_maxcolors($self->{IMG});
1173 $self->_valid_image("findcolor")
1176 unless ($opts{color}) {
1177 $self->_set_error("findcolor: no color parameter");
1181 my $color = _color($opts{color})
1184 return i_findcolor($self->{IMG}, $color);
1190 $self->_valid_image("bits")
1193 my $bits = i_img_bits($self->{IMG});
1194 if ($bits && $bits == length(pack("d", 1)) * 8) {
1203 $self->_valid_image("type")
1206 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1212 $self->_valid_image("virtual")
1215 return i_img_virtual($self->{IMG});
1221 $self->_valid_image("is_bilevel")
1224 return i_img_is_monochrome($self->{IMG});
1228 my ($self, %opts) = @_;
1230 $self->_valid_image("tags")
1233 if (defined $opts{name}) {
1237 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1238 push @result, (i_tags_get($self->{IMG}, $found))[1];
1241 return wantarray ? @result : $result[0];
1243 elsif (defined $opts{code}) {
1247 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1248 push @result, (i_tags_get($self->{IMG}, $found))[1];
1255 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1258 return i_tags_count($self->{IMG});
1267 $self->_valid_image("addtag")
1271 if (defined $opts{value}) {
1272 if ($opts{value} =~ /^\d+$/) {
1274 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1277 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1280 elsif (defined $opts{data}) {
1281 # force addition as a string
1282 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1285 $self->{ERRSTR} = "No value supplied";
1289 elsif ($opts{code}) {
1290 if (defined $opts{value}) {
1291 if ($opts{value} =~ /^\d+$/) {
1293 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1296 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1299 elsif (defined $opts{data}) {
1300 # force addition as a string
1301 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1304 $self->{ERRSTR} = "No value supplied";
1317 $self->_valid_image("deltag")
1320 if (defined $opts{'index'}) {
1321 return i_tags_delete($self->{IMG}, $opts{'index'});
1323 elsif (defined $opts{name}) {
1324 return i_tags_delbyname($self->{IMG}, $opts{name});
1326 elsif (defined $opts{code}) {
1327 return i_tags_delbycode($self->{IMG}, $opts{code});
1330 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1336 my ($self, %opts) = @_;
1338 $self->_valid_image("settag")
1342 $self->deltag(name=>$opts{name});
1343 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1345 elsif (defined $opts{code}) {
1346 $self->deltag(code=>$opts{code});
1347 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1355 sub _get_reader_io {
1356 my ($self, $input) = @_;
1359 return $input->{io}, undef;
1361 elsif ($input->{fd}) {
1362 return io_new_fd($input->{fd});
1364 elsif ($input->{fh}) {
1365 unless (Scalar::Util::openhandle($input->{fh})) {
1366 $self->_set_error("Handle in fh option not opened");
1369 return Imager::IO->new_fh($input->{fh});
1371 elsif ($input->{file}) {
1372 my $file = IO::File->new($input->{file}, "r");
1374 $self->_set_error("Could not open $input->{file}: $!");
1378 return (io_new_fd(fileno($file)), $file);
1380 elsif ($input->{data}) {
1381 return io_new_buffer($input->{data});
1383 elsif ($input->{callback} || $input->{readcb}) {
1384 if (!$input->{seekcb}) {
1385 $self->_set_error("Need a seekcb parameter");
1387 if ($input->{maxbuffer}) {
1388 return io_new_cb($input->{writecb},
1389 $input->{callback} || $input->{readcb},
1390 $input->{seekcb}, $input->{closecb},
1391 $input->{maxbuffer});
1394 return io_new_cb($input->{writecb},
1395 $input->{callback} || $input->{readcb},
1396 $input->{seekcb}, $input->{closecb});
1400 $self->_set_error("file/fd/fh/data/callback parameter missing");
1405 sub _get_writer_io {
1406 my ($self, $input) = @_;
1408 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1415 elsif ($input->{fd}) {
1416 $io = io_new_fd($input->{fd});
1418 elsif ($input->{fh}) {
1419 unless (Scalar::Util::openhandle($input->{fh})) {
1420 $self->_set_error("Handle in fh option not opened");
1423 $io = Imager::IO->new_fh($input->{fh});
1425 elsif ($input->{file}) {
1426 my $fh = new IO::File($input->{file},"w+");
1428 $self->_set_error("Could not open file $input->{file}: $!");
1431 binmode($fh) or die;
1432 $io = io_new_fd(fileno($fh));
1435 elsif ($input->{data}) {
1436 $io = io_new_bufchain();
1438 elsif ($input->{callback} || $input->{writecb}) {
1439 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1442 $io = io_new_cb($input->{callback} || $input->{writecb},
1444 $input->{seekcb}, $input->{closecb});
1447 $self->_set_error("file/fd/fh/data/callback parameter missing");
1451 unless ($buffered) {
1452 $io->set_buffered(0);
1455 return ($io, @extras);
1458 # Read an image from file
1464 if (defined($self->{IMG})) {
1465 # let IIM_DESTROY do the destruction, since the image may be
1466 # referenced from elsewhere
1467 #i_img_destroy($self->{IMG});
1468 undef($self->{IMG});
1471 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1473 my $type = $input{'type'};
1475 $type = i_test_format_probe($IO, -1);
1478 if ($input{file} && !$type) {
1480 $type = $FORMATGUESS->($input{file});
1484 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1485 $input{file} and $msg .= " or file name";
1486 $self->_set_error($msg);
1490 _reader_autoload($type);
1492 if ($readers{$type} && $readers{$type}{single}) {
1493 return $readers{$type}{single}->($self, $IO, %input);
1496 unless ($formats_low{$type}) {
1497 my $read_types = join ', ', sort Imager->read_types();
1498 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1502 my $allow_incomplete = $input{allow_incomplete};
1503 defined $allow_incomplete or $allow_incomplete = 0;
1505 if ( $type eq 'pnm' ) {
1506 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1507 if ( !defined($self->{IMG}) ) {
1508 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1511 $self->{DEBUG} && print "loading a pnm file\n";
1515 if ( $type eq 'bmp' ) {
1516 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1517 if ( !defined($self->{IMG}) ) {
1518 $self->{ERRSTR}=$self->_error_as_msg();
1521 $self->{DEBUG} && print "loading a bmp file\n";
1524 if ( $type eq 'tga' ) {
1525 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1526 if ( !defined($self->{IMG}) ) {
1527 $self->{ERRSTR}=$self->_error_as_msg();
1530 $self->{DEBUG} && print "loading a tga file\n";
1533 if ( $type eq 'raw' ) {
1534 unless ( $input{xsize} && $input{ysize} ) {
1535 $self->_set_error('missing xsize or ysize parameter for raw');
1539 my $interleave = _first($input{raw_interleave}, $input{interleave});
1540 unless (defined $interleave) {
1541 my @caller = caller;
1542 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1545 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1546 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1548 $self->{IMG} = i_readraw_wiol( $IO,
1554 if ( !defined($self->{IMG}) ) {
1555 $self->{ERRSTR}=$self->_error_as_msg();
1558 $self->{DEBUG} && print "loading a raw file\n";
1564 sub register_reader {
1565 my ($class, %opts) = @_;
1568 or die "register_reader called with no type parameter\n";
1570 my $type = $opts{type};
1572 defined $opts{single} || defined $opts{multiple}
1573 or die "register_reader called with no single or multiple parameter\n";
1575 $readers{$type} = { };
1576 if ($opts{single}) {
1577 $readers{$type}{single} = $opts{single};
1579 if ($opts{multiple}) {
1580 $readers{$type}{multiple} = $opts{multiple};
1586 sub register_writer {
1587 my ($class, %opts) = @_;
1590 or die "register_writer called with no type parameter\n";
1592 my $type = $opts{type};
1594 defined $opts{single} || defined $opts{multiple}
1595 or die "register_writer called with no single or multiple parameter\n";
1597 $writers{$type} = { };
1598 if ($opts{single}) {
1599 $writers{$type}{single} = $opts{single};
1601 if ($opts{multiple}) {
1602 $writers{$type}{multiple} = $opts{multiple};
1613 grep($file_formats{$_}, keys %formats),
1614 qw(ico sgi), # formats not handled directly, but supplied with Imager
1625 grep($file_formats{$_}, keys %formats),
1626 qw(ico sgi), # formats not handled directly, but supplied with Imager
1633 my ($file, $error) = @_;
1635 if ($attempted_to_load{$file}) {
1636 if ($file_load_errors{$file}) {
1637 $$error = $file_load_errors{$file};
1645 local $SIG{__DIE__};
1647 ++$attempted_to_load{$file};
1655 my $work = $@ || "Unknown error";
1657 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1658 $work =~ s/\n/\\n/g;
1659 $work =~ s/\s*\.?\z/ loading $file/;
1660 $file_load_errors{$file} = $work;
1667 # probes for an Imager::File::whatever module
1668 sub _reader_autoload {
1671 return if $formats_low{$type} || $readers{$type};
1673 return unless $type =~ /^\w+$/;
1675 my $file = "Imager/File/\U$type\E.pm";
1678 my $loaded = _load_file($file, \$error);
1679 if (!$loaded && $error =~ /^Can't locate /) {
1680 my $filer = "Imager/File/\U$type\EReader.pm";
1681 $loaded = _load_file($filer, \$error);
1682 if ($error =~ /^Can't locate /) {
1683 $error = "Can't locate $file or $filer";
1687 $reader_load_errors{$type} = $error;
1691 # probes for an Imager::File::whatever module
1692 sub _writer_autoload {
1695 return if $formats_low{$type} || $writers{$type};
1697 return unless $type =~ /^\w+$/;
1699 my $file = "Imager/File/\U$type\E.pm";
1702 my $loaded = _load_file($file, \$error);
1703 if (!$loaded && $error =~ /^Can't locate /) {
1704 my $filew = "Imager/File/\U$type\EWriter.pm";
1705 $loaded = _load_file($filew, \$error);
1706 if ($error =~ /^Can't locate /) {
1707 $error = "Can't locate $file or $filew";
1711 $writer_load_errors{$type} = $error;
1715 sub _fix_gif_positions {
1716 my ($opts, $opt, $msg, @imgs) = @_;
1718 my $positions = $opts->{'gif_positions'};
1720 for my $pos (@$positions) {
1721 my ($x, $y) = @$pos;
1722 my $img = $imgs[$index++];
1723 $img->settag(name=>'gif_left', value=>$x);
1724 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1726 $$msg .= "replaced with the gif_left and gif_top tags";
1731 gif_each_palette=>'gif_local_map',
1732 interlace => 'gif_interlace',
1733 gif_delays => 'gif_delay',
1734 gif_positions => \&_fix_gif_positions,
1735 gif_loop_count => 'gif_loop',
1738 # options that should be converted to colors
1739 my %color_opts = map { $_ => 1 } qw/i_background/;
1742 my ($self, $opts, $prefix, @imgs) = @_;
1744 for my $opt (keys %$opts) {
1746 if ($obsolete_opts{$opt}) {
1747 my $new = $obsolete_opts{$opt};
1748 my $msg = "Obsolete option $opt ";
1750 $new->($opts, $opt, \$msg, @imgs);
1753 $msg .= "replaced with the $new tag ";
1756 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1757 warn $msg if $warn_obsolete && $^W;
1759 next unless $tagname =~ /^\Q$prefix/;
1760 my $value = $opts->{$opt};
1761 if ($color_opts{$opt}) {
1762 $value = _color($value);
1764 $self->_set_error($Imager::ERRSTR);
1769 if (UNIVERSAL::isa($value, "Imager::Color")) {
1770 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1771 for my $img (@imgs) {
1772 $img->settag(name=>$tagname, value=>$tag);
1775 elsif (ref($value) eq 'ARRAY') {
1776 for my $i (0..$#$value) {
1777 my $val = $value->[$i];
1779 if (UNIVERSAL::isa($val, "Imager::Color")) {
1780 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1782 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1785 $self->_set_error("Unknown reference type " . ref($value) .
1786 " supplied in array for $opt");
1792 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1797 $self->_set_error("Unknown reference type " . ref($value) .
1798 " supplied for $opt");
1803 # set it as a tag for every image
1804 for my $img (@imgs) {
1805 $img->settag(name=>$tagname, value=>$value);
1813 # Write an image to file
1816 my %input=(jpegquality=>75,
1826 $self->_valid_image("write")
1829 $self->_set_opts(\%input, "i_", $self)
1832 my $type = $input{'type'};
1833 if (!$type and $input{file}) {
1834 $type = $FORMATGUESS->($input{file});
1837 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1841 _writer_autoload($type);
1844 if ($writers{$type} && $writers{$type}{single}) {
1845 ($IO, $fh) = $self->_get_writer_io(\%input)
1848 $writers{$type}{single}->($self, $IO, %input, type => $type)
1852 if (!$formats_low{$type}) {
1853 my $write_types = join ', ', sort Imager->write_types();
1854 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1858 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1861 if ( $type eq 'pnm' ) {
1862 $self->_set_opts(\%input, "pnm_", $self)
1864 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1865 $self->{ERRSTR} = $self->_error_as_msg();
1868 $self->{DEBUG} && print "writing a pnm file\n";
1870 elsif ( $type eq 'raw' ) {
1871 $self->_set_opts(\%input, "raw_", $self)
1873 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1874 $self->{ERRSTR} = $self->_error_as_msg();
1877 $self->{DEBUG} && print "writing a raw file\n";
1879 elsif ( $type eq 'bmp' ) {
1880 $self->_set_opts(\%input, "bmp_", $self)
1882 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1883 $self->{ERRSTR} = $self->_error_as_msg;
1886 $self->{DEBUG} && print "writing a bmp file\n";
1888 elsif ( $type eq 'tga' ) {
1889 $self->_set_opts(\%input, "tga_", $self)
1892 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1893 $self->{ERRSTR}=$self->_error_as_msg();
1896 $self->{DEBUG} && print "writing a tga file\n";
1900 if (exists $input{'data'}) {
1901 my $data = io_slurp($IO);
1903 $self->{ERRSTR}='Could not slurp from buffer';
1906 ${$input{data}} = $data;
1912 my ($class, $opts, @images) = @_;
1914 my $type = $opts->{type};
1916 if (!$type && $opts->{'file'}) {
1917 $type = $FORMATGUESS->($opts->{'file'});
1920 $class->_set_error('type parameter missing and not possible to guess from extension');
1923 # translate to ImgRaw
1925 for my $img (@images) {
1926 unless ($img->_valid_image("write_multi")) {
1927 $class->_set_error($img->errstr . " (image $index)");
1932 $class->_set_opts($opts, "i_", @images)
1934 my @work = map $_->{IMG}, @images;
1936 _writer_autoload($type);
1939 if ($writers{$type} && $writers{$type}{multiple}) {
1940 ($IO, $file) = $class->_get_writer_io($opts, $type)
1943 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1947 if (!$formats{$type}) {
1948 my $write_types = join ', ', sort Imager->write_types();
1949 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1953 ($IO, $file) = $class->_get_writer_io($opts, $type)
1956 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1960 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1965 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1971 if (exists $opts->{'data'}) {
1972 my $data = io_slurp($IO);
1974 Imager->_set_error('Could not slurp from buffer');
1977 ${$opts->{data}} = $data;
1982 # read multiple images from a file
1984 my ($class, %opts) = @_;
1986 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1989 my $type = $opts{'type'};
1991 $type = i_test_format_probe($IO, -1);
1994 if ($opts{file} && !$type) {
1996 $type = $FORMATGUESS->($opts{file});
2000 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2001 $opts{file} and $msg .= " or file name";
2002 Imager->_set_error($msg);
2006 _reader_autoload($type);
2008 if ($readers{$type} && $readers{$type}{multiple}) {
2009 return $readers{$type}{multiple}->($IO, %opts);
2012 unless ($formats{$type}) {
2013 my $read_types = join ', ', sort Imager->read_types();
2014 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2019 if ($type eq 'pnm') {
2020 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2023 my $img = Imager->new;
2024 if ($img->read(%opts, io => $IO, type => $type)) {
2027 Imager->_set_error($img->errstr);
2032 $ERRSTR = _error_as_msg();
2036 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2040 # Destroy an Imager object
2044 # delete $instances{$self};
2045 if (defined($self->{IMG})) {
2046 # the following is now handled by the XS DESTROY method for
2047 # Imager::ImgRaw object
2048 # Re-enabling this will break virtual images
2049 # tested for in t/t020masked.t
2050 # i_img_destroy($self->{IMG});
2051 undef($self->{IMG});
2053 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2057 # Perform an inplace filter of an image
2058 # that is the image will be overwritten with the data
2065 $self->_valid_image("filter")
2068 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2070 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2071 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2074 if ($filters{$input{'type'}}{names}) {
2075 my $names = $filters{$input{'type'}}{names};
2076 for my $name (keys %$names) {
2077 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2078 $input{$name} = $names->{$name}{$input{$name}};
2082 if (defined($filters{$input{'type'}}{defaults})) {
2083 %hsh=( image => $self->{IMG},
2085 %{$filters{$input{'type'}}{defaults}},
2088 %hsh=( image => $self->{IMG},
2093 my @cs=@{$filters{$input{'type'}}{callseq}};
2096 if (!defined($hsh{$_})) {
2097 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2102 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2103 &{$filters{$input{'type'}}{callsub}}(%hsh);
2106 chomp($self->{ERRSTR} = $@);
2112 $self->{DEBUG} && print "callseq is: @cs\n";
2113 $self->{DEBUG} && print "matching callseq is: @b\n";
2118 sub register_filter {
2120 my %hsh = ( defaults => {}, @_ );
2123 or die "register_filter() with no type\n";
2124 defined $hsh{callsub}
2125 or die "register_filter() with no callsub\n";
2126 defined $hsh{callseq}
2127 or die "register_filter() with no callseq\n";
2129 exists $filters{$hsh{type}}
2132 $filters{$hsh{type}} = \%hsh;
2137 sub scale_calculate {
2140 my %opts = ('type'=>'max', @_);
2142 # none of these should be references
2143 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2144 if (defined $opts{$name} && ref $opts{$name}) {
2145 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2150 my ($x_scale, $y_scale);
2151 my $width = $opts{width};
2152 my $height = $opts{height};
2154 defined $width or $width = $self->getwidth;
2155 defined $height or $height = $self->getheight;
2158 unless (defined $width && defined $height) {
2159 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2164 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2165 $x_scale = $opts{'xscalefactor'};
2166 $y_scale = $opts{'yscalefactor'};
2168 elsif ($opts{'xscalefactor'}) {
2169 $x_scale = $opts{'xscalefactor'};
2170 $y_scale = $opts{'scalefactor'} || $x_scale;
2172 elsif ($opts{'yscalefactor'}) {
2173 $y_scale = $opts{'yscalefactor'};
2174 $x_scale = $opts{'scalefactor'} || $y_scale;
2177 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2180 # work out the scaling
2181 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2182 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2183 $opts{ypixels} / $height );
2184 if ($opts{'type'} eq 'min') {
2185 $x_scale = $y_scale = _min($xpix,$ypix);
2187 elsif ($opts{'type'} eq 'max') {
2188 $x_scale = $y_scale = _max($xpix,$ypix);
2190 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2195 $self->_set_error('invalid value for type parameter');
2198 } elsif ($opts{xpixels}) {
2199 $x_scale = $y_scale = $opts{xpixels} / $width;
2201 elsif ($opts{ypixels}) {
2202 $x_scale = $y_scale = $opts{ypixels}/$height;
2204 elsif ($opts{constrain} && ref $opts{constrain}
2205 && $opts{constrain}->can('constrain')) {
2206 # we've been passed an Image::Math::Constrain object or something
2207 # that looks like one
2209 (undef, undef, $scalefactor)
2210 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2211 unless ($scalefactor) {
2212 $self->_set_error('constrain method failed on constrain parameter');
2215 $x_scale = $y_scale = $scalefactor;
2218 my $new_width = int($x_scale * $width + 0.5);
2219 $new_width > 0 or $new_width = 1;
2220 my $new_height = int($y_scale * $height + 0.5);
2221 $new_height > 0 or $new_height = 1;
2223 return ($x_scale, $y_scale, $new_width, $new_height);
2227 # Scale an image to requested size and return the scaled version
2231 my %opts = (qtype=>'normal' ,@_);
2232 my $img = Imager->new();
2233 my $tmp = Imager->new();
2235 unless (defined wantarray) {
2236 my @caller = caller;
2237 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2241 $self->_valid_image("scale")
2244 my ($x_scale, $y_scale, $new_width, $new_height) =
2245 $self->scale_calculate(%opts)
2248 if ($opts{qtype} eq 'normal') {
2249 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2250 if ( !defined($tmp->{IMG}) ) {
2251 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2254 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2255 if ( !defined($img->{IMG}) ) {
2256 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2262 elsif ($opts{'qtype'} eq 'preview') {
2263 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2264 if ( !defined($img->{IMG}) ) {
2265 $self->{ERRSTR}='unable to scale image';
2270 elsif ($opts{'qtype'} eq 'mixing') {
2271 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2272 unless ($img->{IMG}) {
2273 $self->_set_error(Imager->_error_as_msg);
2279 $self->_set_error('invalid value for qtype parameter');
2284 # Scales only along the X axis
2288 my %opts = ( scalefactor=>0.5, @_ );
2290 unless (defined wantarray) {
2291 my @caller = caller;
2292 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2296 $self->_valid_image("scaleX")
2299 my $img = Imager->new();
2301 my $scalefactor = $opts{scalefactor};
2303 if ($opts{pixels}) {
2304 $scalefactor = $opts{pixels} / $self->getwidth();
2307 unless ($self->{IMG}) {
2308 $self->{ERRSTR}='empty input image';
2312 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2314 if ( !defined($img->{IMG}) ) {
2315 $self->{ERRSTR} = 'unable to scale image';
2322 # Scales only along the Y axis
2326 my %opts = ( scalefactor => 0.5, @_ );
2328 unless (defined wantarray) {
2329 my @caller = caller;
2330 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2334 $self->_valid_image("scaleY")
2337 my $img = Imager->new();
2339 my $scalefactor = $opts{scalefactor};
2341 if ($opts{pixels}) {
2342 $scalefactor = $opts{pixels} / $self->getheight();
2345 unless ($self->{IMG}) {
2346 $self->{ERRSTR} = 'empty input image';
2349 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2351 if ( !defined($img->{IMG}) ) {
2352 $self->{ERRSTR} = 'unable to scale image';
2359 # Transform returns a spatial transformation of the input image
2360 # this moves pixels to a new location in the returned image.
2361 # NOTE - should make a utility function to check transforms for
2367 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2369 # print Dumper(\%opts);
2372 $self->_valid_image("transform")
2375 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2377 eval ("use Affix::Infix2Postfix;");
2380 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2383 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2384 {op=>'-',trans=>'Sub'},
2385 {op=>'*',trans=>'Mult'},
2386 {op=>'/',trans=>'Div'},
2387 {op=>'-','type'=>'unary',trans=>'u-'},
2389 {op=>'func','type'=>'unary'}],
2390 'grouping'=>[qw( \( \) )],
2391 'func'=>[qw( sin cos )],
2396 @xt=$I2P->translate($opts{'xexpr'});
2397 @yt=$I2P->translate($opts{'yexpr'});
2399 $numre=$I2P->{'numre'};
2402 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2403 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2404 @{$opts{'parm'}}=@pt;
2407 # print Dumper(\%opts);
2409 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2410 $self->{ERRSTR}='transform: no xopcodes given.';
2414 @op=@{$opts{'xopcodes'}};
2416 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2417 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2420 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2426 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2427 $self->{ERRSTR}='transform: no yopcodes given.';
2431 @op=@{$opts{'yopcodes'}};
2433 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2434 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2437 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2442 if ( !exists $opts{'parm'}) {
2443 $self->{ERRSTR}='transform: no parameter arg given.';
2447 # print Dumper(\@ropx);
2448 # print Dumper(\@ropy);
2449 # print Dumper(\@ropy);
2451 my $img = Imager->new();
2452 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2453 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2459 my ($opts, @imgs) = @_;
2461 require "Imager/Expr.pm";
2463 $opts->{variables} = [ qw(x y) ];
2464 my ($width, $height) = @{$opts}{qw(width height)};
2467 for my $img (@imgs) {
2468 unless ($img->_valid_image("transform2")) {
2469 Imager->_set_error($img->errstr . " (input image $index)");
2475 $width ||= $imgs[0]->getwidth();
2476 $height ||= $imgs[0]->getheight();
2478 for my $img (@imgs) {
2479 $opts->{constants}{"w$img_num"} = $img->getwidth();
2480 $opts->{constants}{"h$img_num"} = $img->getheight();
2481 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2482 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2487 $opts->{constants}{w} = $width;
2488 $opts->{constants}{cx} = $width/2;
2491 $Imager::ERRSTR = "No width supplied";
2495 $opts->{constants}{h} = $height;
2496 $opts->{constants}{cy} = $height/2;
2499 $Imager::ERRSTR = "No height supplied";
2502 my $code = Imager::Expr->new($opts);
2504 $Imager::ERRSTR = Imager::Expr::error();
2507 my $channels = $opts->{channels} || 3;
2508 unless ($channels >= 1 && $channels <= 4) {
2509 return Imager->_set_error("channels must be an integer between 1 and 4");
2512 my $img = Imager->new();
2513 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2514 $channels, $code->code(),
2515 $code->nregs(), $code->cregs(),
2516 [ map { $_->{IMG} } @imgs ]);
2517 if (!defined $img->{IMG}) {
2518 $Imager::ERRSTR = Imager->_error_as_msg();
2529 $self->_valid_image("rubthrough")
2532 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2533 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2537 %opts = (src_minx => 0,
2539 src_maxx => $opts{src}->getwidth(),
2540 src_maxy => $opts{src}->getheight(),
2544 defined $tx or $tx = $opts{left};
2545 defined $tx or $tx = 0;
2548 defined $ty or $ty = $opts{top};
2549 defined $ty or $ty = 0;
2551 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2552 $opts{src_minx}, $opts{src_miny},
2553 $opts{src_maxx}, $opts{src_maxy})) {
2554 $self->_set_error($self->_error_as_msg());
2571 $self->_valid_image("compose")
2574 unless ($opts{src}) {
2575 $self->_set_error("compose: src parameter missing");
2579 unless ($opts{src}->_valid_image("compose")) {
2580 $self->_set_error($opts{src}->errstr . " (for src)");
2583 my $src = $opts{src};
2585 my $left = $opts{left};
2586 defined $left or $left = $opts{tx};
2587 defined $left or $left = 0;
2589 my $top = $opts{top};
2590 defined $top or $top = $opts{ty};
2591 defined $top or $top = 0;
2593 my $src_left = $opts{src_left};
2594 defined $src_left or $src_left = $opts{src_minx};
2595 defined $src_left or $src_left = 0;
2597 my $src_top = $opts{src_top};
2598 defined $src_top or $src_top = $opts{src_miny};
2599 defined $src_top or $src_top = 0;
2601 my $width = $opts{width};
2602 if (!defined $width && defined $opts{src_maxx}) {
2603 $width = $opts{src_maxx} - $src_left;
2605 defined $width or $width = $src->getwidth() - $src_left;
2607 my $height = $opts{height};
2608 if (!defined $height && defined $opts{src_maxy}) {
2609 $height = $opts{src_maxy} - $src_top;
2611 defined $height or $height = $src->getheight() - $src_top;
2613 my $combine = $self->_combine($opts{combine}, 'normal');
2616 unless ($opts{mask}->_valid_image("compose")) {
2617 $self->_set_error($opts{mask}->errstr . " (for mask)");
2621 my $mask_left = $opts{mask_left};
2622 defined $mask_left or $mask_left = $opts{mask_minx};
2623 defined $mask_left or $mask_left = 0;
2625 my $mask_top = $opts{mask_top};
2626 defined $mask_top or $mask_top = $opts{mask_miny};
2627 defined $mask_top or $mask_top = 0;
2629 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2630 $left, $top, $src_left, $src_top,
2631 $mask_left, $mask_top, $width, $height,
2632 $combine, $opts{opacity})) {
2633 $self->_set_error(Imager->_error_as_msg);
2638 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2639 $width, $height, $combine, $opts{opacity})) {
2640 $self->_set_error(Imager->_error_as_msg);
2652 $self->_valid_image("flip")
2655 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2657 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2658 $dir = $xlate{$opts{'dir'}};
2659 return $self if i_flipxy($self->{IMG}, $dir);
2667 unless (defined wantarray) {
2668 my @caller = caller;
2669 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2673 $self->_valid_image("rotate")
2676 if (defined $opts{right}) {
2677 my $degrees = $opts{right};
2679 $degrees += 360 * int(((-$degrees)+360)/360);
2681 $degrees = $degrees % 360;
2682 if ($degrees == 0) {
2683 return $self->copy();
2685 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2686 my $result = Imager->new();
2687 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2691 $self->{ERRSTR} = $self->_error_as_msg();
2696 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2700 elsif (defined $opts{radians} || defined $opts{degrees}) {
2701 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2703 my $back = $opts{back};
2704 my $result = Imager->new;
2706 $back = _color($back);
2708 $self->_set_error(Imager->errstr);
2712 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2715 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2717 if ($result->{IMG}) {
2721 $self->{ERRSTR} = $self->_error_as_msg();
2726 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2731 sub matrix_transform {
2735 $self->_valid_image("matrix_transform")
2738 unless (defined wantarray) {
2739 my @caller = caller;
2740 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2744 if ($opts{matrix}) {
2745 my $xsize = $opts{xsize} || $self->getwidth;
2746 my $ysize = $opts{ysize} || $self->getheight;
2748 my $result = Imager->new;
2750 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2751 $opts{matrix}, $opts{back})
2755 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2763 $self->{ERRSTR} = "matrix parameter required";
2769 *yatf = \&matrix_transform;
2771 # These two are supported for legacy code only
2774 return Imager::Color->new(@_);
2778 return Imager::Color::set(@_);
2781 # Draws a box between the specified corner points.
2784 my $raw = $self->{IMG};
2786 $self->_valid_image("box")
2791 my ($xmin, $ymin, $xmax, $ymax);
2792 if (exists $opts{'box'}) {
2793 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2794 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2795 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2796 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2799 defined($xmin = $opts{xmin}) or $xmin = 0;
2800 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2801 defined($ymin = $opts{ymin}) or $ymin = 0;
2802 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2805 if ($opts{filled}) {
2806 my $color = $opts{'color'};
2808 if (defined $color) {
2809 unless (_is_color_object($color)) {
2810 $color = _color($color);
2812 $self->{ERRSTR} = $Imager::ERRSTR;
2818 $color = i_color_new(255,255,255,255);
2821 if ($color->isa("Imager::Color")) {
2822 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2825 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2828 elsif ($opts{fill}) {
2829 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2830 # assume it's a hash ref
2831 require 'Imager/Fill.pm';
2832 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2833 $self->{ERRSTR} = $Imager::ERRSTR;
2837 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2840 my $color = $opts{'color'};
2841 if (defined $color) {
2842 unless (_is_color_object($color)) {
2843 $color = _color($color);
2845 $self->{ERRSTR} = $Imager::ERRSTR;
2851 $color = i_color_new(255, 255, 255, 255);
2854 $self->{ERRSTR} = $Imager::ERRSTR;
2857 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2866 $self->_valid_image("arc")
2869 my $dflcl= [ 255, 255, 255, 255];
2874 'r'=>_min($self->getwidth(),$self->getheight())/3,
2875 'x'=>$self->getwidth()/2,
2876 'y'=>$self->getheight()/2,
2883 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2884 # assume it's a hash ref
2885 require 'Imager/Fill.pm';
2886 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2887 $self->{ERRSTR} = $Imager::ERRSTR;
2891 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2892 $opts{'d2'}, $opts{fill}{fill});
2894 elsif ($opts{filled}) {
2895 my $color = _color($opts{'color'});
2897 $self->{ERRSTR} = $Imager::ERRSTR;
2900 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2901 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2905 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2906 $opts{'d1'}, $opts{'d2'}, $color);
2910 my $color = _color($opts{'color'});
2911 if ($opts{d2} - $opts{d1} >= 360) {
2912 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2915 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2921 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2922 # assume it's a hash ref
2923 require 'Imager/Fill.pm';
2924 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2925 $self->{ERRSTR} = $Imager::ERRSTR;
2929 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2930 $opts{'d2'}, $opts{fill}{fill});
2933 my $color = _color($opts{'color'});
2935 $self->{ERRSTR} = $Imager::ERRSTR;
2938 if ($opts{filled}) {
2939 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2940 $opts{'d1'}, $opts{'d2'}, $color);
2943 if ($opts{d1} == 0 && $opts{d2} == 361) {
2944 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2947 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2953 $self->_set_error($self->_error_as_msg);
2960 # Draws a line from one point to the other
2961 # the endpoint is set if the endp parameter is set which it is by default.
2962 # to turn of the endpoint being set use endp=>0 when calling line.
2966 my $dflcl=i_color_new(0,0,0,0);
2967 my %opts=(color=>$dflcl,
2971 $self->_valid_image("line")
2974 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2975 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2977 my $color = _color($opts{'color'});
2979 $self->{ERRSTR} = $Imager::ERRSTR;
2983 $opts{antialias} = $opts{aa} if defined $opts{aa};
2984 if ($opts{antialias}) {
2985 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2986 $color, $opts{endp});
2988 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2989 $color, $opts{endp});
2994 # Draws a line between an ordered set of points - It more or less just transforms this
2995 # into a list of lines.
2999 my ($pt,$ls,@points);
3000 my $dflcl=i_color_new(0,0,0,0);
3001 my %opts=(color=>$dflcl,@_);
3003 $self->_valid_image("polyline")
3006 if (exists($opts{points})) { @points=@{$opts{points}}; }
3007 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3008 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3011 # print Dumper(\@points);
3013 my $color = _color($opts{'color'});
3015 $self->{ERRSTR} = $Imager::ERRSTR;
3018 $opts{antialias} = $opts{aa} if defined $opts{aa};
3019 if ($opts{antialias}) {
3022 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3029 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3039 my ($pt,$ls,@points);
3040 my $dflcl = i_color_new(0,0,0,0);
3041 my %opts = (color=>$dflcl, @_);
3043 $self->_valid_image("polygon")
3046 if (exists($opts{points})) {
3047 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3048 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3051 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3052 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3055 if ($opts{'fill'}) {
3056 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3057 # assume it's a hash ref
3058 require 'Imager/Fill.pm';
3059 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3060 $self->{ERRSTR} = $Imager::ERRSTR;
3064 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
3065 $opts{'fill'}{'fill'});
3068 my $color = _color($opts{'color'});
3070 $self->{ERRSTR} = $Imager::ERRSTR;
3073 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3080 # this the multipoint bezier curve
3081 # this is here more for testing that actual usage since
3082 # this is not a good algorithm. Usually the curve would be
3083 # broken into smaller segments and each done individually.
3087 my ($pt,$ls,@points);
3088 my $dflcl=i_color_new(0,0,0,0);
3089 my %opts=(color=>$dflcl,@_);
3091 $self->_valid_image("polybezier")
3094 if (exists $opts{points}) {
3095 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3096 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3099 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3100 $self->{ERRSTR}='Missing or invalid points.';
3104 my $color = _color($opts{'color'});
3106 $self->{ERRSTR} = $Imager::ERRSTR;
3109 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3115 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3118 $self->_valid_image("flood_fill")
3121 unless (exists $opts{'x'} && exists $opts{'y'}) {
3122 $self->{ERRSTR} = "missing seed x and y parameters";
3126 if ($opts{border}) {
3127 my $border = _color($opts{border});
3129 $self->_set_error($Imager::ERRSTR);
3133 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3134 # assume it's a hash ref
3135 require Imager::Fill;
3136 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3137 $self->{ERRSTR} = $Imager::ERRSTR;
3141 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3142 $opts{fill}{fill}, $border);
3145 my $color = _color($opts{'color'});
3147 $self->{ERRSTR} = $Imager::ERRSTR;
3150 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3157 $self->{ERRSTR} = $self->_error_as_msg();
3163 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3164 # assume it's a hash ref
3165 require 'Imager/Fill.pm';
3166 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3167 $self->{ERRSTR} = $Imager::ERRSTR;
3171 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3174 my $color = _color($opts{'color'});
3176 $self->{ERRSTR} = $Imager::ERRSTR;
3179 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3185 $self->{ERRSTR} = $self->_error_as_msg();
3192 my ($self, %opts) = @_;
3194 $self->_valid_image("setpixel")
3197 my $color = $opts{color};
3198 unless (defined $color) {
3199 $color = $self->{fg};
3200 defined $color or $color = NC(255, 255, 255);
3203 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3204 unless ($color = _color($color, 'setpixel')) {
3205 $self->_set_error("setpixel: " . Imager->errstr);
3210 unless (exists $opts{'x'} && exists $opts{'y'}) {
3211 $self->_set_error('setpixel: missing x or y parameter');
3217 if (ref $x || ref $y) {
3218 $x = ref $x ? $x : [ $x ];
3219 $y = ref $y ? $y : [ $y ];
3221 $self->_set_error("setpixel: x is a reference to an empty array");
3225 $self->_set_error("setpixel: y is a reference to an empty array");
3229 # make both the same length, replicating the last element
3231 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3234 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3238 if ($color->isa('Imager::Color')) {
3239 for my $i (0..$#$x) {
3240 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3245 for my $i (0..$#$x) {
3246 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3254 if ($color->isa('Imager::Color')) {
3255 i_ppix($self->{IMG}, $x, $y, $color)
3256 and return "0 but true";
3259 i_ppixf($self->{IMG}, $x, $y, $color)
3260 and return "0 but true";
3270 my %opts = ( "type"=>'8bit', @_);
3272 $self->_valid_image("getpixel")
3275 unless (exists $opts{'x'} && exists $opts{'y'}) {
3276 $self->_set_error('getpixel: missing x or y parameter');
3282 my $type = $opts{'type'};
3283 if (ref $x || ref $y) {
3284 $x = ref $x ? $x : [ $x ];
3285 $y = ref $y ? $y : [ $y ];
3287 $self->_set_error("getpixel: x is a reference to an empty array");
3291 $self->_set_error("getpixel: y is a reference to an empty array");
3295 # make both the same length, replicating the last element
3297 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3300 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3304 if ($type eq '8bit') {
3305 for my $i (0..$#$x) {
3306 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3309 elsif ($type eq 'float' || $type eq 'double') {
3310 for my $i (0..$#$x) {
3311 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3315 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3318 return wantarray ? @result : \@result;
3321 if ($type eq '8bit') {
3322 return i_get_pixel($self->{IMG}, $x, $y);
3324 elsif ($type eq 'float' || $type eq 'double') {
3325 return i_gpixf($self->{IMG}, $x, $y);
3328 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3336 my %opts = ( type => '8bit', x=>0, @_);
3338 $self->_valid_image("getscanline")
3341 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3343 unless (defined $opts{'y'}) {
3344 $self->_set_error("missing y parameter");
3348 if ($opts{type} eq '8bit') {
3349 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3352 elsif ($opts{type} eq 'float') {
3353 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3356 elsif ($opts{type} eq 'index') {
3357 unless (i_img_type($self->{IMG})) {
3358 $self->_set_error("type => index only valid on paletted images");
3361 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3365 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3372 my %opts = ( x=>0, @_);
3374 $self->_valid_image("setscanline")
3377 unless (defined $opts{'y'}) {
3378 $self->_set_error("missing y parameter");
3383 if (ref $opts{pixels} && @{$opts{pixels}}) {
3384 # try to guess the type
3385 if ($opts{pixels}[0]->isa('Imager::Color')) {
3386 $opts{type} = '8bit';
3388 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3389 $opts{type} = 'float';
3392 $self->_set_error("missing type parameter and could not guess from pixels");
3398 $opts{type} = '8bit';
3402 if ($opts{type} eq '8bit') {
3403 if (ref $opts{pixels}) {
3404 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3407 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3410 elsif ($opts{type} eq 'float') {
3411 if (ref $opts{pixels}) {
3412 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3415 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3418 elsif ($opts{type} eq 'index') {
3419 if (ref $opts{pixels}) {
3420 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3423 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3427 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3434 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3436 $self->_valid_image("getsamples")
3439 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3441 unless (defined $opts{'y'}) {
3442 $self->_set_error("missing y parameter");
3446 if ($opts{target}) {
3447 my $target = $opts{target};
3448 my $offset = $opts{offset};
3449 if ($opts{type} eq '8bit') {
3450 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3451 $opts{y}, $opts{channels})
3453 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3454 return scalar(@samples);
3456 elsif ($opts{type} eq 'float') {
3457 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3458 $opts{y}, $opts{channels});
3459 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3460 return scalar(@samples);
3462 elsif ($opts{type} =~ /^(\d+)bit$/) {
3466 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3467 $opts{y}, $bits, $target,
3468 $offset, $opts{channels});
3469 unless (defined $count) {
3470 $self->_set_error(Imager->_error_as_msg);
3477 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3482 if ($opts{type} eq '8bit') {
3483 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3484 $opts{y}, $opts{channels});
3486 elsif ($opts{type} eq 'float') {
3487 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3488 $opts{y}, $opts{channels});
3490 elsif ($opts{type} =~ /^(\d+)bit$/) {
3494 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3495 $opts{y}, $bits, \@data, 0, $opts{channels})
3500 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3509 $self->_valid_image("setsamples")
3512 my %opts = ( x => 0, offset => 0 );
3514 # avoid duplicating the data parameter, it may be a large scalar
3516 while ($i < @_ -1) {
3517 if ($_[$i] eq 'data') {
3521 $opts{$_[$i]} = $_[$i+1];
3527 unless(defined $data_index) {
3528 $self->_set_error('setsamples: data parameter missing');
3531 unless (defined $_[$data_index]) {
3532 $self->_set_error('setsamples: data parameter not defined');
3536 my $type = $opts{type};
3537 defined $type or $type = '8bit';
3539 my $width = defined $opts{width} ? $opts{width}
3540 : $self->getwidth() - $opts{x};
3543 if ($type eq '8bit') {
3544 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3545 $_[$data_index], $opts{offset}, $width);
3547 elsif ($type eq 'float') {
3548 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3549 $_[$data_index], $opts{offset}, $width);
3551 elsif ($type =~ /^([0-9]+)bit$/) {
3554 unless (ref $_[$data_index]) {
3555 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3559 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3560 $opts{channels}, $_[$data_index], $opts{offset},
3564 $self->_set_error('setsamples: type parameter invalid');
3568 unless (defined $count) {
3569 $self->_set_error(Imager->_error_as_msg);
3576 # make an identity matrix of the given size
3580 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3581 for my $c (0 .. ($size-1)) {
3582 $matrix->[$c][$c] = 1;
3587 # general function to convert an image
3589 my ($self, %opts) = @_;
3592 $self->_valid_image("convert")
3595 unless (defined wantarray) {
3596 my @caller = caller;
3597 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3601 # the user can either specify a matrix or preset
3602 # the matrix overrides the preset
3603 if (!exists($opts{matrix})) {
3604 unless (exists($opts{preset})) {
3605 $self->{ERRSTR} = "convert() needs a matrix or preset";
3609 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3610 # convert to greyscale, keeping the alpha channel if any
3611 if ($self->getchannels == 3) {
3612 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3614 elsif ($self->getchannels == 4) {
3615 # preserve the alpha channel
3616 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3621 $matrix = _identity($self->getchannels);
3624 elsif ($opts{preset} eq 'noalpha') {
3625 # strip the alpha channel
3626 if ($self->getchannels == 2 or $self->getchannels == 4) {
3627 $matrix = _identity($self->getchannels);
3628 pop(@$matrix); # lose the alpha entry
3631 $matrix = _identity($self->getchannels);
3634 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3636 $matrix = [ [ 1 ] ];
3638 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3639 $matrix = [ [ 0, 1 ] ];
3641 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3642 $matrix = [ [ 0, 0, 1 ] ];
3644 elsif ($opts{preset} eq 'alpha') {
3645 if ($self->getchannels == 2 or $self->getchannels == 4) {
3646 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3649 # the alpha is just 1 <shrug>
3650 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3653 elsif ($opts{preset} eq 'rgb') {
3654 if ($self->getchannels == 1) {
3655 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3657 elsif ($self->getchannels == 2) {
3658 # preserve the alpha channel
3659 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3662 $matrix = _identity($self->getchannels);
3665 elsif ($opts{preset} eq 'addalpha') {
3666 if ($self->getchannels == 1) {
3667 $matrix = _identity(2);
3669 elsif ($self->getchannels == 3) {
3670 $matrix = _identity(4);
3673 $matrix = _identity($self->getchannels);
3677 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3683 $matrix = $opts{matrix};
3686 my $new = Imager->new;
3687 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3688 unless ($new->{IMG}) {
3689 # most likely a bad matrix
3690 i_push_error(0, "convert");
3691 $self->{ERRSTR} = _error_as_msg();
3697 # combine channels from multiple input images, a class method
3699 my ($class, %opts) = @_;
3701 my $src = delete $opts{src};
3703 $class->_set_error("src parameter missing");
3708 for my $img (@$src) {
3709 unless (eval { $img->isa("Imager") }) {
3710 $class->_set_error("src must contain image objects");
3713 unless ($img->_valid_image("combine")) {
3714 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3717 push @imgs, $img->{IMG};
3720 if (my $channels = delete $opts{channels}) {
3721 $result = i_combine(\@imgs, $channels);
3724 $result = i_combine(\@imgs);
3727 $class->_set_error($class->_error_as_msg);
3731 my $img = $class->new;
3732 $img->{IMG} = $result;
3738 # general function to map an image through lookup tables
3741 my ($self, %opts) = @_;
3742 my @chlist = qw( red green blue alpha );
3744 $self->_valid_image("map")
3747 if (!exists($opts{'maps'})) {
3748 # make maps from channel maps
3750 for $chnum (0..$#chlist) {
3751 if (exists $opts{$chlist[$chnum]}) {
3752 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3753 } elsif (exists $opts{'all'}) {
3754 $opts{'maps'}[$chnum] = $opts{'all'};
3758 if ($opts{'maps'} and $self->{IMG}) {
3759 i_map($self->{IMG}, $opts{'maps'} );
3765 my ($self, %opts) = @_;
3767 $self->_valid_image("difference")
3770 defined $opts{mindist} or $opts{mindist} = 0;
3772 defined $opts{other}
3773 or return $self->_set_error("No 'other' parameter supplied");
3774 unless ($opts{other}->_valid_image("difference")) {
3775 $self->_set_error($opts{other}->errstr . " (other image)");
3779 my $result = Imager->new;
3780 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3782 or return $self->_set_error($self->_error_as_msg());
3787 # destructive border - image is shrunk by one pixel all around
3790 my ($self,%opts)=@_;
3791 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3792 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3796 # Get the width of an image
3801 $self->_valid_image("getwidth")
3804 return i_img_get_width($self->{IMG});
3807 # Get the height of an image
3812 $self->_valid_image("getheight")
3815 return i_img_get_height($self->{IMG});
3818 # Get number of channels in an image
3823 $self->_valid_image("getchannels")
3826 return i_img_getchannels($self->{IMG});
3834 $self->_valid_image("getmask")
3837 return i_img_getmask($self->{IMG});
3846 $self->_valid_image("setmask")
3849 unless (defined $opts{mask}) {
3850 $self->_set_error("mask parameter required");
3854 i_img_setmask( $self->{IMG} , $opts{mask} );
3859 # Get number of colors in an image
3863 my %opts=('maxcolors'=>2**30,@_);
3865 $self->_valid_image("getcolorcount")
3868 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3869 return ($rc==-1? undef : $rc);
3872 # Returns a reference to a hash. The keys are colour named (packed) and the
3873 # values are the number of pixels in this colour.
3874 sub getcolorusagehash {
3877 $self->_valid_image("getcolorusagehash")
3880 my %opts = ( maxcolors => 2**30, @_ );
3881 my $max_colors = $opts{maxcolors};
3882 unless (defined $max_colors && $max_colors > 0) {
3883 $self->_set_error('maxcolors must be a positive integer');
3887 my $channels= $self->getchannels;
3888 # We don't want to look at the alpha channel, because some gifs using it
3889 # doesn't define it for every colour (but only for some)
3890 $channels -= 1 if $channels == 2 or $channels == 4;
3892 my $height = $self->getheight;
3893 for my $y (0 .. $height - 1) {
3894 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3895 while (length $colors) {
3896 $color_use{ substr($colors, 0, $channels, '') }++;
3898 keys %color_use > $max_colors
3904 # This will return a ordered array of the colour usage. Kind of the sorted
3905 # version of the values of the hash returned by getcolorusagehash.
3906 # You might want to add safety checks and change the names, etc...
3910 $self->_valid_image("getcolorusage")
3913 my %opts = ( maxcolors => 2**30, @_ );
3914 my $max_colors = $opts{maxcolors};
3915 unless (defined $max_colors && $max_colors > 0) {
3916 $self->_set_error('maxcolors must be a positive integer');
3920 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3923 # draw string to an image
3928 $self->_valid_image("string")
3931 my %input=('x'=>0, 'y'=>0, @_);
3932 defined($input{string}) or $input{string} = $input{text};
3934 unless(defined $input{string}) {
3935 $self->{ERRSTR}="missing required parameter 'string'";
3939 unless($input{font}) {
3940 $self->{ERRSTR}="missing required parameter 'font'";
3944 unless ($input{font}->draw(image=>$self, %input)) {
3956 $self->_valid_image("align_string")
3965 my %input=('x'=>0, 'y'=>0, @_);
3966 defined $input{string}
3967 or $input{string} = $input{text};
3969 unless(exists $input{string}) {
3970 $self->_set_error("missing required parameter 'string'");
3974 unless($input{font}) {
3975 $self->_set_error("missing required parameter 'font'");
3980 unless (@result = $input{font}->align(image=>$img, %input)) {
3984 return wantarray ? @result : $result[0];
3987 my @file_limit_names = qw/width height bytes/;
3989 sub set_file_limits {
3996 @values{@file_limit_names} = (0) x @file_limit_names;
3999 @values{@file_limit_names} = i_get_image_file_limits();
4002 for my $key (keys %values) {
4003 defined $opts{$key} and $values{$key} = $opts{$key};
4006 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4009 sub get_file_limits {
4010 i_get_image_file_limits();
4013 my @check_args = qw(width height channels sample_size);
4015 sub check_file_limits {
4025 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4026 $opts{sample_size} = length(pack("d", 0));
4029 for my $name (@check_args) {
4030 unless (defined $opts{$name}) {
4031 $class->_set_error("check_file_limits: $name must be defined");
4034 unless ($opts{$name} == int($opts{$name})) {
4035 $class->_set_error("check_file_limits: $name must be a positive integer");
4040 my $result = i_int_check_image_file_limits(@opts{@check_args});
4042 $class->_set_error($class->_error_as_msg());
4048 # Shortcuts that can be exported
4050 sub newcolor { Imager::Color->new(@_); }
4051 sub newfont { Imager::Font->new(@_); }
4053 require Imager::Color::Float;
4054 return Imager::Color::Float->new(@_);
4057 *NC=*newcolour=*newcolor;
4064 #### Utility routines
4067 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4071 my ($self, $msg) = @_;
4074 $self->{ERRSTR} = $msg;
4082 # Default guess for the type of an image from extension
4084 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4088 ( map { $_ => $_ } @simple_types ),
4094 pnm => "pnm", # technically wrong, but historically it works in Imager
4107 sub def_guess_type {
4110 my ($ext) = $name =~ /\.([^.]+)$/
4113 my $type = $ext_types{$ext}
4120 return @combine_types;
4123 # get the minimum of a list
4127 for(@_) { if ($_<$mx) { $mx=$_; }}
4131 # get the maximum of a list
4135 for(@_) { if ($_>$mx) { $mx=$_; }}
4139 # string stuff for iptc headers
4143 $str = substr($str,3);
4144 $str =~ s/[\n\r]//g;
4151 # A little hack to parse iptc headers.
4156 my($caption,$photogr,$headln,$credit);
4158 my $str=$self->{IPTCRAW};
4163 @ar=split(/8BIM/,$str);
4168 @sar=split(/\034\002/);
4169 foreach $item (@sar) {
4170 if ($item =~ m/^x/) {
4171 $caption = _clean($item);
4174 if ($item =~ m/^P/) {
4175 $photogr = _clean($item);
4178 if ($item =~ m/^i/) {
4179 $headln = _clean($item);
4182 if ($item =~ m/^n/) {
4183 $credit = _clean($item);
4189 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4196 or die "Only C language supported";
4198 require Imager::ExtUtils;
4199 return Imager::ExtUtils->inline_config;
4202 # threads shouldn't try to close raw Imager objects
4203 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4206 # this serves two purposes:
4207 # - a class method to load the file support modules included with Imager
4208 # (or were included, once the library dependent modules are split out)
4209 # - something for Module::ScanDeps to analyze
4210 # https://rt.cpan.org/Ticket/Display.html?id=6566
4212 eval { require Imager::File::GIF };
4213 eval { require Imager::File::JPEG };
4214 eval { require Imager::File::PNG };
4215 eval { require Imager::File::SGI };
4216 eval { require Imager::File::TIFF };
4217 eval { require Imager::File::ICO };
4218 eval { require Imager::Font::W32 };
4219 eval { require Imager::Font::FT2 };
4220 eval { require Imager::Font::T1 };
4227 my ($class, $fh) = @_;
4230 return $class->new_cb
4235 return print $fh $_[0];
4239 my $count = CORE::read $fh, $tmp, $_[1];
4247 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4248 unless (CORE::seek $fh, $_[0], $_[1]) {
4259 return $class->_new_perlio($fh);
4263 # backward compatibility for %formats
4264 package Imager::FORMATS;
4266 use constant IX_FORMATS => 0;
4267 use constant IX_LIST => 1;
4268 use constant IX_INDEX => 2;
4269 use constant IX_CLASSES => 3;
4272 my ($class, $formats, $classes) = @_;
4274 return bless [ $formats, [ ], 0, $classes ], $class;
4278 my ($self, $key) = @_;
4280 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4283 my $loaded = Imager::_load_file($file, \$error);
4288 if ($error =~ /^Can't locate /) {
4289 $error = "Can't locate $file";
4291 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4294 $self->[IX_FORMATS]{$key} = $value;
4300 my ($self, $key) = @_;
4302 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4304 $self->[IX_CLASSES]{$key} or return undef;
4306 return $self->_check($key);
4310 die "%Imager::formats is not user monifiable";
4314 die "%Imager::formats is not user monifiable";
4318 die "%Imager::formats is not user monifiable";
4322 my ($self, $key) = @_;
4324 if (exists $self->[IX_FORMATS]{$key}) {
4325 my $value = $self->[IX_FORMATS]{$key}
4330 $self->_check($key) or return 1==0;
4338 unless (@{$self->[IX_LIST]}) {
4340 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4341 keys %{$self->[IX_FORMATS]};
4343 for my $key (keys %{$self->[IX_CLASSES]}) {
4344 $self->[IX_FORMATS]{$key} and next;
4346 and push @{$self->[IX_LIST]}, $key;
4350 @{$self->[IX_LIST]} or return;
4351 $self->[IX_INDEX] = 1;
4352 return $self->[IX_LIST][0];
4358 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4361 return $self->[IX_LIST][$self->[IX_INDEX]++];
4367 return scalar @{$self->[IX_LIST]};
4372 # Below is the stub of documentation for your module. You better edit it!
4376 Imager - Perl extension for Generating 24 bit Images
4386 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4391 # see Imager::Files for information on the read() method
4392 my $img = Imager->new(file=>$file)
4393 or die Imager->errstr();
4395 $file =~ s/\.[^.]*$//;
4397 # Create smaller version
4398 # documented in Imager::Transformations
4399 my $thumb = $img->scale(scalefactor=>.3);
4401 # Autostretch individual channels
4402 $thumb->filter(type=>'autolevels');
4404 # try to save in one of these formats
4407 for $format ( qw( png gif jpeg tiff ppm ) ) {
4408 # Check if given format is supported
4409 if ($Imager::formats{$format}) {
4410 $file.="_low.$format";
4411 print "Storing image as: $file\n";
4412 # documented in Imager::Files
4413 $thumb->write(file=>$file) or
4421 Imager is a module for creating and altering images. It can read and
4422 write various image formats, draw primitive shapes like lines,and
4423 polygons, blend multiple images together in various ways, scale, crop,
4424 render text and more.
4426 =head2 Overview of documentation
4432 Imager - This document - Synopsis, Example, Table of Contents and
4437 L<Imager::Install> - installation notes for Imager.
4441 L<Imager::Tutorial> - a brief introduction to Imager.
4445 L<Imager::Cookbook> - how to do various things with Imager.
4449 L<Imager::ImageTypes> - Basics of constructing image objects with
4450 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4451 8/16/double bits/channel, color maps, channel masks, image tags, color
4452 quantization. Also discusses basic image information methods.
4456 L<Imager::Files> - IO interaction, reading/writing images, format
4461 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4466 L<Imager::Color> - Color specification.
4470 L<Imager::Fill> - Fill pattern specification.
4474 L<Imager::Font> - General font rendering, bounding boxes and font
4479 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4480 blending, pasting, convert and map.
4484 L<Imager::Engines> - Programmable transformations through
4485 C<transform()>, C<transform2()> and C<matrix_transform()>.
4489 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4494 L<Imager::Expr> - Expressions for evaluation engine used by
4499 L<Imager::Matrix2d> - Helper class for affine transformations.
4503 L<Imager::Fountain> - Helper for making gradient profiles.
4507 L<Imager::IO> - Imager I/O abstraction.
4511 L<Imager::API> - using Imager's C API
4515 L<Imager::APIRef> - API function reference
4519 L<Imager::Inline> - using Imager's C API from Inline::C
4523 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4527 L<Imager::Security> - brief security notes.
4531 L<Imager::Threads> - brief information on working with threads.
4535 =head2 Basic Overview
4537 An Image object is created with C<$img = Imager-E<gt>new()>.
4540 $img=Imager->new(); # create empty image
4541 $img->read(file=>'lena.png',type=>'png') or # read image from file
4542 die $img->errstr(); # give an explanation
4543 # if something failed
4545 or if you want to create an empty image:
4547 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4549 This example creates a completely black image of width 400 and height
4552 =head1 ERROR HANDLING
4554 In general a method will return false when it fails, if it does use
4555 the C<errstr()> method to find out why:
4561 Returns the last error message in that context.
4563 If the last error you received was from calling an object method, such
4564 as read, call errstr() as an object method to find out why:
4566 my $image = Imager->new;
4567 $image->read(file => 'somefile.gif')
4568 or die $image->errstr;
4570 If it was a class method then call errstr() as a class method:
4572 my @imgs = Imager->read_multi(file => 'somefile.gif')
4573 or die Imager->errstr;
4575 Note that in some cases object methods are implemented in terms of
4576 class methods so a failing object method may set both.
4580 The C<Imager-E<gt>new> method is described in detail in
4581 L<Imager::ImageTypes>.
4585 Where to find information on methods for Imager class objects.
4587 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4590 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4592 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4595 arc() - L<Imager::Draw/arc()> - draw a filled arc
4597 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4600 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4602 check_file_limits() - L<Imager::Files/check_file_limits()>
4604 circle() - L<Imager::Draw/circle()> - draw a filled circle
4606 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4609 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4610 colors in an image's palette (paletted images only)
4612 combine() - L<Imager::Transformations/combine()> - combine channels
4613 from one or more images.
4615 combines() - L<Imager::Draw/combines()> - return a list of the
4616 different combine type keywords
4618 compose() - L<Imager::Transformations/compose()> - compose one image
4621 convert() - L<Imager::Transformations/convert()> - transform the color
4624 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4627 crop() - L<Imager::Transformations/crop()> - extract part of an image
4629 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4630 used to guess the output file format based on the output file name
4632 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4634 difference() - L<Imager::Filters/difference()> - produce a difference
4635 images from two input images.
4637 errstr() - L</errstr()> - the error from the last failed operation.
4639 filter() - L<Imager::Filters/filter()> - image filtering
4641 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4642 palette, if it has one
4644 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4647 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4650 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4651 samples per pixel for an image
4653 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4654 different colors used by an image (works for direct color images)
4656 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4657 palette, if it has one
4659 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4661 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4663 get_file_limits() - L<Imager::Files/get_file_limits()>
4665 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4668 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4670 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4673 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4674 row or partial row of pixels.
4676 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4677 row or partial row of pixels.
4679 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4682 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4685 init() - L<Imager::ImageTypes/init()>
4687 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4688 image write functions should write the image in their bilevel (blank
4689 and white, no gray levels) format
4691 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4694 line() - L<Imager::Draw/line()> - draw an interval
4696 load_plugin() - L<Imager::Filters/load_plugin()>
4698 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4701 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4702 color palette from one or more input images.
4704 map() - L<Imager::Transformations/map()> - remap color
4707 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4709 matrix_transform() - L<Imager::Engines/matrix_transform()>
4711 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4713 NC() - L<Imager::Handy/NC()>
4715 NCF() - L<Imager::Handy/NCF()>
4717 new() - L<Imager::ImageTypes/new()>
4719 newcolor() - L<Imager::Handy/newcolor()>
4721 newcolour() - L<Imager::Handy/newcolour()>
4723 newfont() - L<Imager::Handy/newfont()>
4725 NF() - L<Imager::Handy/NF()>
4727 open() - L<Imager::Files/read()> - an alias for read()
4729 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4733 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4736 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4739 polygon() - L<Imager::Draw/polygon()>
4741 polyline() - L<Imager::Draw/polyline()>
4743 preload() - L<Imager::Files/preload()>
4745 read() - L<Imager::Files/read()> - read a single image from an image file
4747 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4750 read_types() - L<Imager::Files/read_types()> - list image types Imager
4753 register_filter() - L<Imager::Filters/register_filter()>
4755 register_reader() - L<Imager::Files/register_reader()>
4757 register_writer() - L<Imager::Files/register_writer()>
4759 rotate() - L<Imager::Transformations/rotate()>
4761 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4762 onto an image and use the alpha channel
4764 scale() - L<Imager::Transformations/scale()>
4766 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4768 scaleX() - L<Imager::Transformations/scaleX()>
4770 scaleY() - L<Imager::Transformations/scaleY()>
4772 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4775 set_file_limits() - L<Imager::Files/set_file_limits()>
4777 setmask() - L<Imager::ImageTypes/setmask()>
4779 setpixel() - L<Imager::Draw/setpixel()>
4781 setsamples() - L<Imager::Draw/setsamples()>
4783 setscanline() - L<Imager::Draw/setscanline()>
4785 settag() - L<Imager::ImageTypes/settag()>
4787 string() - L<Imager::Draw/string()> - draw text on an image
4789 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4791 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4793 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4795 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4797 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4798 double per sample image.
4800 transform() - L<Imager::Engines/"transform()">
4802 transform2() - L<Imager::Engines/"transform2()">
4804 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4806 unload_plugin() - L<Imager::Filters/unload_plugin()>
4808 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4811 write() - L<Imager::Files/write()> - write an image to a file
4813 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4816 write_types() - L<Imager::Files/read_types()> - list image types Imager
4819 =head1 CONCEPT INDEX
4821 animated GIF - L<Imager::Files/"Writing an animated GIF">
4823 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4824 L<Imager::ImageTypes/"Common Tags">.
4826 blend - alpha blending one image onto another
4827 L<Imager::Transformations/rubthrough()>
4829 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4831 boxes, drawing - L<Imager::Draw/box()>
4833 changes between image - L<Imager::Filters/"Image Difference">
4835 channels, combine into one image - L<Imager::Transformations/combine()>
4837 color - L<Imager::Color>
4839 color names - L<Imager::Color>, L<Imager::Color::Table>
4841 combine modes - L<Imager::Draw/"Combine Types">
4843 compare images - L<Imager::Filters/"Image Difference">
4845 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4847 convolution - L<Imager::Filters/conv>
4849 cropping - L<Imager::Transformations/crop()>
4851 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4853 C<diff> images - L<Imager::Filters/"Image Difference">
4855 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4856 L<Imager::Cookbook/"Image spatial resolution">
4858 drawing boxes - L<Imager::Draw/box()>
4860 drawing lines - L<Imager::Draw/line()>
4862 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4864 error message - L</"ERROR HANDLING">
4866 files, font - L<Imager::Font>
4868 files, image - L<Imager::Files>
4870 filling, types of fill - L<Imager::Fill>
4872 filling, boxes - L<Imager::Draw/box()>
4874 filling, flood fill - L<Imager::Draw/flood_fill()>
4876 flood fill - L<Imager::Draw/flood_fill()>
4878 fonts - L<Imager::Font>
4880 fonts, drawing with - L<Imager::Draw/string()>,
4881 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4883 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4885 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4887 fountain fill - L<Imager::Fill/"Fountain fills">,
4888 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4889 L<Imager::Filters/gradgen>
4891 GIF files - L<Imager::Files/"GIF">
4893 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4895 gradient fill - L<Imager::Fill/"Fountain fills">,
4896 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4897 L<Imager::Filters/gradgen>
4899 gray scale, convert image to - L<Imager::Transformations/convert()>
4901 gaussian blur - L<Imager::Filters/gaussian>
4903 hatch fills - L<Imager::Fill/"Hatched fills">
4905 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4907 invert image - L<Imager::Filters/hardinvert>,
4908 L<Imager::Filters/hardinvertall>
4910 JPEG - L<Imager::Files/"JPEG">
4912 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4914 lines, drawing - L<Imager::Draw/line()>
4916 matrix - L<Imager::Matrix2d>,
4917 L<Imager::Engines/"Matrix Transformations">,
4918 L<Imager::Font/transform()>
4920 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
4922 mosaic - L<Imager::Filters/mosaic>
4924 noise, filter - L<Imager::Filters/noise>
4926 noise, rendered - L<Imager::Filters/turbnoise>,
4927 L<Imager::Filters/radnoise>
4929 paste - L<Imager::Transformations/paste()>,
4930 L<Imager::Transformations/rubthrough()>
4932 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4933 L<Imager::ImageTypes/new()>
4935 =for stopwords posterize
4937 posterize - L<Imager::Filters/postlevels>
4939 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4941 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4943 rectangles, drawing - L<Imager::Draw/box()>
4945 resizing an image - L<Imager::Transformations/scale()>,
4946 L<Imager::Transformations/crop()>
4948 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4950 saving an image - L<Imager::Files>
4952 scaling - L<Imager::Transformations/scale()>
4954 security - L<Imager::Security>
4956 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4958 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4960 size, image - L<Imager::ImageTypes/getwidth()>,
4961 L<Imager::ImageTypes/getheight()>
4963 size, text - L<Imager::Font/bounding_box()>
4965 tags, image metadata - L<Imager::ImageTypes/"Tags">
4967 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4968 L<Imager::Font::Wrap>
4970 text, wrapping text in an area - L<Imager::Font::Wrap>
4972 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4974 threads - L<Imager::Threads>
4976 tiles, color - L<Imager::Filters/mosaic>
4978 transparent images - L<Imager::ImageTypes>,
4979 L<Imager::Cookbook/"Transparent PNG">
4981 =for stopwords unsharp
4983 unsharp mask - L<Imager::Filters/unsharpmask>
4985 watermark - L<Imager::Filters/watermark>
4987 writing an image to a file - L<Imager::Files>
4991 The best place to get help with Imager is the mailing list.
4993 To subscribe send a message with C<subscribe> in the body to:
4995 imager-devel+request@molar.is
5001 L<http://www.molar.is/en/lists/imager-devel/>
5005 where you can also find the mailing list archive.
5007 You can report bugs by pointing your browser at:
5011 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5015 or by sending an email to:
5019 bug-Imager@rt.cpan.org
5023 Please remember to include the versions of Imager, perl, supporting
5024 libraries, and any relevant code. If you have specific images that
5025 cause the problems, please include those too.
5027 If you don't want to publish your email address on a mailing list you
5028 can use CPAN::Forum:
5030 http://www.cpanforum.com/dist/Imager
5032 You will need to register to post.
5034 =head1 CONTRIBUTING TO IMAGER
5040 If you like or dislike Imager, you can add a public review of Imager
5043 http://cpanratings.perl.org/dist/Imager
5045 =for stopwords Bitcard
5047 This requires a Bitcard account (http://www.bitcard.org).
5049 You can also send email to the maintainer below.
5051 If you send me a bug report via email, it will be copied to Request
5056 I accept patches, preferably against the master branch in git. Please
5057 include an explanation of the reason for why the patch is needed or
5060 Your patch should include regression tests where possible, otherwise
5061 it will be delayed until I get a chance to write them.
5063 To browse Imager's git repository:
5065 http://git.imager.perl.org/imager.git
5069 git clone git://git.imager.perl.org/imager.git
5071 My preference is that patches are provided in the format produced by
5072 C<git format-patch>, for example, if you made your changes in a branch
5073 from master you might do:
5075 git format-patch -k --stdout master >my-patch.txt
5077 and then attach that to your bug report, either by adding it as an
5078 attachment in your email client, or by using the Request Tracker
5079 attachment mechanism.
5083 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5085 Arnar M. Hrafnkelsson is the original author of Imager.
5087 Many others have contributed to Imager, please see the C<README> for a
5092 Imager is licensed under the same terms as perl itself.
5095 makeblendedfont Fontforge
5097 A test font, generated by the Debian packaged Fontforge,
5098 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5099 copyrighted by Adobe. See F<adobe.txt> in the source for license
5104 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5105 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5106 L<Imager::Font>(3), L<Imager::Transformations>(3),
5107 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5108 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5110 L<http://imager.perl.org/>
5112 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5114 Other perl imaging modules include:
5116 L<GD>(3), L<Image::Magick>(3),
5117 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5118 L<Prima::Image>, L<IPA>.
5120 For manipulating image metadata see L<Image::ExifTool>.
5122 If you're trying to use Imager for array processing, you should
5123 probably using L<PDL>.