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) {
147 $VERSION = '1.004_004';
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_skew} ={
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{autolevels} ={
214 callseq => ['image','lsat','usat'],
215 defaults => { lsat=>0.1,usat=>0.1 },
216 callsub => sub { my %hsh=@_; i_autolevels_mono($hsh{image},$hsh{lsat},$hsh{usat}); }
219 $filters{turbnoise} ={
220 callseq => ['image'],
221 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
222 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
225 $filters{radnoise} ={
226 callseq => ['image'],
227 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
228 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
233 callseq => ['image', 'coef'],
238 i_conv($hsh{image},$hsh{coef})
239 or die Imager->_error_as_msg() . "\n";
245 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
246 defaults => { dist => 0 },
250 my @colors = @{$hsh{colors}};
253 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
257 $filters{nearest_color} =
259 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
264 # make sure the segments are specified with colors
266 for my $color (@{$hsh{colors}}) {
267 my $new_color = _color($color)
268 or die $Imager::ERRSTR."\n";
269 push @colors, $new_color;
272 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
274 or die Imager->_error_as_msg() . "\n";
277 $filters{gaussian} = {
278 callseq => [ 'image', 'stddev' ],
280 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
284 callseq => [ qw(image size) ],
285 defaults => { size => 20 },
286 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
290 callseq => [ qw(image bump elevation lightx lighty st) ],
291 defaults => { elevation=>0, st=> 2 },
294 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
295 $hsh{lightx}, $hsh{lighty}, $hsh{st});
298 $filters{bumpmap_complex} =
300 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
317 for my $cname (qw/Ia Il Is/) {
318 my $old = $hsh{$cname};
319 my $new_color = _color($old)
320 or die $Imager::ERRSTR, "\n";
321 $hsh{$cname} = $new_color;
323 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
324 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
325 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
329 $filters{postlevels} =
331 callseq => [ qw(image levels) ],
332 defaults => { levels => 10 },
333 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
335 $filters{watermark} =
337 callseq => [ qw(image wmark tx ty pixdiff) ],
338 defaults => { pixdiff=>10, tx=>0, ty=>0 },
342 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
348 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
350 ftype => { linear => 0,
356 repeat => { none => 0,
371 multiply => 2, mult => 2,
374 subtract => 5, 'sub' => 5,
384 defaults => { ftype => 0, repeat => 0, combine => 0,
385 super_sample => 0, ssample_param => 4,
398 # make sure the segments are specified with colors
400 for my $segment (@{$hsh{segments}}) {
401 my @new_segment = @$segment;
403 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
404 push @segments, \@new_segment;
407 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
408 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
409 $hsh{ssample_param}, \@segments)
410 or die Imager->_error_as_msg() . "\n";
413 $filters{unsharpmask} =
415 callseq => [ qw(image stddev scale) ],
416 defaults => { stddev=>2.0, scale=>1.0 },
420 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
424 $FORMATGUESS=\&def_guess_type;
434 # NOTE: this might be moved to an import override later on
439 if ($_[$i] eq '-log-stderr') {
447 goto &Exporter::import;
451 Imager->open_log(log => $_[0], level => $_[1]);
456 my %parms=(loglevel=>1,@_);
458 if (exists $parms{'warn_obsolete'}) {
459 $warn_obsolete = $parms{'warn_obsolete'};
463 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
467 if (exists $parms{'t1log'}) {
469 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
470 Imager->_set_error(Imager->_error_as_msg);
484 my (%opts) = ( loglevel => 1, @_ );
486 $is_logging = i_init_log($opts{log}, $opts{loglevel});
487 unless ($is_logging) {
488 Imager->_set_error(Imager->_error_as_msg());
492 Imager->log("Imager $VERSION starting\n", 1);
498 i_init_log(undef, -1);
503 my ($class, $message, $level) = @_;
505 defined $level or $level = 1;
507 i_log_entry($message, $level);
517 print "shutdown code\n";
518 # for(keys %instances) { $instances{$_}->DESTROY(); }
519 malloc_state(); # how do decide if this should be used? -- store something from the import
520 print "Imager exiting\n";
524 # Load a filter plugin
530 if ($^O eq 'android') {
532 $filename = File::Spec->rel2abs($filename);
535 my ($DSO_handle,$str)=DSO_open($filename);
536 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
537 my %funcs=DSO_funclist($DSO_handle);
538 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
540 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
542 $DSOs{$filename}=[$DSO_handle,\%funcs];
545 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
546 $DEBUG && print "eval string:\n",$evstr,"\n";
558 if ($^O eq 'android') {
560 $filename = File::Spec->rel2abs($filename);
563 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
564 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
565 for(keys %{$funcref}) {
567 $DEBUG && print "unloading: $_\n";
569 my $rc=DSO_close($DSO_handle);
570 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
574 # take the results of i_error() and make a message out of it
576 return join(": ", map $_->[0], i_errors());
579 # this function tries to DWIM for color parameters
580 # color objects are used as is
581 # simple scalars are simply treated as single parameters to Imager::Color->new
582 # hashrefs are treated as named argument lists to Imager::Color->new
583 # arrayrefs are treated as list arguments to Imager::Color->new iff any
585 # other arrayrefs are treated as list arguments to Imager::Color::Float
589 # perl 5.6.0 seems to do weird things to $arg if we don't make an
590 # explicitly stringified copy
591 # I vaguely remember a bug on this on p5p, but couldn't find it
592 # through bugs.perl.org (I had trouble getting it to find any bugs)
593 my $copy = $arg . "";
597 if (UNIVERSAL::isa($arg, "Imager::Color")
598 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
602 if ($copy =~ /^HASH\(/) {
603 $result = Imager::Color->new(%$arg);
605 elsif ($copy =~ /^ARRAY\(/) {
606 $result = Imager::Color->new(@$arg);
609 $Imager::ERRSTR = "Not a color";
614 # assume Imager::Color::new knows how to handle it
615 $result = Imager::Color->new($arg);
622 my ($self, $combine, $default) = @_;
624 if (!defined $combine && ref $self) {
625 $combine = $self->{combine};
627 defined $combine or $combine = $defaults{combine};
628 defined $combine or $combine = $default;
630 if (exists $combine_types{$combine}) {
631 $combine = $combine_types{$combine};
638 my ($self, $method) = @_;
640 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
642 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
643 $msg = "$method: $msg" if $method;
644 $self->_set_error($msg);
649 # returns first defined parameter
652 return $_ if defined $_;
658 # Methods to be called on objects.
661 # Create a new Imager object takes very few parameters.
662 # usually you call this method and then call open from
663 # the resulting object
670 $self->{IMG}=undef; # Just to indicate what exists
671 $self->{ERRSTR}=undef; #
672 $self->{DEBUG}=$DEBUG;
673 $self->{DEBUG} and print "Initialized Imager\n";
674 if (defined $hsh{file} ||
677 defined $hsh{callback} ||
678 defined $hsh{readcb} ||
679 defined $hsh{data} ||
681 # allow $img = Imager->new(file => $filename)
684 # type is already used as a parameter to new(), rename it for the
686 if ($hsh{filetype}) {
687 $extras{type} = $hsh{filetype};
689 unless ($self->read(%hsh, %extras)) {
690 $Imager::ERRSTR = $self->{ERRSTR};
694 elsif (defined $hsh{xsize} || defined $hsh{ysize}) {
695 unless ($self->img_set(%hsh)) {
696 $Imager::ERRSTR = $self->{ERRSTR};
701 Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
708 # Copy an entire image with no changes
709 # - if an image has magic the copy of it will not be magical
714 $self->_valid_image("copy")
717 unless (defined wantarray) {
719 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
723 my $newcopy=Imager->new();
724 $newcopy->{IMG} = i_copy($self->{IMG});
733 $self->_valid_image("paste")
736 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
737 my $src = $input{img} || $input{src};
739 $self->_set_error("no source image");
742 unless ($src->_valid_image("paste")) {
743 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
746 $input{left}=0 if $input{left} <= 0;
747 $input{top}=0 if $input{top} <= 0;
749 my($r,$b)=i_img_info($src->{IMG});
750 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
751 my ($src_right, $src_bottom);
752 if ($input{src_coords}) {
753 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
756 if (defined $input{src_maxx}) {
757 $src_right = $input{src_maxx};
759 elsif (defined $input{width}) {
760 if ($input{width} <= 0) {
761 $self->_set_error("paste: width must me positive");
764 $src_right = $src_left + $input{width};
769 if (defined $input{src_maxy}) {
770 $src_bottom = $input{src_maxy};
772 elsif (defined $input{height}) {
773 if ($input{height} < 0) {
774 $self->_set_error("paste: height must be positive");
777 $src_bottom = $src_top + $input{height};
784 $src_right > $r and $src_right = $r;
785 $src_bottom > $b and $src_bottom = $b;
787 if ($src_right <= $src_left
788 || $src_bottom < $src_top) {
789 $self->_set_error("nothing to paste");
793 i_copyto($self->{IMG}, $src->{IMG},
794 $src_left, $src_top, $src_right, $src_bottom,
795 $input{left}, $input{top});
797 return $self; # What should go here??
800 # Crop an image - i.e. return a new image that is smaller
805 $self->_valid_image("crop")
808 unless (defined wantarray) {
810 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
816 my ($w, $h, $l, $r, $b, $t) =
817 @hsh{qw(width height left right bottom top)};
819 # work through the various possibilities
824 elsif (!defined $r) {
825 $r = $self->getwidth;
837 $l = int(0.5+($self->getwidth()-$w)/2);
842 $r = $self->getwidth;
848 elsif (!defined $b) {
849 $b = $self->getheight;
861 $t=int(0.5+($self->getheight()-$h)/2);
866 $b = $self->getheight;
869 ($l,$r)=($r,$l) if $l>$r;
870 ($t,$b)=($b,$t) if $t>$b;
873 $r > $self->getwidth and $r = $self->getwidth;
875 $b > $self->getheight and $b = $self->getheight;
877 if ($l == $r || $t == $b) {
878 $self->_set_error("resulting image would have no content");
881 if( $r < $l or $b < $t ) {
882 $self->_set_error("attempting to crop outside of the image");
885 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
887 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
892 my ($self, %opts) = @_;
897 my $x = $opts{xsize} || $self->getwidth;
898 my $y = $opts{ysize} || $self->getheight;
899 my $channels = $opts{channels} || $self->getchannels;
901 my $out = Imager->new;
902 if ($channels == $self->getchannels) {
903 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
906 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
908 unless ($out->{IMG}) {
909 $self->{ERRSTR} = $self->_error_as_msg;
916 # Sets an image to a certain size and channel number
917 # if there was previously data in the image it is discarded
930 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
935 if (my $channels = $model_channels{$hsh{model}}) {
936 $hsh{channels} = $channels;
939 $self->_set_error("new: unknown value for model '$hsh{model}'");
944 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
945 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
946 $hsh{maxcolors} || 256);
948 elsif ($hsh{bits} eq 'double') {
949 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
951 elsif ($hsh{bits} == 16) {
952 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
955 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
959 unless ($self->{IMG}) {
960 $self->_set_error(Imager->_error_as_msg());
967 # created a masked version of the current image
971 $self->_valid_image("masked")
974 my %opts = (left => 0,
976 right => $self->getwidth,
977 bottom => $self->getheight,
979 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
981 my $result = Imager->new;
982 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
983 $opts{top}, $opts{right} - $opts{left},
984 $opts{bottom} - $opts{top});
985 unless ($result->{IMG}) {
986 $self->_set_error(Imager->_error_as_msg);
990 # keep references to the mask and base images so they don't
992 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
997 # convert an RGB image into a paletted image
1001 if (@_ != 1 && !ref $_[0]) {
1008 unless (defined wantarray) {
1009 my @caller = caller;
1010 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
1014 $self->_valid_image("to_paletted")
1017 my $result = Imager->new;
1018 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1019 $self->_set_error(Imager->_error_as_msg);
1027 my ($class, $quant, @images) = @_;
1030 Imager->_set_error("make_palette: supply at least one image");
1034 for my $img (@images) {
1035 unless ($img->{IMG}) {
1036 Imager->_set_error("make_palette: image $index is empty");
1042 return i_img_make_palette($quant, map $_->{IMG}, @images);
1045 # convert a paletted (or any image) to an 8-bit/channel RGB image
1049 unless (defined wantarray) {
1050 my @caller = caller;
1051 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1055 $self->_valid_image("to_rgb8")
1058 my $result = Imager->new;
1059 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1060 $self->_set_error(Imager->_error_as_msg());
1067 # convert a paletted (or any image) to a 16-bit/channel RGB image
1071 unless (defined wantarray) {
1072 my @caller = caller;
1073 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1077 $self->_valid_image("to_rgb16")
1080 my $result = Imager->new;
1081 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1082 $self->_set_error(Imager->_error_as_msg());
1089 # convert a paletted (or any image) to an double/channel RGB image
1093 unless (defined wantarray) {
1094 my @caller = caller;
1095 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1099 $self->_valid_image("to_rgb_double")
1102 my $result = Imager->new;
1103 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1104 $self->_set_error(Imager->_error_as_msg());
1113 my %opts = (colors=>[], @_);
1115 $self->_valid_image("addcolors")
1118 my @colors = @{$opts{colors}}
1121 for my $color (@colors) {
1122 $color = _color($color);
1124 $self->_set_error($Imager::ERRSTR);
1129 return i_addcolors($self->{IMG}, @colors);
1134 my %opts = (start=>0, colors=>[], @_);
1136 $self->_valid_image("setcolors")
1139 my @colors = @{$opts{colors}}
1142 for my $color (@colors) {
1143 $color = _color($color);
1145 $self->_set_error($Imager::ERRSTR);
1150 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1157 $self->_valid_image("getcolors")
1160 if (!exists $opts{start} && !exists $opts{count}) {
1163 $opts{count} = $self->colorcount;
1165 elsif (!exists $opts{count}) {
1168 elsif (!exists $opts{start}) {
1172 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1178 $self->_valid_image("colorcount")
1181 return i_colorcount($self->{IMG});
1187 $self->_valid_image("maxcolors")
1190 i_maxcolors($self->{IMG});
1197 $self->_valid_image("findcolor")
1200 unless ($opts{color}) {
1201 $self->_set_error("findcolor: no color parameter");
1205 my $color = _color($opts{color})
1208 return i_findcolor($self->{IMG}, $color);
1214 $self->_valid_image("bits")
1217 my $bits = i_img_bits($self->{IMG});
1218 if ($bits && $bits == length(pack("d", 1)) * 8) {
1227 $self->_valid_image("type")
1230 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1236 $self->_valid_image("virtual")
1239 return i_img_virtual($self->{IMG});
1245 $self->_valid_image("is_bilevel")
1248 return i_img_is_monochrome($self->{IMG});
1252 my ($self, %opts) = @_;
1254 $self->_valid_image("tags")
1257 if (defined $opts{name}) {
1261 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1262 push @result, (i_tags_get($self->{IMG}, $found))[1];
1265 return wantarray ? @result : $result[0];
1267 elsif (defined $opts{code}) {
1271 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1272 push @result, (i_tags_get($self->{IMG}, $found))[1];
1279 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1282 return i_tags_count($self->{IMG});
1291 $self->_valid_image("addtag")
1295 if (defined $opts{value}) {
1296 if ($opts{value} =~ /^\d+$/) {
1298 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1301 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1304 elsif (defined $opts{data}) {
1305 # force addition as a string
1306 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1309 $self->{ERRSTR} = "No value supplied";
1313 elsif ($opts{code}) {
1314 if (defined $opts{value}) {
1315 if ($opts{value} =~ /^\d+$/) {
1317 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1320 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1323 elsif (defined $opts{data}) {
1324 # force addition as a string
1325 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1328 $self->{ERRSTR} = "No value supplied";
1341 $self->_valid_image("deltag")
1344 if (defined $opts{'index'}) {
1345 return i_tags_delete($self->{IMG}, $opts{'index'});
1347 elsif (defined $opts{name}) {
1348 return i_tags_delbyname($self->{IMG}, $opts{name});
1350 elsif (defined $opts{code}) {
1351 return i_tags_delbycode($self->{IMG}, $opts{code});
1354 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1360 my ($self, %opts) = @_;
1362 $self->_valid_image("settag")
1366 $self->deltag(name=>$opts{name});
1367 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1369 elsif (defined $opts{code}) {
1370 $self->deltag(code=>$opts{code});
1371 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1379 sub _get_reader_io {
1380 my ($self, $input) = @_;
1383 return $input->{io}, undef;
1385 elsif ($input->{fd}) {
1386 return io_new_fd($input->{fd});
1388 elsif ($input->{fh}) {
1389 unless (Scalar::Util::openhandle($input->{fh})) {
1390 $self->_set_error("Handle in fh option not opened");
1393 return Imager::IO->new_fh($input->{fh});
1395 elsif ($input->{file}) {
1396 my $file = IO::File->new($input->{file}, "r");
1398 $self->_set_error("Could not open $input->{file}: $!");
1402 return (io_new_fd(fileno($file)), $file);
1404 elsif ($input->{data}) {
1405 return io_new_buffer($input->{data});
1407 elsif ($input->{callback} || $input->{readcb}) {
1408 if (!$input->{seekcb}) {
1409 $self->_set_error("Need a seekcb parameter");
1411 if ($input->{maxbuffer}) {
1412 return io_new_cb($input->{writecb},
1413 $input->{callback} || $input->{readcb},
1414 $input->{seekcb}, $input->{closecb},
1415 $input->{maxbuffer});
1418 return io_new_cb($input->{writecb},
1419 $input->{callback} || $input->{readcb},
1420 $input->{seekcb}, $input->{closecb});
1424 $self->_set_error("file/fd/fh/data/callback parameter missing");
1429 sub _get_writer_io {
1430 my ($self, $input) = @_;
1432 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1439 elsif ($input->{fd}) {
1440 $io = io_new_fd($input->{fd});
1442 elsif ($input->{fh}) {
1443 unless (Scalar::Util::openhandle($input->{fh})) {
1444 $self->_set_error("Handle in fh option not opened");
1447 $io = Imager::IO->new_fh($input->{fh});
1449 elsif ($input->{file}) {
1450 my $fh = new IO::File($input->{file},"w+");
1452 $self->_set_error("Could not open file $input->{file}: $!");
1455 binmode($fh) or die;
1456 $io = io_new_fd(fileno($fh));
1459 elsif ($input->{data}) {
1460 $io = io_new_bufchain();
1462 elsif ($input->{callback} || $input->{writecb}) {
1463 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1466 $io = io_new_cb($input->{callback} || $input->{writecb},
1468 $input->{seekcb}, $input->{closecb});
1471 $self->_set_error("file/fd/fh/data/callback parameter missing");
1475 unless ($buffered) {
1476 $io->set_buffered(0);
1479 return ($io, @extras);
1482 # Read an image from file
1488 if (defined($self->{IMG})) {
1489 # let IIM_DESTROY do the destruction, since the image may be
1490 # referenced from elsewhere
1491 #i_img_destroy($self->{IMG});
1492 undef($self->{IMG});
1495 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1497 my $type = $input{'type'};
1499 $type = i_test_format_probe($IO, -1);
1502 if ($input{file} && !$type) {
1504 $type = $FORMATGUESS->($input{file});
1508 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1509 $input{file} and $msg .= " or file name";
1510 $self->_set_error($msg);
1514 _reader_autoload($type);
1516 if ($readers{$type} && $readers{$type}{single}) {
1517 return $readers{$type}{single}->($self, $IO, %input);
1520 unless ($formats_low{$type}) {
1521 my $read_types = join ', ', sort Imager->read_types();
1522 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1526 my $allow_incomplete = $input{allow_incomplete};
1527 defined $allow_incomplete or $allow_incomplete = 0;
1529 if ( $type eq 'pnm' ) {
1530 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1531 if ( !defined($self->{IMG}) ) {
1532 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1535 $self->{DEBUG} && print "loading a pnm file\n";
1539 if ( $type eq 'bmp' ) {
1540 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1541 if ( !defined($self->{IMG}) ) {
1542 $self->{ERRSTR}=$self->_error_as_msg();
1545 $self->{DEBUG} && print "loading a bmp file\n";
1548 if ( $type eq 'tga' ) {
1549 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1550 if ( !defined($self->{IMG}) ) {
1551 $self->{ERRSTR}=$self->_error_as_msg();
1554 $self->{DEBUG} && print "loading a tga file\n";
1557 if ( $type eq 'raw' ) {
1558 unless ( $input{xsize} && $input{ysize} ) {
1559 $self->_set_error('missing xsize or ysize parameter for raw');
1563 my $interleave = _first($input{raw_interleave}, $input{interleave});
1564 unless (defined $interleave) {
1565 my @caller = caller;
1566 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1569 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1570 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1572 $self->{IMG} = i_readraw_wiol( $IO,
1578 if ( !defined($self->{IMG}) ) {
1579 $self->{ERRSTR}=$self->_error_as_msg();
1582 $self->{DEBUG} && print "loading a raw file\n";
1588 sub register_reader {
1589 my ($class, %opts) = @_;
1592 or die "register_reader called with no type parameter\n";
1594 my $type = $opts{type};
1596 defined $opts{single} || defined $opts{multiple}
1597 or die "register_reader called with no single or multiple parameter\n";
1599 $readers{$type} = { };
1600 if ($opts{single}) {
1601 $readers{$type}{single} = $opts{single};
1603 if ($opts{multiple}) {
1604 $readers{$type}{multiple} = $opts{multiple};
1610 sub register_writer {
1611 my ($class, %opts) = @_;
1614 or die "register_writer called with no type parameter\n";
1616 my $type = $opts{type};
1618 defined $opts{single} || defined $opts{multiple}
1619 or die "register_writer called with no single or multiple parameter\n";
1621 $writers{$type} = { };
1622 if ($opts{single}) {
1623 $writers{$type}{single} = $opts{single};
1625 if ($opts{multiple}) {
1626 $writers{$type}{multiple} = $opts{multiple};
1637 grep($file_formats{$_}, keys %formats),
1638 qw(ico sgi), # formats not handled directly, but supplied with Imager
1649 grep($file_formats{$_}, keys %formats),
1650 qw(ico sgi), # formats not handled directly, but supplied with Imager
1657 my ($file, $error) = @_;
1659 if ($attempted_to_load{$file}) {
1660 if ($file_load_errors{$file}) {
1661 $$error = $file_load_errors{$file};
1669 local $SIG{__DIE__};
1671 ++$attempted_to_load{$file};
1679 my $work = $@ || "Unknown error";
1681 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1682 $work =~ s/\n/\\n/g;
1683 $work =~ s/\s*\.?\z/ loading $file/;
1684 $file_load_errors{$file} = $work;
1691 # probes for an Imager::File::whatever module
1692 sub _reader_autoload {
1695 return if $formats_low{$type} || $readers{$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 $filer = "Imager/File/\U$type\EReader.pm";
1705 $loaded = _load_file($filer, \$error);
1706 if ($error =~ /^Can't locate /) {
1707 $error = "Can't locate $file or $filer";
1711 $reader_load_errors{$type} = $error;
1715 # probes for an Imager::File::whatever module
1716 sub _writer_autoload {
1719 return if $formats_low{$type} || $writers{$type};
1721 return unless $type =~ /^\w+$/;
1723 my $file = "Imager/File/\U$type\E.pm";
1726 my $loaded = _load_file($file, \$error);
1727 if (!$loaded && $error =~ /^Can't locate /) {
1728 my $filew = "Imager/File/\U$type\EWriter.pm";
1729 $loaded = _load_file($filew, \$error);
1730 if ($error =~ /^Can't locate /) {
1731 $error = "Can't locate $file or $filew";
1735 $writer_load_errors{$type} = $error;
1739 sub _fix_gif_positions {
1740 my ($opts, $opt, $msg, @imgs) = @_;
1742 my $positions = $opts->{'gif_positions'};
1744 for my $pos (@$positions) {
1745 my ($x, $y) = @$pos;
1746 my $img = $imgs[$index++];
1747 $img->settag(name=>'gif_left', value=>$x);
1748 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1750 $$msg .= "replaced with the gif_left and gif_top tags";
1755 gif_each_palette=>'gif_local_map',
1756 interlace => 'gif_interlace',
1757 gif_delays => 'gif_delay',
1758 gif_positions => \&_fix_gif_positions,
1759 gif_loop_count => 'gif_loop',
1762 # options that should be converted to colors
1763 my %color_opts = map { $_ => 1 } qw/i_background/;
1766 my ($self, $opts, $prefix, @imgs) = @_;
1768 for my $opt (keys %$opts) {
1770 if ($obsolete_opts{$opt}) {
1771 my $new = $obsolete_opts{$opt};
1772 my $msg = "Obsolete option $opt ";
1774 $new->($opts, $opt, \$msg, @imgs);
1777 $msg .= "replaced with the $new tag ";
1780 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1781 warn $msg if $warn_obsolete && $^W;
1783 next unless $tagname =~ /^\Q$prefix/;
1784 my $value = $opts->{$opt};
1785 if ($color_opts{$opt}) {
1786 $value = _color($value);
1788 $self->_set_error($Imager::ERRSTR);
1793 if (UNIVERSAL::isa($value, "Imager::Color")) {
1794 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1795 for my $img (@imgs) {
1796 $img->settag(name=>$tagname, value=>$tag);
1799 elsif (ref($value) eq 'ARRAY') {
1800 for my $i (0..$#$value) {
1801 my $val = $value->[$i];
1803 if (UNIVERSAL::isa($val, "Imager::Color")) {
1804 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1806 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1809 $self->_set_error("Unknown reference type " . ref($value) .
1810 " supplied in array for $opt");
1816 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1821 $self->_set_error("Unknown reference type " . ref($value) .
1822 " supplied for $opt");
1827 # set it as a tag for every image
1828 for my $img (@imgs) {
1829 $img->settag(name=>$tagname, value=>$value);
1837 # Write an image to file
1840 my %input=(jpegquality=>75,
1850 $self->_valid_image("write")
1853 $self->_set_opts(\%input, "i_", $self)
1856 my $type = $input{'type'};
1857 if (!$type and $input{file}) {
1858 $type = $FORMATGUESS->($input{file});
1861 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1865 _writer_autoload($type);
1868 if ($writers{$type} && $writers{$type}{single}) {
1869 ($IO, $fh) = $self->_get_writer_io(\%input)
1872 $writers{$type}{single}->($self, $IO, %input, type => $type)
1876 if (!$formats_low{$type}) {
1877 my $write_types = join ', ', sort Imager->write_types();
1878 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1882 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1885 if ( $type eq 'pnm' ) {
1886 $self->_set_opts(\%input, "pnm_", $self)
1888 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1889 $self->{ERRSTR} = $self->_error_as_msg();
1892 $self->{DEBUG} && print "writing a pnm file\n";
1894 elsif ( $type eq 'raw' ) {
1895 $self->_set_opts(\%input, "raw_", $self)
1897 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1898 $self->{ERRSTR} = $self->_error_as_msg();
1901 $self->{DEBUG} && print "writing a raw file\n";
1903 elsif ( $type eq 'bmp' ) {
1904 $self->_set_opts(\%input, "bmp_", $self)
1906 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1907 $self->{ERRSTR} = $self->_error_as_msg;
1910 $self->{DEBUG} && print "writing a bmp file\n";
1912 elsif ( $type eq 'tga' ) {
1913 $self->_set_opts(\%input, "tga_", $self)
1916 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1917 $self->{ERRSTR}=$self->_error_as_msg();
1920 $self->{DEBUG} && print "writing a tga file\n";
1924 if (exists $input{'data'}) {
1925 my $data = io_slurp($IO);
1927 $self->{ERRSTR}='Could not slurp from buffer';
1930 ${$input{data}} = $data;
1936 my ($class, $opts, @images) = @_;
1938 my $type = $opts->{type};
1940 if (!$type && $opts->{'file'}) {
1941 $type = $FORMATGUESS->($opts->{'file'});
1944 $class->_set_error('type parameter missing and not possible to guess from extension');
1947 # translate to ImgRaw
1949 for my $img (@images) {
1950 unless ($img->_valid_image("write_multi")) {
1951 $class->_set_error($img->errstr . " (image $index)");
1956 $class->_set_opts($opts, "i_", @images)
1958 my @work = map $_->{IMG}, @images;
1960 _writer_autoload($type);
1963 if ($writers{$type} && $writers{$type}{multiple}) {
1964 ($IO, $file) = $class->_get_writer_io($opts, $type)
1967 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1971 if (!$formats{$type}) {
1972 my $write_types = join ', ', sort Imager->write_types();
1973 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1977 ($IO, $file) = $class->_get_writer_io($opts, $type)
1980 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1984 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1989 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1995 if (exists $opts->{'data'}) {
1996 my $data = io_slurp($IO);
1998 Imager->_set_error('Could not slurp from buffer');
2001 ${$opts->{data}} = $data;
2006 # read multiple images from a file
2008 my ($class, %opts) = @_;
2010 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2013 my $type = $opts{'type'};
2015 $type = i_test_format_probe($IO, -1);
2018 if ($opts{file} && !$type) {
2020 $type = $FORMATGUESS->($opts{file});
2024 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2025 $opts{file} and $msg .= " or file name";
2026 Imager->_set_error($msg);
2030 _reader_autoload($type);
2032 if ($readers{$type} && $readers{$type}{multiple}) {
2033 return $readers{$type}{multiple}->($IO, %opts);
2036 unless ($formats{$type}) {
2037 my $read_types = join ', ', sort Imager->read_types();
2038 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2043 if ($type eq 'pnm') {
2044 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2047 my $img = Imager->new;
2048 if ($img->read(%opts, io => $IO, type => $type)) {
2051 Imager->_set_error($img->errstr);
2056 $ERRSTR = _error_as_msg();
2060 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2064 # Destroy an Imager object
2068 # delete $instances{$self};
2069 if (defined($self->{IMG})) {
2070 # the following is now handled by the XS DESTROY method for
2071 # Imager::ImgRaw object
2072 # Re-enabling this will break virtual images
2073 # tested for in t/t020masked.t
2074 # i_img_destroy($self->{IMG});
2075 undef($self->{IMG});
2077 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2081 # Perform an inplace filter of an image
2082 # that is the image will be overwritten with the data
2089 $self->_valid_image("filter")
2092 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2094 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2095 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2098 if ($filters{$input{'type'}}{names}) {
2099 my $names = $filters{$input{'type'}}{names};
2100 for my $name (keys %$names) {
2101 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2102 $input{$name} = $names->{$name}{$input{$name}};
2106 if (defined($filters{$input{'type'}}{defaults})) {
2107 %hsh=( image => $self->{IMG},
2109 %{$filters{$input{'type'}}{defaults}},
2112 %hsh=( image => $self->{IMG},
2117 my @cs=@{$filters{$input{'type'}}{callseq}};
2120 if (!defined($hsh{$_})) {
2121 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2126 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2127 &{$filters{$input{'type'}}{callsub}}(%hsh);
2130 chomp($self->{ERRSTR} = $@);
2136 $self->{DEBUG} && print "callseq is: @cs\n";
2137 $self->{DEBUG} && print "matching callseq is: @b\n";
2142 sub register_filter {
2144 my %hsh = ( defaults => {}, @_ );
2147 or die "register_filter() with no type\n";
2148 defined $hsh{callsub}
2149 or die "register_filter() with no callsub\n";
2150 defined $hsh{callseq}
2151 or die "register_filter() with no callseq\n";
2153 exists $filters{$hsh{type}}
2156 $filters{$hsh{type}} = \%hsh;
2161 sub scale_calculate {
2164 my %opts = ('type'=>'max', @_);
2166 # none of these should be references
2167 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2168 if (defined $opts{$name} && ref $opts{$name}) {
2169 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2174 my ($x_scale, $y_scale);
2175 my $width = $opts{width};
2176 my $height = $opts{height};
2178 defined $width or $width = $self->getwidth;
2179 defined $height or $height = $self->getheight;
2182 unless (defined $width && defined $height) {
2183 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2188 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2189 $x_scale = $opts{'xscalefactor'};
2190 $y_scale = $opts{'yscalefactor'};
2192 elsif ($opts{'xscalefactor'}) {
2193 $x_scale = $opts{'xscalefactor'};
2194 $y_scale = $opts{'scalefactor'} || $x_scale;
2196 elsif ($opts{'yscalefactor'}) {
2197 $y_scale = $opts{'yscalefactor'};
2198 $x_scale = $opts{'scalefactor'} || $y_scale;
2201 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2204 # work out the scaling
2205 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2206 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2207 $opts{ypixels} / $height );
2208 if ($opts{'type'} eq 'min') {
2209 $x_scale = $y_scale = _min($xpix,$ypix);
2211 elsif ($opts{'type'} eq 'max') {
2212 $x_scale = $y_scale = _max($xpix,$ypix);
2214 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2219 $self->_set_error('invalid value for type parameter');
2222 } elsif ($opts{xpixels}) {
2223 $x_scale = $y_scale = $opts{xpixels} / $width;
2225 elsif ($opts{ypixels}) {
2226 $x_scale = $y_scale = $opts{ypixels}/$height;
2228 elsif ($opts{constrain} && ref $opts{constrain}
2229 && $opts{constrain}->can('constrain')) {
2230 # we've been passed an Image::Math::Constrain object or something
2231 # that looks like one
2233 (undef, undef, $scalefactor)
2234 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2235 unless ($scalefactor) {
2236 $self->_set_error('constrain method failed on constrain parameter');
2239 $x_scale = $y_scale = $scalefactor;
2242 my $new_width = int($x_scale * $width + 0.5);
2243 $new_width > 0 or $new_width = 1;
2244 my $new_height = int($y_scale * $height + 0.5);
2245 $new_height > 0 or $new_height = 1;
2247 return ($x_scale, $y_scale, $new_width, $new_height);
2251 # Scale an image to requested size and return the scaled version
2255 my %opts = (qtype=>'normal' ,@_);
2256 my $img = Imager->new();
2257 my $tmp = Imager->new();
2259 unless (defined wantarray) {
2260 my @caller = caller;
2261 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2265 $self->_valid_image("scale")
2268 my ($x_scale, $y_scale, $new_width, $new_height) =
2269 $self->scale_calculate(%opts)
2272 if ($opts{qtype} eq 'normal') {
2273 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2274 if ( !defined($tmp->{IMG}) ) {
2275 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2278 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2279 if ( !defined($img->{IMG}) ) {
2280 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2286 elsif ($opts{'qtype'} eq 'preview') {
2287 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2288 if ( !defined($img->{IMG}) ) {
2289 $self->{ERRSTR}='unable to scale image';
2294 elsif ($opts{'qtype'} eq 'mixing') {
2295 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2296 unless ($img->{IMG}) {
2297 $self->_set_error(Imager->_error_as_msg);
2303 $self->_set_error('invalid value for qtype parameter');
2308 # Scales only along the X axis
2312 my %opts = ( scalefactor=>0.5, @_ );
2314 unless (defined wantarray) {
2315 my @caller = caller;
2316 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2320 $self->_valid_image("scaleX")
2323 my $img = Imager->new();
2325 my $scalefactor = $opts{scalefactor};
2327 if ($opts{pixels}) {
2328 $scalefactor = $opts{pixels} / $self->getwidth();
2331 unless ($self->{IMG}) {
2332 $self->{ERRSTR}='empty input image';
2336 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2338 if ( !defined($img->{IMG}) ) {
2339 $self->{ERRSTR} = 'unable to scale image';
2346 # Scales only along the Y axis
2350 my %opts = ( scalefactor => 0.5, @_ );
2352 unless (defined wantarray) {
2353 my @caller = caller;
2354 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2358 $self->_valid_image("scaleY")
2361 my $img = Imager->new();
2363 my $scalefactor = $opts{scalefactor};
2365 if ($opts{pixels}) {
2366 $scalefactor = $opts{pixels} / $self->getheight();
2369 unless ($self->{IMG}) {
2370 $self->{ERRSTR} = 'empty input image';
2373 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2375 if ( !defined($img->{IMG}) ) {
2376 $self->{ERRSTR} = 'unable to scale image';
2383 # Transform returns a spatial transformation of the input image
2384 # this moves pixels to a new location in the returned image.
2385 # NOTE - should make a utility function to check transforms for
2391 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2393 # print Dumper(\%opts);
2396 $self->_valid_image("transform")
2399 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2401 eval ("use Affix::Infix2Postfix;");
2404 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2407 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2408 {op=>'-',trans=>'Sub'},
2409 {op=>'*',trans=>'Mult'},
2410 {op=>'/',trans=>'Div'},
2411 {op=>'-','type'=>'unary',trans=>'u-'},
2413 {op=>'func','type'=>'unary'}],
2414 'grouping'=>[qw( \( \) )],
2415 'func'=>[qw( sin cos )],
2420 @xt=$I2P->translate($opts{'xexpr'});
2421 @yt=$I2P->translate($opts{'yexpr'});
2423 $numre=$I2P->{'numre'};
2426 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2427 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2428 @{$opts{'parm'}}=@pt;
2431 # print Dumper(\%opts);
2433 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2434 $self->{ERRSTR}='transform: no xopcodes given.';
2438 @op=@{$opts{'xopcodes'}};
2440 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2441 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2444 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2450 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2451 $self->{ERRSTR}='transform: no yopcodes given.';
2455 @op=@{$opts{'yopcodes'}};
2457 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2458 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2461 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2466 if ( !exists $opts{'parm'}) {
2467 $self->{ERRSTR}='transform: no parameter arg given.';
2471 # print Dumper(\@ropx);
2472 # print Dumper(\@ropy);
2473 # print Dumper(\@ropy);
2475 my $img = Imager->new();
2476 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2477 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2483 my ($opts, @imgs) = @_;
2485 require "Imager/Expr.pm";
2487 $opts->{variables} = [ qw(x y) ];
2488 my ($width, $height) = @{$opts}{qw(width height)};
2491 for my $img (@imgs) {
2492 unless ($img->_valid_image("transform2")) {
2493 Imager->_set_error($img->errstr . " (input image $index)");
2499 $width ||= $imgs[0]->getwidth();
2500 $height ||= $imgs[0]->getheight();
2502 for my $img (@imgs) {
2503 $opts->{constants}{"w$img_num"} = $img->getwidth();
2504 $opts->{constants}{"h$img_num"} = $img->getheight();
2505 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2506 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2511 $opts->{constants}{w} = $width;
2512 $opts->{constants}{cx} = $width/2;
2515 $Imager::ERRSTR = "No width supplied";
2519 $opts->{constants}{h} = $height;
2520 $opts->{constants}{cy} = $height/2;
2523 $Imager::ERRSTR = "No height supplied";
2526 my $code = Imager::Expr->new($opts);
2528 $Imager::ERRSTR = Imager::Expr::error();
2531 my $channels = $opts->{channels} || 3;
2532 unless ($channels >= 1 && $channels <= 4) {
2533 return Imager->_set_error("channels must be an integer between 1 and 4");
2536 my $img = Imager->new();
2537 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2538 $channels, $code->code(),
2539 $code->nregs(), $code->cregs(),
2540 [ map { $_->{IMG} } @imgs ]);
2541 if (!defined $img->{IMG}) {
2542 $Imager::ERRSTR = Imager->_error_as_msg();
2553 $self->_valid_image("rubthrough")
2556 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2557 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2561 %opts = (src_minx => 0,
2563 src_maxx => $opts{src}->getwidth(),
2564 src_maxy => $opts{src}->getheight(),
2568 defined $tx or $tx = $opts{left};
2569 defined $tx or $tx = 0;
2572 defined $ty or $ty = $opts{top};
2573 defined $ty or $ty = 0;
2575 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2576 $opts{src_minx}, $opts{src_miny},
2577 $opts{src_maxx}, $opts{src_maxy})) {
2578 $self->_set_error($self->_error_as_msg());
2595 $self->_valid_image("compose")
2598 unless ($opts{src}) {
2599 $self->_set_error("compose: src parameter missing");
2603 unless ($opts{src}->_valid_image("compose")) {
2604 $self->_set_error($opts{src}->errstr . " (for src)");
2607 my $src = $opts{src};
2609 my $left = $opts{left};
2610 defined $left or $left = $opts{tx};
2611 defined $left or $left = 0;
2613 my $top = $opts{top};
2614 defined $top or $top = $opts{ty};
2615 defined $top or $top = 0;
2617 my $src_left = $opts{src_left};
2618 defined $src_left or $src_left = $opts{src_minx};
2619 defined $src_left or $src_left = 0;
2621 my $src_top = $opts{src_top};
2622 defined $src_top or $src_top = $opts{src_miny};
2623 defined $src_top or $src_top = 0;
2625 my $width = $opts{width};
2626 if (!defined $width && defined $opts{src_maxx}) {
2627 $width = $opts{src_maxx} - $src_left;
2629 defined $width or $width = $src->getwidth() - $src_left;
2631 my $height = $opts{height};
2632 if (!defined $height && defined $opts{src_maxy}) {
2633 $height = $opts{src_maxy} - $src_top;
2635 defined $height or $height = $src->getheight() - $src_top;
2637 my $combine = $self->_combine($opts{combine}, 'normal');
2640 unless ($opts{mask}->_valid_image("compose")) {
2641 $self->_set_error($opts{mask}->errstr . " (for mask)");
2645 my $mask_left = $opts{mask_left};
2646 defined $mask_left or $mask_left = $opts{mask_minx};
2647 defined $mask_left or $mask_left = 0;
2649 my $mask_top = $opts{mask_top};
2650 defined $mask_top or $mask_top = $opts{mask_miny};
2651 defined $mask_top or $mask_top = 0;
2653 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2654 $left, $top, $src_left, $src_top,
2655 $mask_left, $mask_top, $width, $height,
2656 $combine, $opts{opacity})) {
2657 $self->_set_error(Imager->_error_as_msg);
2662 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2663 $width, $height, $combine, $opts{opacity})) {
2664 $self->_set_error(Imager->_error_as_msg);
2676 $self->_valid_image("flip")
2679 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2681 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2682 $dir = $xlate{$opts{'dir'}};
2683 return $self if i_flipxy($self->{IMG}, $dir);
2691 unless (defined wantarray) {
2692 my @caller = caller;
2693 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2697 $self->_valid_image("rotate")
2700 if (defined $opts{right}) {
2701 my $degrees = $opts{right};
2703 $degrees += 360 * int(((-$degrees)+360)/360);
2705 $degrees = $degrees % 360;
2706 if ($degrees == 0) {
2707 return $self->copy();
2709 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2710 my $result = Imager->new();
2711 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2715 $self->{ERRSTR} = $self->_error_as_msg();
2720 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2724 elsif (defined $opts{radians} || defined $opts{degrees}) {
2725 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2727 my $back = $opts{back};
2728 my $result = Imager->new;
2730 $back = _color($back);
2732 $self->_set_error(Imager->errstr);
2736 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2739 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2741 if ($result->{IMG}) {
2745 $self->{ERRSTR} = $self->_error_as_msg();
2750 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2755 sub matrix_transform {
2759 $self->_valid_image("matrix_transform")
2762 unless (defined wantarray) {
2763 my @caller = caller;
2764 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2768 if ($opts{matrix}) {
2769 my $xsize = $opts{xsize} || $self->getwidth;
2770 my $ysize = $opts{ysize} || $self->getheight;
2772 my $result = Imager->new;
2774 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2775 $opts{matrix}, $opts{back})
2779 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2787 $self->{ERRSTR} = "matrix parameter required";
2793 *yatf = \&matrix_transform;
2795 # These two are supported for legacy code only
2798 return Imager::Color->new(@_);
2802 return Imager::Color::set(@_);
2805 # Draws a box between the specified corner points.
2808 my $raw = $self->{IMG};
2810 $self->_valid_image("box")
2815 my ($xmin, $ymin, $xmax, $ymax);
2816 if (exists $opts{'box'}) {
2817 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2818 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2819 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2820 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2823 defined($xmin = $opts{xmin}) or $xmin = 0;
2824 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2825 defined($ymin = $opts{ymin}) or $ymin = 0;
2826 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2829 if ($opts{filled}) {
2830 my $color = $opts{'color'};
2832 if (defined $color) {
2833 unless (_is_color_object($color)) {
2834 $color = _color($color);
2836 $self->{ERRSTR} = $Imager::ERRSTR;
2842 $color = i_color_new(255,255,255,255);
2845 if ($color->isa("Imager::Color")) {
2846 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2849 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2852 elsif ($opts{fill}) {
2853 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2854 # assume it's a hash ref
2855 require 'Imager/Fill.pm';
2856 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2857 $self->{ERRSTR} = $Imager::ERRSTR;
2861 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2864 my $color = $opts{'color'};
2865 if (defined $color) {
2866 unless (_is_color_object($color)) {
2867 $color = _color($color);
2869 $self->{ERRSTR} = $Imager::ERRSTR;
2875 $color = i_color_new(255, 255, 255, 255);
2878 $self->{ERRSTR} = $Imager::ERRSTR;
2881 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2890 $self->_valid_image("arc")
2893 my $dflcl= [ 255, 255, 255, 255];
2898 'r'=>_min($self->getwidth(),$self->getheight())/3,
2899 'x'=>$self->getwidth()/2,
2900 'y'=>$self->getheight()/2,
2907 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2908 # assume it's a hash ref
2909 require 'Imager/Fill.pm';
2910 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2911 $self->{ERRSTR} = $Imager::ERRSTR;
2915 if ($opts{d1} == 0 && $opts{d2} == 361) {
2916 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2920 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2921 $opts{'d2'}, $opts{fill}{fill});
2924 elsif ($opts{filled}) {
2925 my $color = _color($opts{'color'});
2927 $self->{ERRSTR} = $Imager::ERRSTR;
2930 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2931 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2935 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2936 $opts{'d1'}, $opts{'d2'}, $color);
2940 my $color = _color($opts{'color'});
2941 if ($opts{d2} - $opts{d1} >= 360) {
2942 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2945 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2951 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2952 # assume it's a hash ref
2953 require 'Imager/Fill.pm';
2954 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2955 $self->{ERRSTR} = $Imager::ERRSTR;
2959 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2960 $opts{'d2'}, $opts{fill}{fill});
2963 my $color = _color($opts{'color'});
2965 $self->{ERRSTR} = $Imager::ERRSTR;
2968 if ($opts{filled}) {
2969 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2970 $opts{'d1'}, $opts{'d2'}, $color);
2973 if ($opts{d1} == 0 && $opts{d2} == 361) {
2974 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2977 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2983 $self->_set_error($self->_error_as_msg);
2990 # Draws a line from one point to the other
2991 # the endpoint is set if the endp parameter is set which it is by default.
2992 # to turn of the endpoint being set use endp=>0 when calling line.
2996 my $dflcl=i_color_new(0,0,0,0);
2997 my %opts=(color=>$dflcl,
3001 $self->_valid_image("line")
3004 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
3005 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
3007 my $color = _color($opts{'color'});
3009 $self->{ERRSTR} = $Imager::ERRSTR;
3013 $opts{antialias} = $opts{aa} if defined $opts{aa};
3014 if ($opts{antialias}) {
3015 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3016 $color, $opts{endp});
3018 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3019 $color, $opts{endp});
3024 # Draws a line between an ordered set of points - It more or less just transforms this
3025 # into a list of lines.
3029 my ($pt,$ls,@points);
3030 my $dflcl=i_color_new(0,0,0,0);
3031 my %opts=(color=>$dflcl,@_);
3033 $self->_valid_image("polyline")
3036 if (exists($opts{points})) { @points=@{$opts{points}}; }
3037 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3038 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3041 # print Dumper(\@points);
3043 my $color = _color($opts{'color'});
3045 $self->{ERRSTR} = $Imager::ERRSTR;
3048 $opts{antialias} = $opts{aa} if defined $opts{aa};
3049 if ($opts{antialias}) {
3052 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3059 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3069 my ($pt,$ls,@points);
3070 my $dflcl = i_color_new(0,0,0,0);
3071 my %opts = (color=>$dflcl, @_);
3073 $self->_valid_image("polygon")
3076 if (exists($opts{points})) {
3077 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3078 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3081 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3082 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3085 my $mode = _first($opts{mode}, 0);
3087 if ($opts{'fill'}) {
3088 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3089 # assume it's a hash ref
3090 require 'Imager/Fill.pm';
3091 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3092 $self->{ERRSTR} = $Imager::ERRSTR;
3096 i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3097 $mode, $opts{'fill'}{'fill'});
3100 my $color = _color($opts{'color'});
3102 $self->{ERRSTR} = $Imager::ERRSTR;
3105 i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color);
3112 my ($self, %opts) = @_;
3114 $self->_valid_image("polypolygon")
3117 my $points = $opts{points};
3119 or return $self->_set_error("polypolygon: missing required points");
3121 my $mode = _first($opts{mode}, "evenodd");
3123 if ($opts{filled}) {
3124 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3125 or return $self->_set_error($Imager::ERRSTR);
3127 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3128 or return $self->_set_error($self->_error_as_msg);
3130 elsif ($opts{fill}) {
3131 my $fill = $opts{fill};
3132 $self->_valid_fill($fill, "polypolygon")
3135 i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3136 or return $self->_set_error($self->_error_as_msg);
3139 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3140 or return $self->_set_error($Imager::ERRSTR);
3142 my $rimg = $self->{IMG};
3144 if (_first($opts{aa}, 1)) {
3145 for my $poly (@$points) {
3146 my $xp = $poly->[0];
3147 my $yp = $poly->[1];
3148 for my $i (0 .. $#$xp - 1) {
3149 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3152 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3157 for my $poly (@$points) {
3158 my $xp = $poly->[0];
3159 my $yp = $poly->[1];
3160 for my $i (0 .. $#$xp - 1) {
3161 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3164 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3173 # this the multipoint bezier curve
3174 # this is here more for testing that actual usage since
3175 # this is not a good algorithm. Usually the curve would be
3176 # broken into smaller segments and each done individually.
3180 my ($pt,$ls,@points);
3181 my $dflcl=i_color_new(0,0,0,0);
3182 my %opts=(color=>$dflcl,@_);
3184 $self->_valid_image("polybezier")
3187 if (exists $opts{points}) {
3188 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3189 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3192 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3193 $self->{ERRSTR}='Missing or invalid points.';
3197 my $color = _color($opts{'color'});
3199 $self->{ERRSTR} = $Imager::ERRSTR;
3202 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3208 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3211 $self->_valid_image("flood_fill")
3214 unless (exists $opts{'x'} && exists $opts{'y'}) {
3215 $self->{ERRSTR} = "missing seed x and y parameters";
3219 if ($opts{border}) {
3220 my $border = _color($opts{border});
3222 $self->_set_error($Imager::ERRSTR);
3226 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3227 # assume it's a hash ref
3228 require Imager::Fill;
3229 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3230 $self->{ERRSTR} = $Imager::ERRSTR;
3234 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3235 $opts{fill}{fill}, $border);
3238 my $color = _color($opts{'color'});
3240 $self->{ERRSTR} = $Imager::ERRSTR;
3243 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3250 $self->{ERRSTR} = $self->_error_as_msg();
3256 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3257 # assume it's a hash ref
3258 require 'Imager/Fill.pm';
3259 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3260 $self->{ERRSTR} = $Imager::ERRSTR;
3264 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3267 my $color = _color($opts{'color'});
3269 $self->{ERRSTR} = $Imager::ERRSTR;
3272 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3278 $self->{ERRSTR} = $self->_error_as_msg();
3285 my ($self, %opts) = @_;
3287 $self->_valid_image("setpixel")
3290 my $color = $opts{color};
3291 unless (defined $color) {
3292 $color = $self->{fg};
3293 defined $color or $color = NC(255, 255, 255);
3296 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3297 unless ($color = _color($color, 'setpixel')) {
3298 $self->_set_error("setpixel: " . Imager->errstr);
3303 unless (exists $opts{'x'} && exists $opts{'y'}) {
3304 $self->_set_error('setpixel: missing x or y parameter');
3310 if (ref $x || ref $y) {
3311 $x = ref $x ? $x : [ $x ];
3312 $y = ref $y ? $y : [ $y ];
3314 $self->_set_error("setpixel: x is a reference to an empty array");
3318 $self->_set_error("setpixel: y is a reference to an empty array");
3322 # make both the same length, replicating the last element
3324 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3327 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3331 if ($color->isa('Imager::Color')) {
3332 for my $i (0..$#$x) {
3333 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3338 for my $i (0..$#$x) {
3339 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3347 if ($color->isa('Imager::Color')) {
3348 i_ppix($self->{IMG}, $x, $y, $color)
3349 and return "0 but true";
3352 i_ppixf($self->{IMG}, $x, $y, $color)
3353 and return "0 but true";
3363 my %opts = ( "type"=>'8bit', @_);
3365 $self->_valid_image("getpixel")
3368 unless (exists $opts{'x'} && exists $opts{'y'}) {
3369 $self->_set_error('getpixel: missing x or y parameter');
3375 my $type = $opts{'type'};
3376 if (ref $x || ref $y) {
3377 $x = ref $x ? $x : [ $x ];
3378 $y = ref $y ? $y : [ $y ];
3380 $self->_set_error("getpixel: x is a reference to an empty array");
3384 $self->_set_error("getpixel: y is a reference to an empty array");
3388 # make both the same length, replicating the last element
3390 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3393 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3397 if ($type eq '8bit') {
3398 for my $i (0..$#$x) {
3399 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3402 elsif ($type eq 'float' || $type eq 'double') {
3403 for my $i (0..$#$x) {
3404 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3408 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3411 return wantarray ? @result : \@result;
3414 if ($type eq '8bit') {
3415 return i_get_pixel($self->{IMG}, $x, $y);
3417 elsif ($type eq 'float' || $type eq 'double') {
3418 return i_gpixf($self->{IMG}, $x, $y);
3421 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3429 my %opts = ( type => '8bit', x=>0, @_);
3431 $self->_valid_image("getscanline")
3434 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3436 unless (defined $opts{'y'}) {
3437 $self->_set_error("missing y parameter");
3441 if ($opts{type} eq '8bit') {
3442 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3445 elsif ($opts{type} eq 'float') {
3446 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3449 elsif ($opts{type} eq 'index') {
3450 unless (i_img_type($self->{IMG})) {
3451 $self->_set_error("type => index only valid on paletted images");
3454 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3458 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3465 my %opts = ( x=>0, @_);
3467 $self->_valid_image("setscanline")
3470 unless (defined $opts{'y'}) {
3471 $self->_set_error("missing y parameter");
3476 if (ref $opts{pixels} && @{$opts{pixels}}) {
3477 # try to guess the type
3478 if ($opts{pixels}[0]->isa('Imager::Color')) {
3479 $opts{type} = '8bit';
3481 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3482 $opts{type} = 'float';
3485 $self->_set_error("missing type parameter and could not guess from pixels");
3491 $opts{type} = '8bit';
3495 if ($opts{type} eq '8bit') {
3496 if (ref $opts{pixels}) {
3497 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3500 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3503 elsif ($opts{type} eq 'float') {
3504 if (ref $opts{pixels}) {
3505 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3508 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3511 elsif ($opts{type} eq 'index') {
3512 if (ref $opts{pixels}) {
3513 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3516 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3520 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3527 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3529 $self->_valid_image("getsamples")
3532 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3534 unless (defined $opts{'y'}) {
3535 $self->_set_error("missing y parameter");
3539 if ($opts{target}) {
3540 my $target = $opts{target};
3541 my $offset = $opts{offset};
3542 if ($opts{type} eq '8bit') {
3543 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3544 $opts{y}, $opts{channels})
3546 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3547 return scalar(@samples);
3549 elsif ($opts{type} eq 'float') {
3550 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3551 $opts{y}, $opts{channels});
3552 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3553 return scalar(@samples);
3555 elsif ($opts{type} =~ /^(\d+)bit$/) {
3559 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3560 $opts{y}, $bits, $target,
3561 $offset, $opts{channels});
3562 unless (defined $count) {
3563 $self->_set_error(Imager->_error_as_msg);
3570 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3575 if ($opts{type} eq '8bit') {
3576 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3577 $opts{y}, $opts{channels});
3579 elsif ($opts{type} eq 'float') {
3580 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3581 $opts{y}, $opts{channels});
3583 elsif ($opts{type} =~ /^(\d+)bit$/) {
3587 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3588 $opts{y}, $bits, \@data, 0, $opts{channels})
3593 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3602 $self->_valid_image("setsamples")
3605 my %opts = ( x => 0, offset => 0 );
3607 # avoid duplicating the data parameter, it may be a large scalar
3609 while ($i < @_ -1) {
3610 if ($_[$i] eq 'data') {
3614 $opts{$_[$i]} = $_[$i+1];
3620 unless(defined $data_index) {
3621 $self->_set_error('setsamples: data parameter missing');
3624 unless (defined $_[$data_index]) {
3625 $self->_set_error('setsamples: data parameter not defined');
3629 my $type = $opts{type};
3630 defined $type or $type = '8bit';
3632 my $width = defined $opts{width} ? $opts{width}
3633 : $self->getwidth() - $opts{x};
3636 if ($type eq '8bit') {
3637 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3638 $_[$data_index], $opts{offset}, $width);
3640 elsif ($type eq 'float') {
3641 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3642 $_[$data_index], $opts{offset}, $width);
3644 elsif ($type =~ /^([0-9]+)bit$/) {
3647 unless (ref $_[$data_index]) {
3648 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3652 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3653 $opts{channels}, $_[$data_index], $opts{offset},
3657 $self->_set_error('setsamples: type parameter invalid');
3661 unless (defined $count) {
3662 $self->_set_error(Imager->_error_as_msg);
3669 # make an identity matrix of the given size
3673 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3674 for my $c (0 .. ($size-1)) {
3675 $matrix->[$c][$c] = 1;
3680 # general function to convert an image
3682 my ($self, %opts) = @_;
3685 $self->_valid_image("convert")
3688 unless (defined wantarray) {
3689 my @caller = caller;
3690 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3694 # the user can either specify a matrix or preset
3695 # the matrix overrides the preset
3696 if (!exists($opts{matrix})) {
3697 unless (exists($opts{preset})) {
3698 $self->{ERRSTR} = "convert() needs a matrix or preset";
3702 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3703 # convert to greyscale, keeping the alpha channel if any
3704 if ($self->getchannels == 3) {
3705 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3707 elsif ($self->getchannels == 4) {
3708 # preserve the alpha channel
3709 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3714 $matrix = _identity($self->getchannels);
3717 elsif ($opts{preset} eq 'noalpha') {
3718 # strip the alpha channel
3719 if ($self->getchannels == 2 or $self->getchannels == 4) {
3720 $matrix = _identity($self->getchannels);
3721 pop(@$matrix); # lose the alpha entry
3724 $matrix = _identity($self->getchannels);
3727 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3729 $matrix = [ [ 1 ] ];
3731 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3732 $matrix = [ [ 0, 1 ] ];
3734 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3735 $matrix = [ [ 0, 0, 1 ] ];
3737 elsif ($opts{preset} eq 'alpha') {
3738 if ($self->getchannels == 2 or $self->getchannels == 4) {
3739 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3742 # the alpha is just 1 <shrug>
3743 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3746 elsif ($opts{preset} eq 'rgb') {
3747 if ($self->getchannels == 1) {
3748 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3750 elsif ($self->getchannels == 2) {
3751 # preserve the alpha channel
3752 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3755 $matrix = _identity($self->getchannels);
3758 elsif ($opts{preset} eq 'addalpha') {
3759 if ($self->getchannels == 1) {
3760 $matrix = _identity(2);
3762 elsif ($self->getchannels == 3) {
3763 $matrix = _identity(4);
3766 $matrix = _identity($self->getchannels);
3770 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3776 $matrix = $opts{matrix};
3779 my $new = Imager->new;
3780 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3781 unless ($new->{IMG}) {
3782 # most likely a bad matrix
3783 i_push_error(0, "convert");
3784 $self->{ERRSTR} = _error_as_msg();
3790 # combine channels from multiple input images, a class method
3792 my ($class, %opts) = @_;
3794 my $src = delete $opts{src};
3796 $class->_set_error("src parameter missing");
3801 for my $img (@$src) {
3802 unless (eval { $img->isa("Imager") }) {
3803 $class->_set_error("src must contain image objects");
3806 unless ($img->_valid_image("combine")) {
3807 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3810 push @imgs, $img->{IMG};
3813 if (my $channels = delete $opts{channels}) {
3814 $result = i_combine(\@imgs, $channels);
3817 $result = i_combine(\@imgs);
3820 $class->_set_error($class->_error_as_msg);
3824 my $img = $class->new;
3825 $img->{IMG} = $result;
3831 # general function to map an image through lookup tables
3834 my ($self, %opts) = @_;
3835 my @chlist = qw( red green blue alpha );
3837 $self->_valid_image("map")
3840 if (!exists($opts{'maps'})) {
3841 # make maps from channel maps
3843 for $chnum (0..$#chlist) {
3844 if (exists $opts{$chlist[$chnum]}) {
3845 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3846 } elsif (exists $opts{'all'}) {
3847 $opts{'maps'}[$chnum] = $opts{'all'};
3851 if ($opts{'maps'} and $self->{IMG}) {
3852 i_map($self->{IMG}, $opts{'maps'} );
3858 my ($self, %opts) = @_;
3860 $self->_valid_image("difference")
3863 defined $opts{mindist} or $opts{mindist} = 0;
3865 defined $opts{other}
3866 or return $self->_set_error("No 'other' parameter supplied");
3867 unless ($opts{other}->_valid_image("difference")) {
3868 $self->_set_error($opts{other}->errstr . " (other image)");
3872 my $result = Imager->new;
3873 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3875 or return $self->_set_error($self->_error_as_msg());
3880 # destructive border - image is shrunk by one pixel all around
3883 my ($self,%opts)=@_;
3884 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3885 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3889 # Get the width of an image
3894 $self->_valid_image("getwidth")
3897 return i_img_get_width($self->{IMG});
3900 # Get the height of an image
3905 $self->_valid_image("getheight")
3908 return i_img_get_height($self->{IMG});
3911 # Get number of channels in an image
3916 $self->_valid_image("getchannels")
3919 return i_img_getchannels($self->{IMG});
3922 my @model_names = qw(unknown gray graya rgb rgba);
3925 my ($self, %opts) = @_;
3927 $self->_valid_image("colormodel")
3930 my $model = i_img_color_model($self->{IMG});
3932 return $opts{numeric} ? $model : $model_names[$model];
3938 $self->_valid_image("colorchannels")
3941 return i_img_color_channels($self->{IMG});
3947 $self->_valid_image("alphachannel")
3950 return scalar(i_img_alpha_channel($self->{IMG}));
3958 $self->_valid_image("getmask")
3961 return i_img_getmask($self->{IMG});
3970 $self->_valid_image("setmask")
3973 unless (defined $opts{mask}) {
3974 $self->_set_error("mask parameter required");
3978 i_img_setmask( $self->{IMG} , $opts{mask} );
3983 # Get number of colors in an image
3987 my %opts=('maxcolors'=>2**30,@_);
3989 $self->_valid_image("getcolorcount")
3992 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3993 return ($rc==-1? undef : $rc);
3996 # Returns a reference to a hash. The keys are colour named (packed) and the
3997 # values are the number of pixels in this colour.
3998 sub getcolorusagehash {
4001 $self->_valid_image("getcolorusagehash")
4004 my %opts = ( maxcolors => 2**30, @_ );
4005 my $max_colors = $opts{maxcolors};
4006 unless (defined $max_colors && $max_colors > 0) {
4007 $self->_set_error('maxcolors must be a positive integer');
4011 my $channels= $self->getchannels;
4012 # We don't want to look at the alpha channel, because some gifs using it
4013 # doesn't define it for every colour (but only for some)
4014 $channels -= 1 if $channels == 2 or $channels == 4;
4016 my $height = $self->getheight;
4017 for my $y (0 .. $height - 1) {
4018 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4019 while (length $colors) {
4020 $color_use{ substr($colors, 0, $channels, '') }++;
4022 keys %color_use > $max_colors
4028 # This will return a ordered array of the colour usage. Kind of the sorted
4029 # version of the values of the hash returned by getcolorusagehash.
4030 # You might want to add safety checks and change the names, etc...
4034 $self->_valid_image("getcolorusage")
4037 my %opts = ( maxcolors => 2**30, @_ );
4038 my $max_colors = $opts{maxcolors};
4039 unless (defined $max_colors && $max_colors > 0) {
4040 $self->_set_error('maxcolors must be a positive integer');
4044 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4047 # draw string to an image
4052 $self->_valid_image("string")
4055 my %input=('x'=>0, 'y'=>0, @_);
4056 defined($input{string}) or $input{string} = $input{text};
4058 unless(defined $input{string}) {
4059 $self->{ERRSTR}="missing required parameter 'string'";
4063 unless($input{font}) {
4064 $self->{ERRSTR}="missing required parameter 'font'";
4068 unless ($input{font}->draw(image=>$self, %input)) {
4080 $self->_valid_image("align_string")
4089 my %input=('x'=>0, 'y'=>0, @_);
4090 defined $input{string}
4091 or $input{string} = $input{text};
4093 unless(exists $input{string}) {
4094 $self->_set_error("missing required parameter 'string'");
4098 unless($input{font}) {
4099 $self->_set_error("missing required parameter 'font'");
4104 unless (@result = $input{font}->align(image=>$img, %input)) {
4108 return wantarray ? @result : $result[0];
4111 my @file_limit_names = qw/width height bytes/;
4113 sub set_file_limits {
4120 @values{@file_limit_names} = (0) x @file_limit_names;
4123 @values{@file_limit_names} = i_get_image_file_limits();
4126 for my $key (keys %values) {
4127 defined $opts{$key} and $values{$key} = $opts{$key};
4130 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4133 sub get_file_limits {
4134 i_get_image_file_limits();
4137 my @check_args = qw(width height channels sample_size);
4139 sub check_file_limits {
4149 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4150 $opts{sample_size} = length(pack("d", 0));
4153 for my $name (@check_args) {
4154 unless (defined $opts{$name}) {
4155 $class->_set_error("check_file_limits: $name must be defined");
4158 unless ($opts{$name} == int($opts{$name})) {
4159 $class->_set_error("check_file_limits: $name must be a positive integer");
4164 my $result = i_int_check_image_file_limits(@opts{@check_args});
4166 $class->_set_error($class->_error_as_msg());
4172 # Shortcuts that can be exported
4174 sub newcolor { Imager::Color->new(@_); }
4175 sub newfont { Imager::Font->new(@_); }
4177 require Imager::Color::Float;
4178 return Imager::Color::Float->new(@_);
4181 *NC=*newcolour=*newcolor;
4188 #### Utility routines
4191 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4195 my ($self, $msg) = @_;
4198 $self->{ERRSTR} = $msg;
4206 # Default guess for the type of an image from extension
4208 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4212 ( map { $_ => $_ } @simple_types ),
4218 pnm => "pnm", # technically wrong, but historically it works in Imager
4231 sub def_guess_type {
4234 my ($ext) = $name =~ /\.([^.]+)$/
4237 my $type = $ext_types{$ext}
4244 return @combine_types;
4247 # get the minimum of a list
4251 for(@_) { if ($_<$mx) { $mx=$_; }}
4255 # get the maximum of a list
4259 for(@_) { if ($_>$mx) { $mx=$_; }}
4263 # string stuff for iptc headers
4267 $str = substr($str,3);
4268 $str =~ s/[\n\r]//g;
4275 # A little hack to parse iptc headers.
4280 my($caption,$photogr,$headln,$credit);
4282 my $str=$self->{IPTCRAW};
4287 @ar=split(/8BIM/,$str);
4292 @sar=split(/\034\002/);
4293 foreach $item (@sar) {
4294 if ($item =~ m/^x/) {
4295 $caption = _clean($item);
4298 if ($item =~ m/^P/) {
4299 $photogr = _clean($item);
4302 if ($item =~ m/^i/) {
4303 $headln = _clean($item);
4306 if ($item =~ m/^n/) {
4307 $credit = _clean($item);
4313 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4317 # Inline added a new argument at the beginning
4321 or die "Only C language supported";
4323 require Imager::ExtUtils;
4324 return Imager::ExtUtils->inline_config;
4327 # threads shouldn't try to close raw Imager objects
4328 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4331 # this serves two purposes:
4332 # - a class method to load the file support modules included with Imager
4333 # (or were included, once the library dependent modules are split out)
4334 # - something for Module::ScanDeps to analyze
4335 # https://rt.cpan.org/Ticket/Display.html?id=6566
4337 eval { require Imager::File::GIF };
4338 eval { require Imager::File::JPEG };
4339 eval { require Imager::File::PNG };
4340 eval { require Imager::File::SGI };
4341 eval { require Imager::File::TIFF };
4342 eval { require Imager::File::ICO };
4343 eval { require Imager::Font::W32 };
4344 eval { require Imager::Font::FT2 };
4345 eval { require Imager::Font::T1 };
4346 eval { require Imager::Color::Table };
4355 my ($class, $fh) = @_;
4358 return $class->new_cb
4363 return print $fh $_[0];
4367 my $count = CORE::read $fh, $tmp, $_[1];
4375 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4376 unless (CORE::seek $fh, $_[0], $_[1]) {
4387 return $class->_new_perlio($fh);
4391 # backward compatibility for %formats
4392 package Imager::FORMATS;
4394 use constant IX_FORMATS => 0;
4395 use constant IX_LIST => 1;
4396 use constant IX_INDEX => 2;
4397 use constant IX_CLASSES => 3;
4400 my ($class, $formats, $classes) = @_;
4402 return bless [ $formats, [ ], 0, $classes ], $class;
4406 my ($self, $key) = @_;
4408 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4411 my $loaded = Imager::_load_file($file, \$error);
4416 if ($error =~ /^Can't locate /) {
4417 $error = "Can't locate $file";
4419 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4422 $self->[IX_FORMATS]{$key} = $value;
4428 my ($self, $key) = @_;
4430 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4432 $self->[IX_CLASSES]{$key} or return undef;
4434 return $self->_check($key);
4438 die "%Imager::formats is not user monifiable";
4442 die "%Imager::formats is not user monifiable";
4446 die "%Imager::formats is not user monifiable";
4450 my ($self, $key) = @_;
4452 if (exists $self->[IX_FORMATS]{$key}) {
4453 my $value = $self->[IX_FORMATS]{$key}
4458 $self->_check($key) or return 1==0;
4466 unless (@{$self->[IX_LIST]}) {
4468 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4469 keys %{$self->[IX_FORMATS]};
4471 for my $key (keys %{$self->[IX_CLASSES]}) {
4472 $self->[IX_FORMATS]{$key} and next;
4474 and push @{$self->[IX_LIST]}, $key;
4478 @{$self->[IX_LIST]} or return;
4479 $self->[IX_INDEX] = 1;
4480 return $self->[IX_LIST][0];
4486 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4489 return $self->[IX_LIST][$self->[IX_INDEX]++];
4495 return scalar @{$self->[IX_LIST]};
4500 # Below is the stub of documentation for your module. You better edit it!
4504 Imager - Perl extension for Generating 24 bit Images
4514 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4519 # see Imager::Files for information on the read() method
4520 my $img = Imager->new(file=>$file)
4521 or die Imager->errstr();
4523 $file =~ s/\.[^.]*$//;
4525 # Create smaller version
4526 # documented in Imager::Transformations
4527 my $thumb = $img->scale(scalefactor=>.3);
4529 # Autostretch individual channels
4530 $thumb->filter(type=>'autolevels');
4532 # try to save in one of these formats
4535 for $format ( qw( png gif jpeg tiff ppm ) ) {
4536 # Check if given format is supported
4537 if ($Imager::formats{$format}) {
4538 $file.="_low.$format";
4539 print "Storing image as: $file\n";
4540 # documented in Imager::Files
4541 $thumb->write(file=>$file) or
4549 Imager is a module for creating and altering images. It can read and
4550 write various image formats, draw primitive shapes like lines,and
4551 polygons, blend multiple images together in various ways, scale, crop,
4552 render text and more.
4554 =head2 Overview of documentation
4560 Imager - This document - Synopsis, Example, Table of Contents and
4565 L<Imager::Install> - installation notes for Imager.
4569 L<Imager::Tutorial> - a brief introduction to Imager.
4573 L<Imager::Cookbook> - how to do various things with Imager.
4577 L<Imager::ImageTypes> - Basics of constructing image objects with
4578 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4579 8/16/double bits/channel, color maps, channel masks, image tags, color
4580 quantization. Also discusses basic image information methods.
4584 L<Imager::Files> - IO interaction, reading/writing images, format
4589 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4594 L<Imager::Color> - Color specification.
4598 L<Imager::Fill> - Fill pattern specification.
4602 L<Imager::Font> - General font rendering, bounding boxes and font
4607 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4608 blending, pasting, convert and map.
4612 L<Imager::Engines> - Programmable transformations through
4613 C<transform()>, C<transform2()> and C<matrix_transform()>.
4617 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4622 L<Imager::Expr> - Expressions for evaluation engine used by
4627 L<Imager::Matrix2d> - Helper class for affine transformations.
4631 L<Imager::Fountain> - Helper for making gradient profiles.
4635 L<Imager::IO> - Imager I/O abstraction.
4639 L<Imager::API> - using Imager's C API
4643 L<Imager::APIRef> - API function reference
4647 L<Imager::Inline> - using Imager's C API from Inline::C
4651 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4655 L<Imager::Security> - brief security notes.
4659 L<Imager::Threads> - brief information on working with threads.
4663 =head2 Basic Overview
4665 An Image object is created with C<$img = Imager-E<gt>new()>.
4668 $img=Imager->new(); # create empty image
4669 $img->read(file=>'lena.png',type=>'png') or # read image from file
4670 die $img->errstr(); # give an explanation
4671 # if something failed
4673 or if you want to create an empty image:
4675 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4677 This example creates a completely black image of width 400 and height
4680 =head1 ERROR HANDLING
4682 In general a method will return false when it fails, if it does use
4683 the C<errstr()> method to find out why:
4689 Returns the last error message in that context.
4691 If the last error you received was from calling an object method, such
4692 as read, call errstr() as an object method to find out why:
4694 my $image = Imager->new;
4695 $image->read(file => 'somefile.gif')
4696 or die $image->errstr;
4698 If it was a class method then call errstr() as a class method:
4700 my @imgs = Imager->read_multi(file => 'somefile.gif')
4701 or die Imager->errstr;
4703 Note that in some cases object methods are implemented in terms of
4704 class methods so a failing object method may set both.
4708 The C<Imager-E<gt>new> method is described in detail in
4709 L<Imager::ImageTypes>.
4713 Where to find information on methods for Imager class objects.
4715 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4718 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4720 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4723 alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
4724 channel index of the alpha channel (if any).
4726 arc() - L<Imager::Draw/arc()> - draw a filled arc
4728 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4731 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4733 check_file_limits() - L<Imager::Files/check_file_limits()>
4735 circle() - L<Imager::Draw/circle()> - draw a filled circle
4737 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4740 colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
4741 of channels used for color.
4743 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4744 colors in an image's palette (paletted images only)
4746 colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
4749 combine() - L<Imager::Transformations/combine()> - combine channels
4750 from one or more images.
4752 combines() - L<Imager::Draw/combines()> - return a list of the
4753 different combine type keywords
4755 compose() - L<Imager::Transformations/compose()> - compose one image
4758 convert() - L<Imager::Transformations/convert()> - transform the color
4761 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4764 crop() - L<Imager::Transformations/crop()> - extract part of an image
4766 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4767 used to guess the output file format based on the output file name
4769 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4771 difference() - L<Imager::Filters/difference()> - produce a difference
4772 images from two input images.
4774 errstr() - L</errstr()> - the error from the last failed operation.
4776 filter() - L<Imager::Filters/filter()> - image filtering
4778 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4779 palette, if it has one
4781 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4784 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4787 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4788 samples per pixel for an image
4790 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4791 different colors used by an image (works for direct color images)
4793 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4794 palette, if it has one
4796 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4798 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4800 get_file_limits() - L<Imager::Files/get_file_limits()>
4802 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4805 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4807 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4810 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4811 row or partial row of pixels.
4813 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4814 row or partial row of pixels.
4816 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4819 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4822 init() - L<Imager::ImageTypes/init()>
4824 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4825 image write functions should write the image in their bilevel (blank
4826 and white, no gray levels) format
4828 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4831 line() - L<Imager::Draw/line()> - draw an interval
4833 load_plugin() - L<Imager::Filters/load_plugin()>
4835 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4838 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4839 color palette from one or more input images.
4841 map() - L<Imager::Transformations/map()> - remap color
4844 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4846 matrix_transform() - L<Imager::Engines/matrix_transform()>
4848 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4850 NC() - L<Imager::Handy/NC()>
4852 NCF() - L<Imager::Handy/NCF()>
4854 new() - L<Imager::ImageTypes/new()>
4856 newcolor() - L<Imager::Handy/newcolor()>
4858 newcolour() - L<Imager::Handy/newcolour()>
4860 newfont() - L<Imager::Handy/newfont()>
4862 NF() - L<Imager::Handy/NF()>
4864 open() - L<Imager::Files/read()> - an alias for read()
4866 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4870 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4873 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4876 polygon() - L<Imager::Draw/polygon()>
4878 polyline() - L<Imager::Draw/polyline()>
4880 polypolygon() - L<Imager::Draw/polypolygon()>
4882 preload() - L<Imager::Files/preload()>
4884 read() - L<Imager::Files/read()> - read a single image from an image file
4886 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4889 read_types() - L<Imager::Files/read_types()> - list image types Imager
4892 register_filter() - L<Imager::Filters/register_filter()>
4894 register_reader() - L<Imager::Files/register_reader()>
4896 register_writer() - L<Imager::Files/register_writer()>
4898 rotate() - L<Imager::Transformations/rotate()>
4900 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4901 onto an image and use the alpha channel
4903 scale() - L<Imager::Transformations/scale()>
4905 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4907 scaleX() - L<Imager::Transformations/scaleX()>
4909 scaleY() - L<Imager::Transformations/scaleY()>
4911 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4914 set_file_limits() - L<Imager::Files/set_file_limits()>
4916 setmask() - L<Imager::ImageTypes/setmask()>
4918 setpixel() - L<Imager::Draw/setpixel()>
4920 setsamples() - L<Imager::Draw/setsamples()>
4922 setscanline() - L<Imager::Draw/setscanline()>
4924 settag() - L<Imager::ImageTypes/settag()>
4926 string() - L<Imager::Draw/string()> - draw text on an image
4928 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4930 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4932 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4934 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4936 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4937 double per sample image.
4939 transform() - L<Imager::Engines/"transform()">
4941 transform2() - L<Imager::Engines/"transform2()">
4943 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4945 unload_plugin() - L<Imager::Filters/unload_plugin()>
4947 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4950 write() - L<Imager::Files/write()> - write an image to a file
4952 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4955 write_types() - L<Imager::Files/read_types()> - list image types Imager
4958 =head1 CONCEPT INDEX
4960 animated GIF - L<Imager::Files/"Writing an animated GIF">
4962 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4963 L<Imager::ImageTypes/"Common Tags">.
4965 blend - alpha blending one image onto another
4966 L<Imager::Transformations/rubthrough()>
4968 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4970 boxes, drawing - L<Imager::Draw/box()>
4972 changes between image - L<Imager::Filters/"Image Difference">
4974 channels, combine into one image - L<Imager::Transformations/combine()>
4976 color - L<Imager::Color>
4978 color names - L<Imager::Color>, L<Imager::Color::Table>
4980 combine modes - L<Imager::Draw/"Combine Types">
4982 compare images - L<Imager::Filters/"Image Difference">
4984 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4986 convolution - L<Imager::Filters/conv>
4988 cropping - L<Imager::Transformations/crop()>
4990 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4992 C<diff> images - L<Imager::Filters/"Image Difference">
4994 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4995 L<Imager::Cookbook/"Image spatial resolution">
4997 drawing boxes - L<Imager::Draw/box()>
4999 drawing lines - L<Imager::Draw/line()>
5001 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
5003 error message - L</"ERROR HANDLING">
5005 files, font - L<Imager::Font>
5007 files, image - L<Imager::Files>
5009 filling, types of fill - L<Imager::Fill>
5011 filling, boxes - L<Imager::Draw/box()>
5013 filling, flood fill - L<Imager::Draw/flood_fill()>
5015 flood fill - L<Imager::Draw/flood_fill()>
5017 fonts - L<Imager::Font>
5019 fonts, drawing with - L<Imager::Draw/string()>,
5020 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
5022 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5024 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
5026 fountain fill - L<Imager::Fill/"Fountain fills">,
5027 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5028 L<Imager::Filters/gradgen>
5030 GIF files - L<Imager::Files/"GIF">
5032 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
5034 gradient fill - L<Imager::Fill/"Fountain fills">,
5035 L<Imager::Filters/fountain>, L<Imager::Fountain>,
5036 L<Imager::Filters/gradgen>
5038 gray scale, convert image to - L<Imager::Transformations/convert()>
5040 gaussian blur - L<Imager::Filters/gaussian>
5042 hatch fills - L<Imager::Fill/"Hatched fills">
5044 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
5046 invert image - L<Imager::Filters/hardinvert>,
5047 L<Imager::Filters/hardinvertall>
5049 JPEG - L<Imager::Files/"JPEG">
5051 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
5053 lines, drawing - L<Imager::Draw/line()>
5055 matrix - L<Imager::Matrix2d>,
5056 L<Imager::Engines/"Matrix Transformations">,
5057 L<Imager::Font/transform()>
5059 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
5061 mosaic - L<Imager::Filters/mosaic>
5063 noise, filter - L<Imager::Filters/noise>
5065 noise, rendered - L<Imager::Filters/turbnoise>,
5066 L<Imager::Filters/radnoise>
5068 paste - L<Imager::Transformations/paste()>,
5069 L<Imager::Transformations/rubthrough()>
5071 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
5072 L<Imager::ImageTypes/new()>
5074 =for stopwords posterize
5076 posterize - L<Imager::Filters/postlevels>
5078 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
5080 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
5082 rectangles, drawing - L<Imager::Draw/box()>
5084 resizing an image - L<Imager::Transformations/scale()>,
5085 L<Imager::Transformations/crop()>
5087 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
5089 saving an image - L<Imager::Files>
5091 scaling - L<Imager::Transformations/scale()>
5093 security - L<Imager::Security>
5095 SGI files - L<Imager::Files/"SGI (RGB, BW)">
5097 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
5099 size, image - L<Imager::ImageTypes/getwidth()>,
5100 L<Imager::ImageTypes/getheight()>
5102 size, text - L<Imager::Font/bounding_box()>
5104 tags, image metadata - L<Imager::ImageTypes/"Tags">
5106 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
5107 L<Imager::Font::Wrap>
5109 text, wrapping text in an area - L<Imager::Font::Wrap>
5111 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
5113 threads - L<Imager::Threads>
5115 tiles, color - L<Imager::Filters/mosaic>
5117 transparent images - L<Imager::ImageTypes>,
5118 L<Imager::Cookbook/"Transparent PNG">
5120 =for stopwords unsharp
5122 unsharp mask - L<Imager::Filters/unsharpmask>
5124 watermark - L<Imager::Filters/watermark>
5126 writing an image to a file - L<Imager::Files>
5130 The best place to get help with Imager is the mailing list.
5132 To subscribe send a message with C<subscribe> in the body to:
5134 imager-devel+request@molar.is
5140 L<http://www.molar.is/en/lists/imager-devel/>
5144 where you can also find the mailing list archive.
5146 You can report bugs by pointing your browser at:
5150 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5154 or by sending an email to:
5158 bug-Imager@rt.cpan.org
5162 Please remember to include the versions of Imager, perl, supporting
5163 libraries, and any relevant code. If you have specific images that
5164 cause the problems, please include those too.
5166 If you don't want to publish your email address on a mailing list you
5167 can use CPAN::Forum:
5169 http://www.cpanforum.com/dist/Imager
5171 You will need to register to post.
5173 =head1 CONTRIBUTING TO IMAGER
5179 If you like or dislike Imager, you can add a public review of Imager
5182 http://cpanratings.perl.org/dist/Imager
5184 =for stopwords Bitcard
5186 This requires a Bitcard account (http://www.bitcard.org).
5188 You can also send email to the maintainer below.
5190 If you send me a bug report via email, it will be copied to Request
5195 I accept patches, preferably against the master branch in git. Please
5196 include an explanation of the reason for why the patch is needed or
5199 Your patch should include regression tests where possible, otherwise
5200 it will be delayed until I get a chance to write them.
5202 To browse Imager's git repository:
5204 http://git.imager.perl.org/imager.git
5208 git clone git://git.imager.perl.org/imager.git
5210 My preference is that patches are provided in the format produced by
5211 C<git format-patch>, for example, if you made your changes in a branch
5212 from master you might do:
5214 git format-patch -k --stdout master >my-patch.txt
5216 and then attach that to your bug report, either by adding it as an
5217 attachment in your email client, or by using the Request Tracker
5218 attachment mechanism.
5222 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5224 Arnar M. Hrafnkelsson is the original author of Imager.
5226 Many others have contributed to Imager, please see the C<README> for a
5231 Imager is licensed under the same terms as perl itself.
5234 makeblendedfont Fontforge
5236 A test font, generated by the Debian packaged Fontforge,
5237 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5238 copyrighted by Adobe. See F<adobe.txt> in the source for license
5243 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5244 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5245 L<Imager::Font>(3), L<Imager::Transformations>(3),
5246 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5247 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5249 L<http://imager.perl.org/>
5251 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5253 Other perl imaging modules include:
5255 L<GD>(3), L<Image::Magick>(3),
5256 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5257 L<Prima::Image>, L<IPA>.
5259 For manipulating image metadata see L<Image::ExifTool>.
5261 If you're trying to use Imager for array processing, you should
5262 probably using L<PDL>.