4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
109 # registered file readers
112 # registered file writers
115 # modules we attempted to autoload
116 my %attempted_to_load;
118 # errors from loading files
119 my %file_load_errors;
121 # what happened when we tried to load
122 my %reader_load_errors;
123 my %writer_load_errors;
125 # library keys that are image file formats
126 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
128 # image pixel combine types
130 qw/none normal multiply dissolve add subtract diff lighten darken
131 hue saturation value color/;
133 @combine_types{@combine_types} = 0 .. $#combine_types;
134 $combine_types{mult} = $combine_types{multiply};
135 $combine_types{'sub'} = $combine_types{subtract};
136 $combine_types{sat} = $combine_types{saturation};
138 # this will be used to store global defaults at some point
143 my $ex_version = eval $Exporter::VERSION;
144 if ($ex_version < 5.57) {
149 XSLoader::load(Imager => $VERSION);
155 png => "Imager::File::PNG",
156 gif => "Imager::File::GIF",
157 tiff => "Imager::File::TIFF",
158 jpeg => "Imager::File::JPEG",
159 w32 => "Imager::Font::W32",
160 ft2 => "Imager::Font::FT2",
161 t1 => "Imager::Font::T1",
164 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
167 for(i_list_formats()) { $formats_low{$_}++; }
169 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
173 # the members of the subhashes under %filters are:
174 # callseq - a list of the parameters to the underlying filter in the
175 # order they are passed
176 # callsub - a code ref that takes a named parameter list and calls the
178 # defaults - a hash of default values
179 # names - defines names for value of given parameters so if the names
180 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
181 # foo parameter, the filter will receive 1 for the foo
184 callseq => ['image','intensity'],
185 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
189 callseq => ['image', 'amount', 'subtype'],
190 defaults => { amount=>3,subtype=>0 },
191 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
194 $filters{hardinvert} ={
195 callseq => ['image'],
197 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
200 $filters{hardinvertall} =
202 callseq => ['image'],
204 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
207 $filters{autolevels_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{xsize} || defined $hsh{ysize}) {
675 unless ($self->img_set(%hsh)) {
676 $Imager::ERRSTR = $self->{ERRSTR};
680 elsif (defined $hsh{file} ||
683 defined $hsh{callback} ||
684 defined $hsh{readcb} ||
685 defined $hsh{data}) {
686 # allow $img = Imager->new(file => $filename)
689 # type is already used as a parameter to new(), rename it for the
691 if ($hsh{filetype}) {
692 $extras{type} = $hsh{filetype};
694 unless ($self->read(%hsh, %extras)) {
695 $Imager::ERRSTR = $self->{ERRSTR};
703 # Copy an entire image with no changes
704 # - if an image has magic the copy of it will not be magical
709 $self->_valid_image("copy")
712 unless (defined wantarray) {
714 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
718 my $newcopy=Imager->new();
719 $newcopy->{IMG} = i_copy($self->{IMG});
728 $self->_valid_image("paste")
731 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
732 my $src = $input{img} || $input{src};
734 $self->_set_error("no source image");
737 unless ($src->_valid_image("paste")) {
738 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
741 $input{left}=0 if $input{left} <= 0;
742 $input{top}=0 if $input{top} <= 0;
744 my($r,$b)=i_img_info($src->{IMG});
745 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
746 my ($src_right, $src_bottom);
747 if ($input{src_coords}) {
748 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
751 if (defined $input{src_maxx}) {
752 $src_right = $input{src_maxx};
754 elsif (defined $input{width}) {
755 if ($input{width} <= 0) {
756 $self->_set_error("paste: width must me positive");
759 $src_right = $src_left + $input{width};
764 if (defined $input{src_maxy}) {
765 $src_bottom = $input{src_maxy};
767 elsif (defined $input{height}) {
768 if ($input{height} < 0) {
769 $self->_set_error("paste: height must be positive");
772 $src_bottom = $src_top + $input{height};
779 $src_right > $r and $src_right = $r;
780 $src_bottom > $b and $src_bottom = $b;
782 if ($src_right <= $src_left
783 || $src_bottom < $src_top) {
784 $self->_set_error("nothing to paste");
788 i_copyto($self->{IMG}, $src->{IMG},
789 $src_left, $src_top, $src_right, $src_bottom,
790 $input{left}, $input{top});
792 return $self; # What should go here??
795 # Crop an image - i.e. return a new image that is smaller
800 $self->_valid_image("crop")
803 unless (defined wantarray) {
805 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
811 my ($w, $h, $l, $r, $b, $t) =
812 @hsh{qw(width height left right bottom top)};
814 # work through the various possibilities
819 elsif (!defined $r) {
820 $r = $self->getwidth;
832 $l = int(0.5+($self->getwidth()-$w)/2);
837 $r = $self->getwidth;
843 elsif (!defined $b) {
844 $b = $self->getheight;
856 $t=int(0.5+($self->getheight()-$h)/2);
861 $b = $self->getheight;
864 ($l,$r)=($r,$l) if $l>$r;
865 ($t,$b)=($b,$t) if $t>$b;
868 $r > $self->getwidth and $r = $self->getwidth;
870 $b > $self->getheight and $b = $self->getheight;
872 if ($l == $r || $t == $b) {
873 $self->_set_error("resulting image would have no content");
876 if( $r < $l or $b < $t ) {
877 $self->_set_error("attempting to crop outside of the image");
880 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
882 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
887 my ($self, %opts) = @_;
892 my $x = $opts{xsize} || $self->getwidth;
893 my $y = $opts{ysize} || $self->getheight;
894 my $channels = $opts{channels} || $self->getchannels;
896 my $out = Imager->new;
897 if ($channels == $self->getchannels) {
898 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
901 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
903 unless ($out->{IMG}) {
904 $self->{ERRSTR} = $self->_error_as_msg;
911 # Sets an image to a certain size and channel number
912 # if there was previously data in the image it is discarded
917 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
919 if (defined($self->{IMG})) {
920 # let IIM_DESTROY destroy it, it's possible this image is
921 # referenced from a virtual image (like masked)
922 #i_img_destroy($self->{IMG});
926 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
927 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
928 $hsh{maxcolors} || 256);
930 elsif ($hsh{bits} eq 'double') {
931 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
933 elsif ($hsh{bits} == 16) {
934 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
937 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
941 unless ($self->{IMG}) {
942 $self->{ERRSTR} = Imager->_error_as_msg();
949 # created a masked version of the current image
953 $self->_valid_image("masked")
956 my %opts = (left => 0,
958 right => $self->getwidth,
959 bottom => $self->getheight,
961 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
963 my $result = Imager->new;
964 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
965 $opts{top}, $opts{right} - $opts{left},
966 $opts{bottom} - $opts{top});
967 unless ($result->{IMG}) {
968 $self->_set_error(Imager->_error_as_msg);
972 # keep references to the mask and base images so they don't
974 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
979 # convert an RGB image into a paletted image
983 if (@_ != 1 && !ref $_[0]) {
990 unless (defined wantarray) {
992 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
996 $self->_valid_image("to_paletted")
999 my $result = Imager->new;
1000 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1001 $self->_set_error(Imager->_error_as_msg);
1009 my ($class, $quant, @images) = @_;
1012 Imager->_set_error("make_palette: supply at least one image");
1016 for my $img (@images) {
1017 unless ($img->{IMG}) {
1018 Imager->_set_error("make_palette: image $index is empty");
1024 return i_img_make_palette($quant, map $_->{IMG}, @images);
1027 # convert a paletted (or any image) to an 8-bit/channel RGB image
1031 unless (defined wantarray) {
1032 my @caller = caller;
1033 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1037 $self->_valid_image("to_rgb8")
1040 my $result = Imager->new;
1041 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1042 $self->_set_error(Imager->_error_as_msg());
1049 # convert a paletted (or any image) to a 16-bit/channel RGB image
1053 unless (defined wantarray) {
1054 my @caller = caller;
1055 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1059 $self->_valid_image("to_rgb16")
1062 my $result = Imager->new;
1063 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1064 $self->_set_error(Imager->_error_as_msg());
1071 # convert a paletted (or any image) to an double/channel RGB image
1075 unless (defined wantarray) {
1076 my @caller = caller;
1077 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1081 $self->_valid_image("to_rgb_double")
1084 my $result = Imager->new;
1085 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1086 $self->_set_error(Imager->_error_as_msg());
1095 my %opts = (colors=>[], @_);
1097 $self->_valid_image("addcolors")
1100 my @colors = @{$opts{colors}}
1103 for my $color (@colors) {
1104 $color = _color($color);
1106 $self->_set_error($Imager::ERRSTR);
1111 return i_addcolors($self->{IMG}, @colors);
1116 my %opts = (start=>0, colors=>[], @_);
1118 $self->_valid_image("setcolors")
1121 my @colors = @{$opts{colors}}
1124 for my $color (@colors) {
1125 $color = _color($color);
1127 $self->_set_error($Imager::ERRSTR);
1132 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1139 $self->_valid_image("getcolors")
1142 if (!exists $opts{start} && !exists $opts{count}) {
1145 $opts{count} = $self->colorcount;
1147 elsif (!exists $opts{count}) {
1150 elsif (!exists $opts{start}) {
1154 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1160 $self->_valid_image("colorcount")
1163 return i_colorcount($self->{IMG});
1169 $self->_valid_image("maxcolors")
1172 i_maxcolors($self->{IMG});
1179 $self->_valid_image("findcolor")
1182 unless ($opts{color}) {
1183 $self->_set_error("findcolor: no color parameter");
1187 my $color = _color($opts{color})
1190 return i_findcolor($self->{IMG}, $color);
1196 $self->_valid_image("bits")
1199 my $bits = i_img_bits($self->{IMG});
1200 if ($bits && $bits == length(pack("d", 1)) * 8) {
1209 $self->_valid_image("type")
1212 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1218 $self->_valid_image("virtual")
1221 return i_img_virtual($self->{IMG});
1227 $self->_valid_image("is_bilevel")
1230 return i_img_is_monochrome($self->{IMG});
1234 my ($self, %opts) = @_;
1236 $self->_valid_image("tags")
1239 if (defined $opts{name}) {
1243 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1244 push @result, (i_tags_get($self->{IMG}, $found))[1];
1247 return wantarray ? @result : $result[0];
1249 elsif (defined $opts{code}) {
1253 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1254 push @result, (i_tags_get($self->{IMG}, $found))[1];
1261 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1264 return i_tags_count($self->{IMG});
1273 $self->_valid_image("addtag")
1277 if (defined $opts{value}) {
1278 if ($opts{value} =~ /^\d+$/) {
1280 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1283 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1286 elsif (defined $opts{data}) {
1287 # force addition as a string
1288 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1291 $self->{ERRSTR} = "No value supplied";
1295 elsif ($opts{code}) {
1296 if (defined $opts{value}) {
1297 if ($opts{value} =~ /^\d+$/) {
1299 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1302 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1305 elsif (defined $opts{data}) {
1306 # force addition as a string
1307 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1310 $self->{ERRSTR} = "No value supplied";
1323 $self->_valid_image("deltag")
1326 if (defined $opts{'index'}) {
1327 return i_tags_delete($self->{IMG}, $opts{'index'});
1329 elsif (defined $opts{name}) {
1330 return i_tags_delbyname($self->{IMG}, $opts{name});
1332 elsif (defined $opts{code}) {
1333 return i_tags_delbycode($self->{IMG}, $opts{code});
1336 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1342 my ($self, %opts) = @_;
1344 $self->_valid_image("settag")
1348 $self->deltag(name=>$opts{name});
1349 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1351 elsif (defined $opts{code}) {
1352 $self->deltag(code=>$opts{code});
1353 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1361 sub _get_reader_io {
1362 my ($self, $input) = @_;
1365 return $input->{io}, undef;
1367 elsif ($input->{fd}) {
1368 return io_new_fd($input->{fd});
1370 elsif ($input->{fh}) {
1371 unless (Scalar::Util::openhandle($input->{fh})) {
1372 $self->_set_error("Handle in fh option not opened");
1375 return Imager::IO->new_fh($input->{fh});
1377 elsif ($input->{file}) {
1378 my $file = IO::File->new($input->{file}, "r");
1380 $self->_set_error("Could not open $input->{file}: $!");
1384 return (io_new_fd(fileno($file)), $file);
1386 elsif ($input->{data}) {
1387 return io_new_buffer($input->{data});
1389 elsif ($input->{callback} || $input->{readcb}) {
1390 if (!$input->{seekcb}) {
1391 $self->_set_error("Need a seekcb parameter");
1393 if ($input->{maxbuffer}) {
1394 return io_new_cb($input->{writecb},
1395 $input->{callback} || $input->{readcb},
1396 $input->{seekcb}, $input->{closecb},
1397 $input->{maxbuffer});
1400 return io_new_cb($input->{writecb},
1401 $input->{callback} || $input->{readcb},
1402 $input->{seekcb}, $input->{closecb});
1406 $self->_set_error("file/fd/fh/data/callback parameter missing");
1411 sub _get_writer_io {
1412 my ($self, $input) = @_;
1414 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1421 elsif ($input->{fd}) {
1422 $io = io_new_fd($input->{fd});
1424 elsif ($input->{fh}) {
1425 unless (Scalar::Util::openhandle($input->{fh})) {
1426 $self->_set_error("Handle in fh option not opened");
1429 $io = Imager::IO->new_fh($input->{fh});
1431 elsif ($input->{file}) {
1432 my $fh = new IO::File($input->{file},"w+");
1434 $self->_set_error("Could not open file $input->{file}: $!");
1437 binmode($fh) or die;
1438 $io = io_new_fd(fileno($fh));
1441 elsif ($input->{data}) {
1442 $io = io_new_bufchain();
1444 elsif ($input->{callback} || $input->{writecb}) {
1445 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1448 $io = io_new_cb($input->{callback} || $input->{writecb},
1450 $input->{seekcb}, $input->{closecb});
1453 $self->_set_error("file/fd/fh/data/callback parameter missing");
1457 unless ($buffered) {
1458 $io->set_buffered(0);
1461 return ($io, @extras);
1464 # Read an image from file
1470 if (defined($self->{IMG})) {
1471 # let IIM_DESTROY do the destruction, since the image may be
1472 # referenced from elsewhere
1473 #i_img_destroy($self->{IMG});
1474 undef($self->{IMG});
1477 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1479 my $type = $input{'type'};
1481 $type = i_test_format_probe($IO, -1);
1484 if ($input{file} && !$type) {
1486 $type = $FORMATGUESS->($input{file});
1490 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1491 $input{file} and $msg .= " or file name";
1492 $self->_set_error($msg);
1496 _reader_autoload($type);
1498 if ($readers{$type} && $readers{$type}{single}) {
1499 return $readers{$type}{single}->($self, $IO, %input);
1502 unless ($formats_low{$type}) {
1503 my $read_types = join ', ', sort Imager->read_types();
1504 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1508 my $allow_incomplete = $input{allow_incomplete};
1509 defined $allow_incomplete or $allow_incomplete = 0;
1511 if ( $type eq 'pnm' ) {
1512 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1513 if ( !defined($self->{IMG}) ) {
1514 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1517 $self->{DEBUG} && print "loading a pnm file\n";
1521 if ( $type eq 'bmp' ) {
1522 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1523 if ( !defined($self->{IMG}) ) {
1524 $self->{ERRSTR}=$self->_error_as_msg();
1527 $self->{DEBUG} && print "loading a bmp file\n";
1530 if ( $type eq 'tga' ) {
1531 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1532 if ( !defined($self->{IMG}) ) {
1533 $self->{ERRSTR}=$self->_error_as_msg();
1536 $self->{DEBUG} && print "loading a tga file\n";
1539 if ( $type eq 'raw' ) {
1540 unless ( $input{xsize} && $input{ysize} ) {
1541 $self->_set_error('missing xsize or ysize parameter for raw');
1545 my $interleave = _first($input{raw_interleave}, $input{interleave});
1546 unless (defined $interleave) {
1547 my @caller = caller;
1548 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1551 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1552 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1554 $self->{IMG} = i_readraw_wiol( $IO,
1560 if ( !defined($self->{IMG}) ) {
1561 $self->{ERRSTR}=$self->_error_as_msg();
1564 $self->{DEBUG} && print "loading a raw file\n";
1570 sub register_reader {
1571 my ($class, %opts) = @_;
1574 or die "register_reader called with no type parameter\n";
1576 my $type = $opts{type};
1578 defined $opts{single} || defined $opts{multiple}
1579 or die "register_reader called with no single or multiple parameter\n";
1581 $readers{$type} = { };
1582 if ($opts{single}) {
1583 $readers{$type}{single} = $opts{single};
1585 if ($opts{multiple}) {
1586 $readers{$type}{multiple} = $opts{multiple};
1592 sub register_writer {
1593 my ($class, %opts) = @_;
1596 or die "register_writer called with no type parameter\n";
1598 my $type = $opts{type};
1600 defined $opts{single} || defined $opts{multiple}
1601 or die "register_writer called with no single or multiple parameter\n";
1603 $writers{$type} = { };
1604 if ($opts{single}) {
1605 $writers{$type}{single} = $opts{single};
1607 if ($opts{multiple}) {
1608 $writers{$type}{multiple} = $opts{multiple};
1619 grep($file_formats{$_}, keys %formats),
1620 qw(ico sgi), # formats not handled directly, but supplied with Imager
1631 grep($file_formats{$_}, keys %formats),
1632 qw(ico sgi), # formats not handled directly, but supplied with Imager
1639 my ($file, $error) = @_;
1641 if ($attempted_to_load{$file}) {
1642 if ($file_load_errors{$file}) {
1643 $$error = $file_load_errors{$file};
1651 local $SIG{__DIE__};
1653 ++$attempted_to_load{$file};
1661 my $work = $@ || "Unknown error";
1663 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1664 $work =~ s/\n/\\n/g;
1665 $work =~ s/\s*\.?\z/ loading $file/;
1666 $file_load_errors{$file} = $work;
1673 # probes for an Imager::File::whatever module
1674 sub _reader_autoload {
1677 return if $formats_low{$type} || $readers{$type};
1679 return unless $type =~ /^\w+$/;
1681 my $file = "Imager/File/\U$type\E.pm";
1684 my $loaded = _load_file($file, \$error);
1685 if (!$loaded && $error =~ /^Can't locate /) {
1686 my $filer = "Imager/File/\U$type\EReader.pm";
1687 $loaded = _load_file($filer, \$error);
1688 if ($error =~ /^Can't locate /) {
1689 $error = "Can't locate $file or $filer";
1693 $reader_load_errors{$type} = $error;
1697 # probes for an Imager::File::whatever module
1698 sub _writer_autoload {
1701 return if $formats_low{$type} || $writers{$type};
1703 return unless $type =~ /^\w+$/;
1705 my $file = "Imager/File/\U$type\E.pm";
1708 my $loaded = _load_file($file, \$error);
1709 if (!$loaded && $error =~ /^Can't locate /) {
1710 my $filew = "Imager/File/\U$type\EWriter.pm";
1711 $loaded = _load_file($filew, \$error);
1712 if ($error =~ /^Can't locate /) {
1713 $error = "Can't locate $file or $filew";
1717 $writer_load_errors{$type} = $error;
1721 sub _fix_gif_positions {
1722 my ($opts, $opt, $msg, @imgs) = @_;
1724 my $positions = $opts->{'gif_positions'};
1726 for my $pos (@$positions) {
1727 my ($x, $y) = @$pos;
1728 my $img = $imgs[$index++];
1729 $img->settag(name=>'gif_left', value=>$x);
1730 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1732 $$msg .= "replaced with the gif_left and gif_top tags";
1737 gif_each_palette=>'gif_local_map',
1738 interlace => 'gif_interlace',
1739 gif_delays => 'gif_delay',
1740 gif_positions => \&_fix_gif_positions,
1741 gif_loop_count => 'gif_loop',
1744 # options that should be converted to colors
1745 my %color_opts = map { $_ => 1 } qw/i_background/;
1748 my ($self, $opts, $prefix, @imgs) = @_;
1750 for my $opt (keys %$opts) {
1752 if ($obsolete_opts{$opt}) {
1753 my $new = $obsolete_opts{$opt};
1754 my $msg = "Obsolete option $opt ";
1756 $new->($opts, $opt, \$msg, @imgs);
1759 $msg .= "replaced with the $new tag ";
1762 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1763 warn $msg if $warn_obsolete && $^W;
1765 next unless $tagname =~ /^\Q$prefix/;
1766 my $value = $opts->{$opt};
1767 if ($color_opts{$opt}) {
1768 $value = _color($value);
1770 $self->_set_error($Imager::ERRSTR);
1775 if (UNIVERSAL::isa($value, "Imager::Color")) {
1776 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1777 for my $img (@imgs) {
1778 $img->settag(name=>$tagname, value=>$tag);
1781 elsif (ref($value) eq 'ARRAY') {
1782 for my $i (0..$#$value) {
1783 my $val = $value->[$i];
1785 if (UNIVERSAL::isa($val, "Imager::Color")) {
1786 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1788 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1791 $self->_set_error("Unknown reference type " . ref($value) .
1792 " supplied in array for $opt");
1798 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1803 $self->_set_error("Unknown reference type " . ref($value) .
1804 " supplied for $opt");
1809 # set it as a tag for every image
1810 for my $img (@imgs) {
1811 $img->settag(name=>$tagname, value=>$value);
1819 # Write an image to file
1822 my %input=(jpegquality=>75,
1832 $self->_valid_image("write")
1835 $self->_set_opts(\%input, "i_", $self)
1838 my $type = $input{'type'};
1839 if (!$type and $input{file}) {
1840 $type = $FORMATGUESS->($input{file});
1843 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1847 _writer_autoload($type);
1850 if ($writers{$type} && $writers{$type}{single}) {
1851 ($IO, $fh) = $self->_get_writer_io(\%input)
1854 $writers{$type}{single}->($self, $IO, %input, type => $type)
1858 if (!$formats_low{$type}) {
1859 my $write_types = join ', ', sort Imager->write_types();
1860 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1864 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1867 if ( $type eq 'pnm' ) {
1868 $self->_set_opts(\%input, "pnm_", $self)
1870 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1871 $self->{ERRSTR} = $self->_error_as_msg();
1874 $self->{DEBUG} && print "writing a pnm file\n";
1876 elsif ( $type eq 'raw' ) {
1877 $self->_set_opts(\%input, "raw_", $self)
1879 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1880 $self->{ERRSTR} = $self->_error_as_msg();
1883 $self->{DEBUG} && print "writing a raw file\n";
1885 elsif ( $type eq 'bmp' ) {
1886 $self->_set_opts(\%input, "bmp_", $self)
1888 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1889 $self->{ERRSTR} = $self->_error_as_msg;
1892 $self->{DEBUG} && print "writing a bmp file\n";
1894 elsif ( $type eq 'tga' ) {
1895 $self->_set_opts(\%input, "tga_", $self)
1898 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1899 $self->{ERRSTR}=$self->_error_as_msg();
1902 $self->{DEBUG} && print "writing a tga file\n";
1906 if (exists $input{'data'}) {
1907 my $data = io_slurp($IO);
1909 $self->{ERRSTR}='Could not slurp from buffer';
1912 ${$input{data}} = $data;
1918 my ($class, $opts, @images) = @_;
1920 my $type = $opts->{type};
1922 if (!$type && $opts->{'file'}) {
1923 $type = $FORMATGUESS->($opts->{'file'});
1926 $class->_set_error('type parameter missing and not possible to guess from extension');
1929 # translate to ImgRaw
1931 for my $img (@images) {
1932 unless ($img->_valid_image("write_multi")) {
1933 $class->_set_error($img->errstr . " (image $index)");
1938 $class->_set_opts($opts, "i_", @images)
1940 my @work = map $_->{IMG}, @images;
1942 _writer_autoload($type);
1945 if ($writers{$type} && $writers{$type}{multiple}) {
1946 ($IO, $file) = $class->_get_writer_io($opts, $type)
1949 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1953 if (!$formats{$type}) {
1954 my $write_types = join ', ', sort Imager->write_types();
1955 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1959 ($IO, $file) = $class->_get_writer_io($opts, $type)
1962 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1966 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1971 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1977 if (exists $opts->{'data'}) {
1978 my $data = io_slurp($IO);
1980 Imager->_set_error('Could not slurp from buffer');
1983 ${$opts->{data}} = $data;
1988 # read multiple images from a file
1990 my ($class, %opts) = @_;
1992 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1995 my $type = $opts{'type'};
1997 $type = i_test_format_probe($IO, -1);
2000 if ($opts{file} && !$type) {
2002 $type = $FORMATGUESS->($opts{file});
2006 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2007 $opts{file} and $msg .= " or file name";
2008 Imager->_set_error($msg);
2012 _reader_autoload($type);
2014 if ($readers{$type} && $readers{$type}{multiple}) {
2015 return $readers{$type}{multiple}->($IO, %opts);
2018 unless ($formats{$type}) {
2019 my $read_types = join ', ', sort Imager->read_types();
2020 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2025 if ($type eq 'pnm') {
2026 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2029 my $img = Imager->new;
2030 if ($img->read(%opts, io => $IO, type => $type)) {
2033 Imager->_set_error($img->errstr);
2038 $ERRSTR = _error_as_msg();
2042 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2046 # Destroy an Imager object
2050 # delete $instances{$self};
2051 if (defined($self->{IMG})) {
2052 # the following is now handled by the XS DESTROY method for
2053 # Imager::ImgRaw object
2054 # Re-enabling this will break virtual images
2055 # tested for in t/t020masked.t
2056 # i_img_destroy($self->{IMG});
2057 undef($self->{IMG});
2059 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2063 # Perform an inplace filter of an image
2064 # that is the image will be overwritten with the data
2071 $self->_valid_image("filter")
2074 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2076 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2077 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2080 if ($filters{$input{'type'}}{names}) {
2081 my $names = $filters{$input{'type'}}{names};
2082 for my $name (keys %$names) {
2083 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2084 $input{$name} = $names->{$name}{$input{$name}};
2088 if (defined($filters{$input{'type'}}{defaults})) {
2089 %hsh=( image => $self->{IMG},
2091 %{$filters{$input{'type'}}{defaults}},
2094 %hsh=( image => $self->{IMG},
2099 my @cs=@{$filters{$input{'type'}}{callseq}};
2102 if (!defined($hsh{$_})) {
2103 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2108 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2109 &{$filters{$input{'type'}}{callsub}}(%hsh);
2112 chomp($self->{ERRSTR} = $@);
2118 $self->{DEBUG} && print "callseq is: @cs\n";
2119 $self->{DEBUG} && print "matching callseq is: @b\n";
2124 sub register_filter {
2126 my %hsh = ( defaults => {}, @_ );
2129 or die "register_filter() with no type\n";
2130 defined $hsh{callsub}
2131 or die "register_filter() with no callsub\n";
2132 defined $hsh{callseq}
2133 or die "register_filter() with no callseq\n";
2135 exists $filters{$hsh{type}}
2138 $filters{$hsh{type}} = \%hsh;
2143 sub scale_calculate {
2146 my %opts = ('type'=>'max', @_);
2148 # none of these should be references
2149 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2150 if (defined $opts{$name} && ref $opts{$name}) {
2151 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2156 my ($x_scale, $y_scale);
2157 my $width = $opts{width};
2158 my $height = $opts{height};
2160 defined $width or $width = $self->getwidth;
2161 defined $height or $height = $self->getheight;
2164 unless (defined $width && defined $height) {
2165 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2170 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2171 $x_scale = $opts{'xscalefactor'};
2172 $y_scale = $opts{'yscalefactor'};
2174 elsif ($opts{'xscalefactor'}) {
2175 $x_scale = $opts{'xscalefactor'};
2176 $y_scale = $opts{'scalefactor'} || $x_scale;
2178 elsif ($opts{'yscalefactor'}) {
2179 $y_scale = $opts{'yscalefactor'};
2180 $x_scale = $opts{'scalefactor'} || $y_scale;
2183 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2186 # work out the scaling
2187 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2188 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2189 $opts{ypixels} / $height );
2190 if ($opts{'type'} eq 'min') {
2191 $x_scale = $y_scale = _min($xpix,$ypix);
2193 elsif ($opts{'type'} eq 'max') {
2194 $x_scale = $y_scale = _max($xpix,$ypix);
2196 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2201 $self->_set_error('invalid value for type parameter');
2204 } elsif ($opts{xpixels}) {
2205 $x_scale = $y_scale = $opts{xpixels} / $width;
2207 elsif ($opts{ypixels}) {
2208 $x_scale = $y_scale = $opts{ypixels}/$height;
2210 elsif ($opts{constrain} && ref $opts{constrain}
2211 && $opts{constrain}->can('constrain')) {
2212 # we've been passed an Image::Math::Constrain object or something
2213 # that looks like one
2215 (undef, undef, $scalefactor)
2216 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2217 unless ($scalefactor) {
2218 $self->_set_error('constrain method failed on constrain parameter');
2221 $x_scale = $y_scale = $scalefactor;
2224 my $new_width = int($x_scale * $width + 0.5);
2225 $new_width > 0 or $new_width = 1;
2226 my $new_height = int($y_scale * $height + 0.5);
2227 $new_height > 0 or $new_height = 1;
2229 return ($x_scale, $y_scale, $new_width, $new_height);
2233 # Scale an image to requested size and return the scaled version
2237 my %opts = (qtype=>'normal' ,@_);
2238 my $img = Imager->new();
2239 my $tmp = Imager->new();
2241 unless (defined wantarray) {
2242 my @caller = caller;
2243 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2247 $self->_valid_image("scale")
2250 my ($x_scale, $y_scale, $new_width, $new_height) =
2251 $self->scale_calculate(%opts)
2254 if ($opts{qtype} eq 'normal') {
2255 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2256 if ( !defined($tmp->{IMG}) ) {
2257 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2260 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2261 if ( !defined($img->{IMG}) ) {
2262 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2268 elsif ($opts{'qtype'} eq 'preview') {
2269 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2270 if ( !defined($img->{IMG}) ) {
2271 $self->{ERRSTR}='unable to scale image';
2276 elsif ($opts{'qtype'} eq 'mixing') {
2277 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2278 unless ($img->{IMG}) {
2279 $self->_set_error(Imager->_error_as_msg);
2285 $self->_set_error('invalid value for qtype parameter');
2290 # Scales only along the X axis
2294 my %opts = ( scalefactor=>0.5, @_ );
2296 unless (defined wantarray) {
2297 my @caller = caller;
2298 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2302 $self->_valid_image("scaleX")
2305 my $img = Imager->new();
2307 my $scalefactor = $opts{scalefactor};
2309 if ($opts{pixels}) {
2310 $scalefactor = $opts{pixels} / $self->getwidth();
2313 unless ($self->{IMG}) {
2314 $self->{ERRSTR}='empty input image';
2318 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2320 if ( !defined($img->{IMG}) ) {
2321 $self->{ERRSTR} = 'unable to scale image';
2328 # Scales only along the Y axis
2332 my %opts = ( scalefactor => 0.5, @_ );
2334 unless (defined wantarray) {
2335 my @caller = caller;
2336 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2340 $self->_valid_image("scaleY")
2343 my $img = Imager->new();
2345 my $scalefactor = $opts{scalefactor};
2347 if ($opts{pixels}) {
2348 $scalefactor = $opts{pixels} / $self->getheight();
2351 unless ($self->{IMG}) {
2352 $self->{ERRSTR} = 'empty input image';
2355 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2357 if ( !defined($img->{IMG}) ) {
2358 $self->{ERRSTR} = 'unable to scale image';
2365 # Transform returns a spatial transformation of the input image
2366 # this moves pixels to a new location in the returned image.
2367 # NOTE - should make a utility function to check transforms for
2373 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2375 # print Dumper(\%opts);
2378 $self->_valid_image("transform")
2381 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2383 eval ("use Affix::Infix2Postfix;");
2386 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2389 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2390 {op=>'-',trans=>'Sub'},
2391 {op=>'*',trans=>'Mult'},
2392 {op=>'/',trans=>'Div'},
2393 {op=>'-','type'=>'unary',trans=>'u-'},
2395 {op=>'func','type'=>'unary'}],
2396 'grouping'=>[qw( \( \) )],
2397 'func'=>[qw( sin cos )],
2402 @xt=$I2P->translate($opts{'xexpr'});
2403 @yt=$I2P->translate($opts{'yexpr'});
2405 $numre=$I2P->{'numre'};
2408 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2409 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2410 @{$opts{'parm'}}=@pt;
2413 # print Dumper(\%opts);
2415 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2416 $self->{ERRSTR}='transform: no xopcodes given.';
2420 @op=@{$opts{'xopcodes'}};
2422 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2423 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2426 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2432 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2433 $self->{ERRSTR}='transform: no yopcodes given.';
2437 @op=@{$opts{'yopcodes'}};
2439 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2440 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2443 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2448 if ( !exists $opts{'parm'}) {
2449 $self->{ERRSTR}='transform: no parameter arg given.';
2453 # print Dumper(\@ropx);
2454 # print Dumper(\@ropy);
2455 # print Dumper(\@ropy);
2457 my $img = Imager->new();
2458 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2459 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2465 my ($opts, @imgs) = @_;
2467 require "Imager/Expr.pm";
2469 $opts->{variables} = [ qw(x y) ];
2470 my ($width, $height) = @{$opts}{qw(width height)};
2473 for my $img (@imgs) {
2474 unless ($img->_valid_image("transform2")) {
2475 Imager->_set_error($img->errstr . " (input image $index)");
2481 $width ||= $imgs[0]->getwidth();
2482 $height ||= $imgs[0]->getheight();
2484 for my $img (@imgs) {
2485 $opts->{constants}{"w$img_num"} = $img->getwidth();
2486 $opts->{constants}{"h$img_num"} = $img->getheight();
2487 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2488 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2493 $opts->{constants}{w} = $width;
2494 $opts->{constants}{cx} = $width/2;
2497 $Imager::ERRSTR = "No width supplied";
2501 $opts->{constants}{h} = $height;
2502 $opts->{constants}{cy} = $height/2;
2505 $Imager::ERRSTR = "No height supplied";
2508 my $code = Imager::Expr->new($opts);
2510 $Imager::ERRSTR = Imager::Expr::error();
2513 my $channels = $opts->{channels} || 3;
2514 unless ($channels >= 1 && $channels <= 4) {
2515 return Imager->_set_error("channels must be an integer between 1 and 4");
2518 my $img = Imager->new();
2519 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2520 $channels, $code->code(),
2521 $code->nregs(), $code->cregs(),
2522 [ map { $_->{IMG} } @imgs ]);
2523 if (!defined $img->{IMG}) {
2524 $Imager::ERRSTR = Imager->_error_as_msg();
2535 $self->_valid_image("rubthrough")
2538 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2539 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2543 %opts = (src_minx => 0,
2545 src_maxx => $opts{src}->getwidth(),
2546 src_maxy => $opts{src}->getheight(),
2550 defined $tx or $tx = $opts{left};
2551 defined $tx or $tx = 0;
2554 defined $ty or $ty = $opts{top};
2555 defined $ty or $ty = 0;
2557 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2558 $opts{src_minx}, $opts{src_miny},
2559 $opts{src_maxx}, $opts{src_maxy})) {
2560 $self->_set_error($self->_error_as_msg());
2577 $self->_valid_image("compose")
2580 unless ($opts{src}) {
2581 $self->_set_error("compose: src parameter missing");
2585 unless ($opts{src}->_valid_image("compose")) {
2586 $self->_set_error($opts{src}->errstr . " (for src)");
2589 my $src = $opts{src};
2591 my $left = $opts{left};
2592 defined $left or $left = $opts{tx};
2593 defined $left or $left = 0;
2595 my $top = $opts{top};
2596 defined $top or $top = $opts{ty};
2597 defined $top or $top = 0;
2599 my $src_left = $opts{src_left};
2600 defined $src_left or $src_left = $opts{src_minx};
2601 defined $src_left or $src_left = 0;
2603 my $src_top = $opts{src_top};
2604 defined $src_top or $src_top = $opts{src_miny};
2605 defined $src_top or $src_top = 0;
2607 my $width = $opts{width};
2608 if (!defined $width && defined $opts{src_maxx}) {
2609 $width = $opts{src_maxx} - $src_left;
2611 defined $width or $width = $src->getwidth() - $src_left;
2613 my $height = $opts{height};
2614 if (!defined $height && defined $opts{src_maxy}) {
2615 $height = $opts{src_maxy} - $src_top;
2617 defined $height or $height = $src->getheight() - $src_top;
2619 my $combine = $self->_combine($opts{combine}, 'normal');
2622 unless ($opts{mask}->_valid_image("compose")) {
2623 $self->_set_error($opts{mask}->errstr . " (for mask)");
2627 my $mask_left = $opts{mask_left};
2628 defined $mask_left or $mask_left = $opts{mask_minx};
2629 defined $mask_left or $mask_left = 0;
2631 my $mask_top = $opts{mask_top};
2632 defined $mask_top or $mask_top = $opts{mask_miny};
2633 defined $mask_top or $mask_top = 0;
2635 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2636 $left, $top, $src_left, $src_top,
2637 $mask_left, $mask_top, $width, $height,
2638 $combine, $opts{opacity})) {
2639 $self->_set_error(Imager->_error_as_msg);
2644 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2645 $width, $height, $combine, $opts{opacity})) {
2646 $self->_set_error(Imager->_error_as_msg);
2658 $self->_valid_image("flip")
2661 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2663 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2664 $dir = $xlate{$opts{'dir'}};
2665 return $self if i_flipxy($self->{IMG}, $dir);
2673 unless (defined wantarray) {
2674 my @caller = caller;
2675 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2679 $self->_valid_image("rotate")
2682 if (defined $opts{right}) {
2683 my $degrees = $opts{right};
2685 $degrees += 360 * int(((-$degrees)+360)/360);
2687 $degrees = $degrees % 360;
2688 if ($degrees == 0) {
2689 return $self->copy();
2691 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2692 my $result = Imager->new();
2693 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2697 $self->{ERRSTR} = $self->_error_as_msg();
2702 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2706 elsif (defined $opts{radians} || defined $opts{degrees}) {
2707 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2709 my $back = $opts{back};
2710 my $result = Imager->new;
2712 $back = _color($back);
2714 $self->_set_error(Imager->errstr);
2718 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2721 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2723 if ($result->{IMG}) {
2727 $self->{ERRSTR} = $self->_error_as_msg();
2732 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2737 sub matrix_transform {
2741 $self->_valid_image("matrix_transform")
2744 unless (defined wantarray) {
2745 my @caller = caller;
2746 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2750 if ($opts{matrix}) {
2751 my $xsize = $opts{xsize} || $self->getwidth;
2752 my $ysize = $opts{ysize} || $self->getheight;
2754 my $result = Imager->new;
2756 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2757 $opts{matrix}, $opts{back})
2761 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2769 $self->{ERRSTR} = "matrix parameter required";
2775 *yatf = \&matrix_transform;
2777 # These two are supported for legacy code only
2780 return Imager::Color->new(@_);
2784 return Imager::Color::set(@_);
2787 # Draws a box between the specified corner points.
2790 my $raw = $self->{IMG};
2792 $self->_valid_image("box")
2797 my ($xmin, $ymin, $xmax, $ymax);
2798 if (exists $opts{'box'}) {
2799 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2800 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2801 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2802 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2805 defined($xmin = $opts{xmin}) or $xmin = 0;
2806 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2807 defined($ymin = $opts{ymin}) or $ymin = 0;
2808 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2811 if ($opts{filled}) {
2812 my $color = $opts{'color'};
2814 if (defined $color) {
2815 unless (_is_color_object($color)) {
2816 $color = _color($color);
2818 $self->{ERRSTR} = $Imager::ERRSTR;
2824 $color = i_color_new(255,255,255,255);
2827 if ($color->isa("Imager::Color")) {
2828 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2831 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2834 elsif ($opts{fill}) {
2835 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2836 # assume it's a hash ref
2837 require 'Imager/Fill.pm';
2838 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2839 $self->{ERRSTR} = $Imager::ERRSTR;
2843 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2846 my $color = $opts{'color'};
2847 if (defined $color) {
2848 unless (_is_color_object($color)) {
2849 $color = _color($color);
2851 $self->{ERRSTR} = $Imager::ERRSTR;
2857 $color = i_color_new(255, 255, 255, 255);
2860 $self->{ERRSTR} = $Imager::ERRSTR;
2863 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2872 $self->_valid_image("arc")
2875 my $dflcl= [ 255, 255, 255, 255];
2880 'r'=>_min($self->getwidth(),$self->getheight())/3,
2881 'x'=>$self->getwidth()/2,
2882 'y'=>$self->getheight()/2,
2889 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2890 # assume it's a hash ref
2891 require 'Imager/Fill.pm';
2892 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2893 $self->{ERRSTR} = $Imager::ERRSTR;
2897 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2898 $opts{'d2'}, $opts{fill}{fill});
2900 elsif ($opts{filled}) {
2901 my $color = _color($opts{'color'});
2903 $self->{ERRSTR} = $Imager::ERRSTR;
2906 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2907 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2911 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2912 $opts{'d1'}, $opts{'d2'}, $color);
2916 my $color = _color($opts{'color'});
2917 if ($opts{d2} - $opts{d1} >= 360) {
2918 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2921 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2927 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2928 # assume it's a hash ref
2929 require 'Imager/Fill.pm';
2930 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2931 $self->{ERRSTR} = $Imager::ERRSTR;
2935 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2936 $opts{'d2'}, $opts{fill}{fill});
2939 my $color = _color($opts{'color'});
2941 $self->{ERRSTR} = $Imager::ERRSTR;
2944 if ($opts{filled}) {
2945 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2946 $opts{'d1'}, $opts{'d2'}, $color);
2949 if ($opts{d1} == 0 && $opts{d2} == 361) {
2950 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2953 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2959 $self->_set_error($self->_error_as_msg);
2966 # Draws a line from one point to the other
2967 # the endpoint is set if the endp parameter is set which it is by default.
2968 # to turn of the endpoint being set use endp=>0 when calling line.
2972 my $dflcl=i_color_new(0,0,0,0);
2973 my %opts=(color=>$dflcl,
2977 $self->_valid_image("line")
2980 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2981 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2983 my $color = _color($opts{'color'});
2985 $self->{ERRSTR} = $Imager::ERRSTR;
2989 $opts{antialias} = $opts{aa} if defined $opts{aa};
2990 if ($opts{antialias}) {
2991 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2992 $color, $opts{endp});
2994 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2995 $color, $opts{endp});
3000 # Draws a line between an ordered set of points - It more or less just transforms this
3001 # into a list of lines.
3005 my ($pt,$ls,@points);
3006 my $dflcl=i_color_new(0,0,0,0);
3007 my %opts=(color=>$dflcl,@_);
3009 $self->_valid_image("polyline")
3012 if (exists($opts{points})) { @points=@{$opts{points}}; }
3013 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3014 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3017 # print Dumper(\@points);
3019 my $color = _color($opts{'color'});
3021 $self->{ERRSTR} = $Imager::ERRSTR;
3024 $opts{antialias} = $opts{aa} if defined $opts{aa};
3025 if ($opts{antialias}) {
3028 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3035 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3045 my ($pt,$ls,@points);
3046 my $dflcl = i_color_new(0,0,0,0);
3047 my %opts = (color=>$dflcl, @_);
3049 $self->_valid_image("polygon")
3052 if (exists($opts{points})) {
3053 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3054 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3057 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3058 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3061 if ($opts{'fill'}) {
3062 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3063 # assume it's a hash ref
3064 require 'Imager/Fill.pm';
3065 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3066 $self->{ERRSTR} = $Imager::ERRSTR;
3070 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
3071 $opts{'fill'}{'fill'});
3074 my $color = _color($opts{'color'});
3076 $self->{ERRSTR} = $Imager::ERRSTR;
3079 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3086 # this the multipoint bezier curve
3087 # this is here more for testing that actual usage since
3088 # this is not a good algorithm. Usually the curve would be
3089 # broken into smaller segments and each done individually.
3093 my ($pt,$ls,@points);
3094 my $dflcl=i_color_new(0,0,0,0);
3095 my %opts=(color=>$dflcl,@_);
3097 $self->_valid_image("polybezier")
3100 if (exists $opts{points}) {
3101 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3102 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3105 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3106 $self->{ERRSTR}='Missing or invalid points.';
3110 my $color = _color($opts{'color'});
3112 $self->{ERRSTR} = $Imager::ERRSTR;
3115 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3121 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3124 $self->_valid_image("flood_fill")
3127 unless (exists $opts{'x'} && exists $opts{'y'}) {
3128 $self->{ERRSTR} = "missing seed x and y parameters";
3132 if ($opts{border}) {
3133 my $border = _color($opts{border});
3135 $self->_set_error($Imager::ERRSTR);
3139 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3140 # assume it's a hash ref
3141 require Imager::Fill;
3142 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3143 $self->{ERRSTR} = $Imager::ERRSTR;
3147 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3148 $opts{fill}{fill}, $border);
3151 my $color = _color($opts{'color'});
3153 $self->{ERRSTR} = $Imager::ERRSTR;
3156 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3163 $self->{ERRSTR} = $self->_error_as_msg();
3169 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3170 # assume it's a hash ref
3171 require 'Imager/Fill.pm';
3172 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3173 $self->{ERRSTR} = $Imager::ERRSTR;
3177 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3180 my $color = _color($opts{'color'});
3182 $self->{ERRSTR} = $Imager::ERRSTR;
3185 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3191 $self->{ERRSTR} = $self->_error_as_msg();
3198 my ($self, %opts) = @_;
3200 $self->_valid_image("setpixel")
3203 my $color = $opts{color};
3204 unless (defined $color) {
3205 $color = $self->{fg};
3206 defined $color or $color = NC(255, 255, 255);
3209 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3210 unless ($color = _color($color, 'setpixel')) {
3211 $self->_set_error("setpixel: " . Imager->errstr);
3216 unless (exists $opts{'x'} && exists $opts{'y'}) {
3217 $self->_set_error('setpixel: missing x or y parameter');
3223 if (ref $x || ref $y) {
3224 $x = ref $x ? $x : [ $x ];
3225 $y = ref $y ? $y : [ $y ];
3227 $self->_set_error("setpixel: x is a reference to an empty array");
3231 $self->_set_error("setpixel: y is a reference to an empty array");
3235 # make both the same length, replicating the last element
3237 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3240 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3244 if ($color->isa('Imager::Color')) {
3245 for my $i (0..$#$x) {
3246 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3251 for my $i (0..$#$x) {
3252 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3260 if ($color->isa('Imager::Color')) {
3261 i_ppix($self->{IMG}, $x, $y, $color)
3262 and return "0 but true";
3265 i_ppixf($self->{IMG}, $x, $y, $color)
3266 and return "0 but true";
3276 my %opts = ( "type"=>'8bit', @_);
3278 $self->_valid_image("getpixel")
3281 unless (exists $opts{'x'} && exists $opts{'y'}) {
3282 $self->_set_error('getpixel: missing x or y parameter');
3288 my $type = $opts{'type'};
3289 if (ref $x || ref $y) {
3290 $x = ref $x ? $x : [ $x ];
3291 $y = ref $y ? $y : [ $y ];
3293 $self->_set_error("getpixel: x is a reference to an empty array");
3297 $self->_set_error("getpixel: y is a reference to an empty array");
3301 # make both the same length, replicating the last element
3303 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3306 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3310 if ($type eq '8bit') {
3311 for my $i (0..$#$x) {
3312 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3315 elsif ($type eq 'float' || $type eq 'double') {
3316 for my $i (0..$#$x) {
3317 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3321 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3324 return wantarray ? @result : \@result;
3327 if ($type eq '8bit') {
3328 return i_get_pixel($self->{IMG}, $x, $y);
3330 elsif ($type eq 'float' || $type eq 'double') {
3331 return i_gpixf($self->{IMG}, $x, $y);
3334 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3342 my %opts = ( type => '8bit', x=>0, @_);
3344 $self->_valid_image("getscanline")
3347 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3349 unless (defined $opts{'y'}) {
3350 $self->_set_error("missing y parameter");
3354 if ($opts{type} eq '8bit') {
3355 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3358 elsif ($opts{type} eq 'float') {
3359 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3362 elsif ($opts{type} eq 'index') {
3363 unless (i_img_type($self->{IMG})) {
3364 $self->_set_error("type => index only valid on paletted images");
3367 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3371 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3378 my %opts = ( x=>0, @_);
3380 $self->_valid_image("setscanline")
3383 unless (defined $opts{'y'}) {
3384 $self->_set_error("missing y parameter");
3389 if (ref $opts{pixels} && @{$opts{pixels}}) {
3390 # try to guess the type
3391 if ($opts{pixels}[0]->isa('Imager::Color')) {
3392 $opts{type} = '8bit';
3394 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3395 $opts{type} = 'float';
3398 $self->_set_error("missing type parameter and could not guess from pixels");
3404 $opts{type} = '8bit';
3408 if ($opts{type} eq '8bit') {
3409 if (ref $opts{pixels}) {
3410 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3413 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3416 elsif ($opts{type} eq 'float') {
3417 if (ref $opts{pixels}) {
3418 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3421 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3424 elsif ($opts{type} eq 'index') {
3425 if (ref $opts{pixels}) {
3426 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3429 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3433 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3440 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3442 $self->_valid_image("getsamples")
3445 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3447 unless (defined $opts{'y'}) {
3448 $self->_set_error("missing y parameter");
3452 if ($opts{target}) {
3453 my $target = $opts{target};
3454 my $offset = $opts{offset};
3455 if ($opts{type} eq '8bit') {
3456 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3457 $opts{y}, $opts{channels})
3459 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3460 return scalar(@samples);
3462 elsif ($opts{type} eq 'float') {
3463 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3464 $opts{y}, $opts{channels});
3465 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3466 return scalar(@samples);
3468 elsif ($opts{type} =~ /^(\d+)bit$/) {
3472 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3473 $opts{y}, $bits, $target,
3474 $offset, $opts{channels});
3475 unless (defined $count) {
3476 $self->_set_error(Imager->_error_as_msg);
3483 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3488 if ($opts{type} eq '8bit') {
3489 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3490 $opts{y}, $opts{channels});
3492 elsif ($opts{type} eq 'float') {
3493 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3494 $opts{y}, $opts{channels});
3496 elsif ($opts{type} =~ /^(\d+)bit$/) {
3500 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3501 $opts{y}, $bits, \@data, 0, $opts{channels})
3506 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3515 $self->_valid_image("setsamples")
3518 my %opts = ( x => 0, offset => 0 );
3520 # avoid duplicating the data parameter, it may be a large scalar
3522 while ($i < @_ -1) {
3523 if ($_[$i] eq 'data') {
3527 $opts{$_[$i]} = $_[$i+1];
3533 unless(defined $data_index) {
3534 $self->_set_error('setsamples: data parameter missing');
3537 unless (defined $_[$data_index]) {
3538 $self->_set_error('setsamples: data parameter not defined');
3542 my $type = $opts{type};
3543 defined $type or $type = '8bit';
3545 my $width = defined $opts{width} ? $opts{width}
3546 : $self->getwidth() - $opts{x};
3549 if ($type eq '8bit') {
3550 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3551 $_[$data_index], $opts{offset}, $width);
3553 elsif ($type eq 'float') {
3554 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3555 $_[$data_index], $opts{offset}, $width);
3557 elsif ($type =~ /^([0-9]+)bit$/) {
3560 unless (ref $_[$data_index]) {
3561 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3565 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3566 $opts{channels}, $_[$data_index], $opts{offset},
3570 $self->_set_error('setsamples: type parameter invalid');
3574 unless (defined $count) {
3575 $self->_set_error(Imager->_error_as_msg);
3582 # make an identity matrix of the given size
3586 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3587 for my $c (0 .. ($size-1)) {
3588 $matrix->[$c][$c] = 1;
3593 # general function to convert an image
3595 my ($self, %opts) = @_;
3598 $self->_valid_image("convert")
3601 unless (defined wantarray) {
3602 my @caller = caller;
3603 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3607 # the user can either specify a matrix or preset
3608 # the matrix overrides the preset
3609 if (!exists($opts{matrix})) {
3610 unless (exists($opts{preset})) {
3611 $self->{ERRSTR} = "convert() needs a matrix or preset";
3615 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3616 # convert to greyscale, keeping the alpha channel if any
3617 if ($self->getchannels == 3) {
3618 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3620 elsif ($self->getchannels == 4) {
3621 # preserve the alpha channel
3622 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3627 $matrix = _identity($self->getchannels);
3630 elsif ($opts{preset} eq 'noalpha') {
3631 # strip the alpha channel
3632 if ($self->getchannels == 2 or $self->getchannels == 4) {
3633 $matrix = _identity($self->getchannels);
3634 pop(@$matrix); # lose the alpha entry
3637 $matrix = _identity($self->getchannels);
3640 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3642 $matrix = [ [ 1 ] ];
3644 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3645 $matrix = [ [ 0, 1 ] ];
3647 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3648 $matrix = [ [ 0, 0, 1 ] ];
3650 elsif ($opts{preset} eq 'alpha') {
3651 if ($self->getchannels == 2 or $self->getchannels == 4) {
3652 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3655 # the alpha is just 1 <shrug>
3656 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3659 elsif ($opts{preset} eq 'rgb') {
3660 if ($self->getchannels == 1) {
3661 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3663 elsif ($self->getchannels == 2) {
3664 # preserve the alpha channel
3665 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3668 $matrix = _identity($self->getchannels);
3671 elsif ($opts{preset} eq 'addalpha') {
3672 if ($self->getchannels == 1) {
3673 $matrix = _identity(2);
3675 elsif ($self->getchannels == 3) {
3676 $matrix = _identity(4);
3679 $matrix = _identity($self->getchannels);
3683 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3689 $matrix = $opts{matrix};
3692 my $new = Imager->new;
3693 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3694 unless ($new->{IMG}) {
3695 # most likely a bad matrix
3696 i_push_error(0, "convert");
3697 $self->{ERRSTR} = _error_as_msg();
3703 # combine channels from multiple input images, a class method
3705 my ($class, %opts) = @_;
3707 my $src = delete $opts{src};
3709 $class->_set_error("src parameter missing");
3714 for my $img (@$src) {
3715 unless (eval { $img->isa("Imager") }) {
3716 $class->_set_error("src must contain image objects");
3719 unless ($img->_valid_image("combine")) {
3720 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3723 push @imgs, $img->{IMG};
3726 if (my $channels = delete $opts{channels}) {
3727 $result = i_combine(\@imgs, $channels);
3730 $result = i_combine(\@imgs);
3733 $class->_set_error($class->_error_as_msg);
3737 my $img = $class->new;
3738 $img->{IMG} = $result;
3744 # general function to map an image through lookup tables
3747 my ($self, %opts) = @_;
3748 my @chlist = qw( red green blue alpha );
3750 $self->_valid_image("map")
3753 if (!exists($opts{'maps'})) {
3754 # make maps from channel maps
3756 for $chnum (0..$#chlist) {
3757 if (exists $opts{$chlist[$chnum]}) {
3758 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3759 } elsif (exists $opts{'all'}) {
3760 $opts{'maps'}[$chnum] = $opts{'all'};
3764 if ($opts{'maps'} and $self->{IMG}) {
3765 i_map($self->{IMG}, $opts{'maps'} );
3771 my ($self, %opts) = @_;
3773 $self->_valid_image("difference")
3776 defined $opts{mindist} or $opts{mindist} = 0;
3778 defined $opts{other}
3779 or return $self->_set_error("No 'other' parameter supplied");
3780 unless ($opts{other}->_valid_image("difference")) {
3781 $self->_set_error($opts{other}->errstr . " (other image)");
3785 my $result = Imager->new;
3786 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3788 or return $self->_set_error($self->_error_as_msg());
3793 # destructive border - image is shrunk by one pixel all around
3796 my ($self,%opts)=@_;
3797 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3798 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3802 # Get the width of an image
3807 $self->_valid_image("getwidth")
3810 return i_img_get_width($self->{IMG});
3813 # Get the height of an image
3818 $self->_valid_image("getheight")
3821 return i_img_get_height($self->{IMG});
3824 # Get number of channels in an image
3829 $self->_valid_image("getchannels")
3832 return i_img_getchannels($self->{IMG});
3840 $self->_valid_image("getmask")
3843 return i_img_getmask($self->{IMG});
3852 $self->_valid_image("setmask")
3855 unless (defined $opts{mask}) {
3856 $self->_set_error("mask parameter required");
3860 i_img_setmask( $self->{IMG} , $opts{mask} );
3865 # Get number of colors in an image
3869 my %opts=('maxcolors'=>2**30,@_);
3871 $self->_valid_image("getcolorcount")
3874 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3875 return ($rc==-1? undef : $rc);
3878 # Returns a reference to a hash. The keys are colour named (packed) and the
3879 # values are the number of pixels in this colour.
3880 sub getcolorusagehash {
3883 $self->_valid_image("getcolorusagehash")
3886 my %opts = ( maxcolors => 2**30, @_ );
3887 my $max_colors = $opts{maxcolors};
3888 unless (defined $max_colors && $max_colors > 0) {
3889 $self->_set_error('maxcolors must be a positive integer');
3893 my $channels= $self->getchannels;
3894 # We don't want to look at the alpha channel, because some gifs using it
3895 # doesn't define it for every colour (but only for some)
3896 $channels -= 1 if $channels == 2 or $channels == 4;
3898 my $height = $self->getheight;
3899 for my $y (0 .. $height - 1) {
3900 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3901 while (length $colors) {
3902 $color_use{ substr($colors, 0, $channels, '') }++;
3904 keys %color_use > $max_colors
3910 # This will return a ordered array of the colour usage. Kind of the sorted
3911 # version of the values of the hash returned by getcolorusagehash.
3912 # You might want to add safety checks and change the names, etc...
3916 $self->_valid_image("getcolorusage")
3919 my %opts = ( maxcolors => 2**30, @_ );
3920 my $max_colors = $opts{maxcolors};
3921 unless (defined $max_colors && $max_colors > 0) {
3922 $self->_set_error('maxcolors must be a positive integer');
3926 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3929 # draw string to an image
3934 $self->_valid_image("string")
3937 my %input=('x'=>0, 'y'=>0, @_);
3938 defined($input{string}) or $input{string} = $input{text};
3940 unless(defined $input{string}) {
3941 $self->{ERRSTR}="missing required parameter 'string'";
3945 unless($input{font}) {
3946 $self->{ERRSTR}="missing required parameter 'font'";
3950 unless ($input{font}->draw(image=>$self, %input)) {
3962 $self->_valid_image("align_string")
3971 my %input=('x'=>0, 'y'=>0, @_);
3972 defined $input{string}
3973 or $input{string} = $input{text};
3975 unless(exists $input{string}) {
3976 $self->_set_error("missing required parameter 'string'");
3980 unless($input{font}) {
3981 $self->_set_error("missing required parameter 'font'");
3986 unless (@result = $input{font}->align(image=>$img, %input)) {
3990 return wantarray ? @result : $result[0];
3993 my @file_limit_names = qw/width height bytes/;
3995 sub set_file_limits {
4002 @values{@file_limit_names} = (0) x @file_limit_names;
4005 @values{@file_limit_names} = i_get_image_file_limits();
4008 for my $key (keys %values) {
4009 defined $opts{$key} and $values{$key} = $opts{$key};
4012 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4015 sub get_file_limits {
4016 i_get_image_file_limits();
4019 my @check_args = qw(width height channels sample_size);
4021 sub check_file_limits {
4031 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4032 $opts{sample_size} = length(pack("d", 0));
4035 for my $name (@check_args) {
4036 unless (defined $opts{$name}) {
4037 $class->_set_error("check_file_limits: $name must be defined");
4040 unless ($opts{$name} == int($opts{$name})) {
4041 $class->_set_error("check_file_limits: $name must be a positive integer");
4046 my $result = i_int_check_image_file_limits(@opts{@check_args});
4048 $class->_set_error($class->_error_as_msg());
4054 # Shortcuts that can be exported
4056 sub newcolor { Imager::Color->new(@_); }
4057 sub newfont { Imager::Font->new(@_); }
4059 require Imager::Color::Float;
4060 return Imager::Color::Float->new(@_);
4063 *NC=*newcolour=*newcolor;
4070 #### Utility routines
4073 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4077 my ($self, $msg) = @_;
4080 $self->{ERRSTR} = $msg;
4088 # Default guess for the type of an image from extension
4090 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4094 ( map { $_ => $_ } @simple_types ),
4100 pnm => "pnm", # technically wrong, but historically it works in Imager
4113 sub def_guess_type {
4116 my ($ext) = $name =~ /\.([^.]+)$/
4119 my $type = $ext_types{$ext}
4126 return @combine_types;
4129 # get the minimum of a list
4133 for(@_) { if ($_<$mx) { $mx=$_; }}
4137 # get the maximum of a list
4141 for(@_) { if ($_>$mx) { $mx=$_; }}
4145 # string stuff for iptc headers
4149 $str = substr($str,3);
4150 $str =~ s/[\n\r]//g;
4157 # A little hack to parse iptc headers.
4162 my($caption,$photogr,$headln,$credit);
4164 my $str=$self->{IPTCRAW};
4169 @ar=split(/8BIM/,$str);
4174 @sar=split(/\034\002/);
4175 foreach $item (@sar) {
4176 if ($item =~ m/^x/) {
4177 $caption = _clean($item);
4180 if ($item =~ m/^P/) {
4181 $photogr = _clean($item);
4184 if ($item =~ m/^i/) {
4185 $headln = _clean($item);
4188 if ($item =~ m/^n/) {
4189 $credit = _clean($item);
4195 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4202 or die "Only C language supported";
4204 require Imager::ExtUtils;
4205 return Imager::ExtUtils->inline_config;
4208 # threads shouldn't try to close raw Imager objects
4209 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4212 # this serves two purposes:
4213 # - a class method to load the file support modules included with Imager
4214 # (or were included, once the library dependent modules are split out)
4215 # - something for Module::ScanDeps to analyze
4216 # https://rt.cpan.org/Ticket/Display.html?id=6566
4218 eval { require Imager::File::GIF };
4219 eval { require Imager::File::JPEG };
4220 eval { require Imager::File::PNG };
4221 eval { require Imager::File::SGI };
4222 eval { require Imager::File::TIFF };
4223 eval { require Imager::File::ICO };
4224 eval { require Imager::Font::W32 };
4225 eval { require Imager::Font::FT2 };
4226 eval { require Imager::Font::T1 };
4233 my ($class, $fh) = @_;
4236 return $class->new_cb
4241 return print $fh $_[0];
4245 my $count = CORE::read $fh, $tmp, $_[1];
4253 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4254 unless (CORE::seek $fh, $_[0], $_[1]) {
4265 return $class->_new_perlio($fh);
4269 # backward compatibility for %formats
4270 package Imager::FORMATS;
4272 use constant IX_FORMATS => 0;
4273 use constant IX_LIST => 1;
4274 use constant IX_INDEX => 2;
4275 use constant IX_CLASSES => 3;
4278 my ($class, $formats, $classes) = @_;
4280 return bless [ $formats, [ ], 0, $classes ], $class;
4284 my ($self, $key) = @_;
4286 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4289 my $loaded = Imager::_load_file($file, \$error);
4294 if ($error =~ /^Can't locate /) {
4295 $error = "Can't locate $file";
4297 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4300 $self->[IX_FORMATS]{$key} = $value;
4306 my ($self, $key) = @_;
4308 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4310 $self->[IX_CLASSES]{$key} or return undef;
4312 return $self->_check($key);
4316 die "%Imager::formats is not user monifiable";
4320 die "%Imager::formats is not user monifiable";
4324 die "%Imager::formats is not user monifiable";
4328 my ($self, $key) = @_;
4330 if (exists $self->[IX_FORMATS]{$key}) {
4331 my $value = $self->[IX_FORMATS]{$key}
4336 $self->_check($key) or return 1==0;
4344 unless (@{$self->[IX_LIST]}) {
4346 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4347 keys %{$self->[IX_FORMATS]};
4349 for my $key (keys %{$self->[IX_CLASSES]}) {
4350 $self->[IX_FORMATS]{$key} and next;
4352 and push @{$self->[IX_LIST]}, $key;
4356 @{$self->[IX_LIST]} or return;
4357 $self->[IX_INDEX] = 1;
4358 return $self->[IX_LIST][0];
4364 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4367 return $self->[IX_LIST][$self->[IX_INDEX]++];
4373 return scalar @{$self->[IX_LIST]};
4378 # Below is the stub of documentation for your module. You better edit it!
4382 Imager - Perl extension for Generating 24 bit Images
4392 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4397 # see Imager::Files for information on the read() method
4398 my $img = Imager->new(file=>$file)
4399 or die Imager->errstr();
4401 $file =~ s/\.[^.]*$//;
4403 # Create smaller version
4404 # documented in Imager::Transformations
4405 my $thumb = $img->scale(scalefactor=>.3);
4407 # Autostretch individual channels
4408 $thumb->filter(type=>'autolevels');
4410 # try to save in one of these formats
4413 for $format ( qw( png gif jpeg tiff ppm ) ) {
4414 # Check if given format is supported
4415 if ($Imager::formats{$format}) {
4416 $file.="_low.$format";
4417 print "Storing image as: $file\n";
4418 # documented in Imager::Files
4419 $thumb->write(file=>$file) or
4427 Imager is a module for creating and altering images. It can read and
4428 write various image formats, draw primitive shapes like lines,and
4429 polygons, blend multiple images together in various ways, scale, crop,
4430 render text and more.
4432 =head2 Overview of documentation
4438 Imager - This document - Synopsis, Example, Table of Contents and
4443 L<Imager::Install> - installation notes for Imager.
4447 L<Imager::Tutorial> - a brief introduction to Imager.
4451 L<Imager::Cookbook> - how to do various things with Imager.
4455 L<Imager::ImageTypes> - Basics of constructing image objects with
4456 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4457 8/16/double bits/channel, color maps, channel masks, image tags, color
4458 quantization. Also discusses basic image information methods.
4462 L<Imager::Files> - IO interaction, reading/writing images, format
4467 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4472 L<Imager::Color> - Color specification.
4476 L<Imager::Fill> - Fill pattern specification.
4480 L<Imager::Font> - General font rendering, bounding boxes and font
4485 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4486 blending, pasting, convert and map.
4490 L<Imager::Engines> - Programmable transformations through
4491 C<transform()>, C<transform2()> and C<matrix_transform()>.
4495 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4500 L<Imager::Expr> - Expressions for evaluation engine used by
4505 L<Imager::Matrix2d> - Helper class for affine transformations.
4509 L<Imager::Fountain> - Helper for making gradient profiles.
4513 L<Imager::IO> - Imager I/O abstraction.
4517 L<Imager::API> - using Imager's C API
4521 L<Imager::APIRef> - API function reference
4525 L<Imager::Inline> - using Imager's C API from Inline::C
4529 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4533 L<Imager::Security> - brief security notes.
4537 L<Imager::Threads> - brief information on working with threads.
4541 =head2 Basic Overview
4543 An Image object is created with C<$img = Imager-E<gt>new()>.
4546 $img=Imager->new(); # create empty image
4547 $img->read(file=>'lena.png',type=>'png') or # read image from file
4548 die $img->errstr(); # give an explanation
4549 # if something failed
4551 or if you want to create an empty image:
4553 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4555 This example creates a completely black image of width 400 and height
4558 =head1 ERROR HANDLING
4560 In general a method will return false when it fails, if it does use
4561 the C<errstr()> method to find out why:
4567 Returns the last error message in that context.
4569 If the last error you received was from calling an object method, such
4570 as read, call errstr() as an object method to find out why:
4572 my $image = Imager->new;
4573 $image->read(file => 'somefile.gif')
4574 or die $image->errstr;
4576 If it was a class method then call errstr() as a class method:
4578 my @imgs = Imager->read_multi(file => 'somefile.gif')
4579 or die Imager->errstr;
4581 Note that in some cases object methods are implemented in terms of
4582 class methods so a failing object method may set both.
4586 The C<Imager-E<gt>new> method is described in detail in
4587 L<Imager::ImageTypes>.
4591 Where to find information on methods for Imager class objects.
4593 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4596 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4598 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4601 arc() - L<Imager::Draw/arc()> - draw a filled arc
4603 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4606 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4608 check_file_limits() - L<Imager::Files/check_file_limits()>
4610 circle() - L<Imager::Draw/circle()> - draw a filled circle
4612 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4615 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4616 colors in an image's palette (paletted images only)
4618 combine() - L<Imager::Transformations/combine()> - combine channels
4619 from one or more images.
4621 combines() - L<Imager::Draw/combines()> - return a list of the
4622 different combine type keywords
4624 compose() - L<Imager::Transformations/compose()> - compose one image
4627 convert() - L<Imager::Transformations/convert()> - transform the color
4630 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4633 crop() - L<Imager::Transformations/crop()> - extract part of an image
4635 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4636 used to guess the output file format based on the output file name
4638 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4640 difference() - L<Imager::Filters/difference()> - produce a difference
4641 images from two input images.
4643 errstr() - L</errstr()> - the error from the last failed operation.
4645 filter() - L<Imager::Filters/filter()> - image filtering
4647 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4648 palette, if it has one
4650 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4653 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4656 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4657 samples per pixel for an image
4659 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4660 different colors used by an image (works for direct color images)
4662 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4663 palette, if it has one
4665 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4667 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4669 get_file_limits() - L<Imager::Files/get_file_limits()>
4671 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4674 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4676 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4679 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4680 row or partial row of pixels.
4682 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4683 row or partial row of pixels.
4685 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4688 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4691 init() - L<Imager::ImageTypes/init()>
4693 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4694 image write functions should write the image in their bilevel (blank
4695 and white, no gray levels) format
4697 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4700 line() - L<Imager::Draw/line()> - draw an interval
4702 load_plugin() - L<Imager::Filters/load_plugin()>
4704 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4707 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4708 color palette from one or more input images.
4710 map() - L<Imager::Transformations/map()> - remap color
4713 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4715 matrix_transform() - L<Imager::Engines/matrix_transform()>
4717 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4719 NC() - L<Imager::Handy/NC()>
4721 NCF() - L<Imager::Handy/NCF()>
4723 new() - L<Imager::ImageTypes/new()>
4725 newcolor() - L<Imager::Handy/newcolor()>
4727 newcolour() - L<Imager::Handy/newcolour()>
4729 newfont() - L<Imager::Handy/newfont()>
4731 NF() - L<Imager::Handy/NF()>
4733 open() - L<Imager::Files/read()> - an alias for read()
4735 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4739 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4742 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4745 polygon() - L<Imager::Draw/polygon()>
4747 polyline() - L<Imager::Draw/polyline()>
4749 preload() - L<Imager::Files/preload()>
4751 read() - L<Imager::Files/read()> - read a single image from an image file
4753 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4756 read_types() - L<Imager::Files/read_types()> - list image types Imager
4759 register_filter() - L<Imager::Filters/register_filter()>
4761 register_reader() - L<Imager::Files/register_reader()>
4763 register_writer() - L<Imager::Files/register_writer()>
4765 rotate() - L<Imager::Transformations/rotate()>
4767 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4768 onto an image and use the alpha channel
4770 scale() - L<Imager::Transformations/scale()>
4772 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4774 scaleX() - L<Imager::Transformations/scaleX()>
4776 scaleY() - L<Imager::Transformations/scaleY()>
4778 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4781 set_file_limits() - L<Imager::Files/set_file_limits()>
4783 setmask() - L<Imager::ImageTypes/setmask()>
4785 setpixel() - L<Imager::Draw/setpixel()>
4787 setsamples() - L<Imager::Draw/setsamples()>
4789 setscanline() - L<Imager::Draw/setscanline()>
4791 settag() - L<Imager::ImageTypes/settag()>
4793 string() - L<Imager::Draw/string()> - draw text on an image
4795 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4797 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4799 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4801 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4803 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4804 double per sample image.
4806 transform() - L<Imager::Engines/"transform()">
4808 transform2() - L<Imager::Engines/"transform2()">
4810 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4812 unload_plugin() - L<Imager::Filters/unload_plugin()>
4814 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4817 write() - L<Imager::Files/write()> - write an image to a file
4819 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4822 write_types() - L<Imager::Files/read_types()> - list image types Imager
4825 =head1 CONCEPT INDEX
4827 animated GIF - L<Imager::Files/"Writing an animated GIF">
4829 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4830 L<Imager::ImageTypes/"Common Tags">.
4832 blend - alpha blending one image onto another
4833 L<Imager::Transformations/rubthrough()>
4835 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4837 boxes, drawing - L<Imager::Draw/box()>
4839 changes between image - L<Imager::Filters/"Image Difference">
4841 channels, combine into one image - L<Imager::Transformations/combine()>
4843 color - L<Imager::Color>
4845 color names - L<Imager::Color>, L<Imager::Color::Table>
4847 combine modes - L<Imager::Draw/"Combine Types">
4849 compare images - L<Imager::Filters/"Image Difference">
4851 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4853 convolution - L<Imager::Filters/conv>
4855 cropping - L<Imager::Transformations/crop()>
4857 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4859 C<diff> images - L<Imager::Filters/"Image Difference">
4861 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4862 L<Imager::Cookbook/"Image spatial resolution">
4864 drawing boxes - L<Imager::Draw/box()>
4866 drawing lines - L<Imager::Draw/line()>
4868 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4870 error message - L</"ERROR HANDLING">
4872 files, font - L<Imager::Font>
4874 files, image - L<Imager::Files>
4876 filling, types of fill - L<Imager::Fill>
4878 filling, boxes - L<Imager::Draw/box()>
4880 filling, flood fill - L<Imager::Draw/flood_fill()>
4882 flood fill - L<Imager::Draw/flood_fill()>
4884 fonts - L<Imager::Font>
4886 fonts, drawing with - L<Imager::Draw/string()>,
4887 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4889 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4891 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4893 fountain fill - L<Imager::Fill/"Fountain fills">,
4894 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4895 L<Imager::Filters/gradgen>
4897 GIF files - L<Imager::Files/"GIF">
4899 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4901 gradient fill - L<Imager::Fill/"Fountain fills">,
4902 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4903 L<Imager::Filters/gradgen>
4905 gray scale, convert image to - L<Imager::Transformations/convert()>
4907 gaussian blur - L<Imager::Filters/gaussian>
4909 hatch fills - L<Imager::Fill/"Hatched fills">
4911 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4913 invert image - L<Imager::Filters/hardinvert>,
4914 L<Imager::Filters/hardinvertall>
4916 JPEG - L<Imager::Files/"JPEG">
4918 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4920 lines, drawing - L<Imager::Draw/line()>
4922 matrix - L<Imager::Matrix2d>,
4923 L<Imager::Engines/"Matrix Transformations">,
4924 L<Imager::Font/transform()>
4926 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
4928 mosaic - L<Imager::Filters/mosaic>
4930 noise, filter - L<Imager::Filters/noise>
4932 noise, rendered - L<Imager::Filters/turbnoise>,
4933 L<Imager::Filters/radnoise>
4935 paste - L<Imager::Transformations/paste()>,
4936 L<Imager::Transformations/rubthrough()>
4938 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4939 L<Imager::ImageTypes/new()>
4941 =for stopwords posterize
4943 posterize - L<Imager::Filters/postlevels>
4945 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4947 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4949 rectangles, drawing - L<Imager::Draw/box()>
4951 resizing an image - L<Imager::Transformations/scale()>,
4952 L<Imager::Transformations/crop()>
4954 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4956 saving an image - L<Imager::Files>
4958 scaling - L<Imager::Transformations/scale()>
4960 security - L<Imager::Security>
4962 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4964 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4966 size, image - L<Imager::ImageTypes/getwidth()>,
4967 L<Imager::ImageTypes/getheight()>
4969 size, text - L<Imager::Font/bounding_box()>
4971 tags, image metadata - L<Imager::ImageTypes/"Tags">
4973 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4974 L<Imager::Font::Wrap>
4976 text, wrapping text in an area - L<Imager::Font::Wrap>
4978 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4980 threads - L<Imager::Threads>
4982 tiles, color - L<Imager::Filters/mosaic>
4984 transparent images - L<Imager::ImageTypes>,
4985 L<Imager::Cookbook/"Transparent PNG">
4987 =for stopwords unsharp
4989 unsharp mask - L<Imager::Filters/unsharpmask>
4991 watermark - L<Imager::Filters/watermark>
4993 writing an image to a file - L<Imager::Files>
4997 The best place to get help with Imager is the mailing list.
4999 To subscribe send a message with C<subscribe> in the body to:
5001 imager-devel+request@molar.is
5007 L<http://www.molar.is/en/lists/imager-devel/>
5011 where you can also find the mailing list archive.
5013 You can report bugs by pointing your browser at:
5017 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5021 or by sending an email to:
5025 bug-Imager@rt.cpan.org
5029 Please remember to include the versions of Imager, perl, supporting
5030 libraries, and any relevant code. If you have specific images that
5031 cause the problems, please include those too.
5033 If you don't want to publish your email address on a mailing list you
5034 can use CPAN::Forum:
5036 http://www.cpanforum.com/dist/Imager
5038 You will need to register to post.
5040 =head1 CONTRIBUTING TO IMAGER
5046 If you like or dislike Imager, you can add a public review of Imager
5049 http://cpanratings.perl.org/dist/Imager
5051 =for stopwords Bitcard
5053 This requires a Bitcard account (http://www.bitcard.org).
5055 You can also send email to the maintainer below.
5057 If you send me a bug report via email, it will be copied to Request
5062 I accept patches, preferably against the master branch in git. Please
5063 include an explanation of the reason for why the patch is needed or
5066 Your patch should include regression tests where possible, otherwise
5067 it will be delayed until I get a chance to write them.
5069 To browse Imager's git repository:
5071 http://git.imager.perl.org/imager.git
5075 git clone git://git.imager.perl.org/imager.git
5077 My preference is that patches are provided in the format produced by
5078 C<git format-patch>, for example, if you made your changes in a branch
5079 from master you might do:
5081 git format-patch -k --stdout master >my-patch.txt
5083 and then attach that to your bug report, either by adding it as an
5084 attachment in your email client, or by using the Request Tracker
5085 attachment mechanism.
5089 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5091 Arnar M. Hrafnkelsson is the original author of Imager.
5093 Many others have contributed to Imager, please see the C<README> for a
5098 Imager is licensed under the same terms as perl itself.
5101 makeblendedfont Fontforge
5103 A test font, generated by the Debian packaged Fontforge,
5104 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5105 copyrighted by Adobe. See F<adobe.txt> in the source for license
5110 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5111 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5112 L<Imager::Font>(3), L<Imager::Transformations>(3),
5113 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5114 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5116 L<http://imager.perl.org/>
5118 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5120 Other perl imaging modules include:
5122 L<GD>(3), L<Image::Magick>(3),
5123 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5124 L<Prima::Image>, L<IPA>.
5126 For manipulating image metadata see L<Image::ExifTool>.
5128 If you're trying to use Imager for array processing, you should
5129 probably using L<PDL>.