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);
4199 # Inline added a new argument at the beginning
4203 or die "Only C language supported";
4205 require Imager::ExtUtils;
4206 return Imager::ExtUtils->inline_config;
4209 # threads shouldn't try to close raw Imager objects
4210 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4213 # this serves two purposes:
4214 # - a class method to load the file support modules included with Imager
4215 # (or were included, once the library dependent modules are split out)
4216 # - something for Module::ScanDeps to analyze
4217 # https://rt.cpan.org/Ticket/Display.html?id=6566
4219 eval { require Imager::File::GIF };
4220 eval { require Imager::File::JPEG };
4221 eval { require Imager::File::PNG };
4222 eval { require Imager::File::SGI };
4223 eval { require Imager::File::TIFF };
4224 eval { require Imager::File::ICO };
4225 eval { require Imager::Font::W32 };
4226 eval { require Imager::Font::FT2 };
4227 eval { require Imager::Font::T1 };
4234 my ($class, $fh) = @_;
4237 return $class->new_cb
4242 return print $fh $_[0];
4246 my $count = CORE::read $fh, $tmp, $_[1];
4254 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4255 unless (CORE::seek $fh, $_[0], $_[1]) {
4266 return $class->_new_perlio($fh);
4270 # backward compatibility for %formats
4271 package Imager::FORMATS;
4273 use constant IX_FORMATS => 0;
4274 use constant IX_LIST => 1;
4275 use constant IX_INDEX => 2;
4276 use constant IX_CLASSES => 3;
4279 my ($class, $formats, $classes) = @_;
4281 return bless [ $formats, [ ], 0, $classes ], $class;
4285 my ($self, $key) = @_;
4287 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4290 my $loaded = Imager::_load_file($file, \$error);
4295 if ($error =~ /^Can't locate /) {
4296 $error = "Can't locate $file";
4298 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4301 $self->[IX_FORMATS]{$key} = $value;
4307 my ($self, $key) = @_;
4309 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4311 $self->[IX_CLASSES]{$key} or return undef;
4313 return $self->_check($key);
4317 die "%Imager::formats is not user monifiable";
4321 die "%Imager::formats is not user monifiable";
4325 die "%Imager::formats is not user monifiable";
4329 my ($self, $key) = @_;
4331 if (exists $self->[IX_FORMATS]{$key}) {
4332 my $value = $self->[IX_FORMATS]{$key}
4337 $self->_check($key) or return 1==0;
4345 unless (@{$self->[IX_LIST]}) {
4347 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4348 keys %{$self->[IX_FORMATS]};
4350 for my $key (keys %{$self->[IX_CLASSES]}) {
4351 $self->[IX_FORMATS]{$key} and next;
4353 and push @{$self->[IX_LIST]}, $key;
4357 @{$self->[IX_LIST]} or return;
4358 $self->[IX_INDEX] = 1;
4359 return $self->[IX_LIST][0];
4365 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4368 return $self->[IX_LIST][$self->[IX_INDEX]++];
4374 return scalar @{$self->[IX_LIST]};
4379 # Below is the stub of documentation for your module. You better edit it!
4383 Imager - Perl extension for Generating 24 bit Images
4393 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4398 # see Imager::Files for information on the read() method
4399 my $img = Imager->new(file=>$file)
4400 or die Imager->errstr();
4402 $file =~ s/\.[^.]*$//;
4404 # Create smaller version
4405 # documented in Imager::Transformations
4406 my $thumb = $img->scale(scalefactor=>.3);
4408 # Autostretch individual channels
4409 $thumb->filter(type=>'autolevels');
4411 # try to save in one of these formats
4414 for $format ( qw( png gif jpeg tiff ppm ) ) {
4415 # Check if given format is supported
4416 if ($Imager::formats{$format}) {
4417 $file.="_low.$format";
4418 print "Storing image as: $file\n";
4419 # documented in Imager::Files
4420 $thumb->write(file=>$file) or
4428 Imager is a module for creating and altering images. It can read and
4429 write various image formats, draw primitive shapes like lines,and
4430 polygons, blend multiple images together in various ways, scale, crop,
4431 render text and more.
4433 =head2 Overview of documentation
4439 Imager - This document - Synopsis, Example, Table of Contents and
4444 L<Imager::Install> - installation notes for Imager.
4448 L<Imager::Tutorial> - a brief introduction to Imager.
4452 L<Imager::Cookbook> - how to do various things with Imager.
4456 L<Imager::ImageTypes> - Basics of constructing image objects with
4457 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4458 8/16/double bits/channel, color maps, channel masks, image tags, color
4459 quantization. Also discusses basic image information methods.
4463 L<Imager::Files> - IO interaction, reading/writing images, format
4468 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4473 L<Imager::Color> - Color specification.
4477 L<Imager::Fill> - Fill pattern specification.
4481 L<Imager::Font> - General font rendering, bounding boxes and font
4486 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4487 blending, pasting, convert and map.
4491 L<Imager::Engines> - Programmable transformations through
4492 C<transform()>, C<transform2()> and C<matrix_transform()>.
4496 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4501 L<Imager::Expr> - Expressions for evaluation engine used by
4506 L<Imager::Matrix2d> - Helper class for affine transformations.
4510 L<Imager::Fountain> - Helper for making gradient profiles.
4514 L<Imager::IO> - Imager I/O abstraction.
4518 L<Imager::API> - using Imager's C API
4522 L<Imager::APIRef> - API function reference
4526 L<Imager::Inline> - using Imager's C API from Inline::C
4530 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4534 L<Imager::Security> - brief security notes.
4538 L<Imager::Threads> - brief information on working with threads.
4542 =head2 Basic Overview
4544 An Image object is created with C<$img = Imager-E<gt>new()>.
4547 $img=Imager->new(); # create empty image
4548 $img->read(file=>'lena.png',type=>'png') or # read image from file
4549 die $img->errstr(); # give an explanation
4550 # if something failed
4552 or if you want to create an empty image:
4554 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4556 This example creates a completely black image of width 400 and height
4559 =head1 ERROR HANDLING
4561 In general a method will return false when it fails, if it does use
4562 the C<errstr()> method to find out why:
4568 Returns the last error message in that context.
4570 If the last error you received was from calling an object method, such
4571 as read, call errstr() as an object method to find out why:
4573 my $image = Imager->new;
4574 $image->read(file => 'somefile.gif')
4575 or die $image->errstr;
4577 If it was a class method then call errstr() as a class method:
4579 my @imgs = Imager->read_multi(file => 'somefile.gif')
4580 or die Imager->errstr;
4582 Note that in some cases object methods are implemented in terms of
4583 class methods so a failing object method may set both.
4587 The C<Imager-E<gt>new> method is described in detail in
4588 L<Imager::ImageTypes>.
4592 Where to find information on methods for Imager class objects.
4594 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4597 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4599 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4602 arc() - L<Imager::Draw/arc()> - draw a filled arc
4604 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4607 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4609 check_file_limits() - L<Imager::Files/check_file_limits()>
4611 circle() - L<Imager::Draw/circle()> - draw a filled circle
4613 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4616 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4617 colors in an image's palette (paletted images only)
4619 combine() - L<Imager::Transformations/combine()> - combine channels
4620 from one or more images.
4622 combines() - L<Imager::Draw/combines()> - return a list of the
4623 different combine type keywords
4625 compose() - L<Imager::Transformations/compose()> - compose one image
4628 convert() - L<Imager::Transformations/convert()> - transform the color
4631 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4634 crop() - L<Imager::Transformations/crop()> - extract part of an image
4636 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4637 used to guess the output file format based on the output file name
4639 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4641 difference() - L<Imager::Filters/difference()> - produce a difference
4642 images from two input images.
4644 errstr() - L</errstr()> - the error from the last failed operation.
4646 filter() - L<Imager::Filters/filter()> - image filtering
4648 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4649 palette, if it has one
4651 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4654 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4657 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4658 samples per pixel for an image
4660 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4661 different colors used by an image (works for direct color images)
4663 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4664 palette, if it has one
4666 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4668 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4670 get_file_limits() - L<Imager::Files/get_file_limits()>
4672 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4675 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4677 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4680 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4681 row or partial row of pixels.
4683 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4684 row or partial row of pixels.
4686 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4689 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4692 init() - L<Imager::ImageTypes/init()>
4694 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4695 image write functions should write the image in their bilevel (blank
4696 and white, no gray levels) format
4698 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4701 line() - L<Imager::Draw/line()> - draw an interval
4703 load_plugin() - L<Imager::Filters/load_plugin()>
4705 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4708 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4709 color palette from one or more input images.
4711 map() - L<Imager::Transformations/map()> - remap color
4714 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4716 matrix_transform() - L<Imager::Engines/matrix_transform()>
4718 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4720 NC() - L<Imager::Handy/NC()>
4722 NCF() - L<Imager::Handy/NCF()>
4724 new() - L<Imager::ImageTypes/new()>
4726 newcolor() - L<Imager::Handy/newcolor()>
4728 newcolour() - L<Imager::Handy/newcolour()>
4730 newfont() - L<Imager::Handy/newfont()>
4732 NF() - L<Imager::Handy/NF()>
4734 open() - L<Imager::Files/read()> - an alias for read()
4736 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4740 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4743 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4746 polygon() - L<Imager::Draw/polygon()>
4748 polyline() - L<Imager::Draw/polyline()>
4750 preload() - L<Imager::Files/preload()>
4752 read() - L<Imager::Files/read()> - read a single image from an image file
4754 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4757 read_types() - L<Imager::Files/read_types()> - list image types Imager
4760 register_filter() - L<Imager::Filters/register_filter()>
4762 register_reader() - L<Imager::Files/register_reader()>
4764 register_writer() - L<Imager::Files/register_writer()>
4766 rotate() - L<Imager::Transformations/rotate()>
4768 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4769 onto an image and use the alpha channel
4771 scale() - L<Imager::Transformations/scale()>
4773 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4775 scaleX() - L<Imager::Transformations/scaleX()>
4777 scaleY() - L<Imager::Transformations/scaleY()>
4779 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4782 set_file_limits() - L<Imager::Files/set_file_limits()>
4784 setmask() - L<Imager::ImageTypes/setmask()>
4786 setpixel() - L<Imager::Draw/setpixel()>
4788 setsamples() - L<Imager::Draw/setsamples()>
4790 setscanline() - L<Imager::Draw/setscanline()>
4792 settag() - L<Imager::ImageTypes/settag()>
4794 string() - L<Imager::Draw/string()> - draw text on an image
4796 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4798 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4800 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4802 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4804 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4805 double per sample image.
4807 transform() - L<Imager::Engines/"transform()">
4809 transform2() - L<Imager::Engines/"transform2()">
4811 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4813 unload_plugin() - L<Imager::Filters/unload_plugin()>
4815 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4818 write() - L<Imager::Files/write()> - write an image to a file
4820 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4823 write_types() - L<Imager::Files/read_types()> - list image types Imager
4826 =head1 CONCEPT INDEX
4828 animated GIF - L<Imager::Files/"Writing an animated GIF">
4830 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4831 L<Imager::ImageTypes/"Common Tags">.
4833 blend - alpha blending one image onto another
4834 L<Imager::Transformations/rubthrough()>
4836 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4838 boxes, drawing - L<Imager::Draw/box()>
4840 changes between image - L<Imager::Filters/"Image Difference">
4842 channels, combine into one image - L<Imager::Transformations/combine()>
4844 color - L<Imager::Color>
4846 color names - L<Imager::Color>, L<Imager::Color::Table>
4848 combine modes - L<Imager::Draw/"Combine Types">
4850 compare images - L<Imager::Filters/"Image Difference">
4852 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4854 convolution - L<Imager::Filters/conv>
4856 cropping - L<Imager::Transformations/crop()>
4858 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4860 C<diff> images - L<Imager::Filters/"Image Difference">
4862 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4863 L<Imager::Cookbook/"Image spatial resolution">
4865 drawing boxes - L<Imager::Draw/box()>
4867 drawing lines - L<Imager::Draw/line()>
4869 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4871 error message - L</"ERROR HANDLING">
4873 files, font - L<Imager::Font>
4875 files, image - L<Imager::Files>
4877 filling, types of fill - L<Imager::Fill>
4879 filling, boxes - L<Imager::Draw/box()>
4881 filling, flood fill - L<Imager::Draw/flood_fill()>
4883 flood fill - L<Imager::Draw/flood_fill()>
4885 fonts - L<Imager::Font>
4887 fonts, drawing with - L<Imager::Draw/string()>,
4888 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4890 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4892 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4894 fountain fill - L<Imager::Fill/"Fountain fills">,
4895 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4896 L<Imager::Filters/gradgen>
4898 GIF files - L<Imager::Files/"GIF">
4900 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4902 gradient fill - L<Imager::Fill/"Fountain fills">,
4903 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4904 L<Imager::Filters/gradgen>
4906 gray scale, convert image to - L<Imager::Transformations/convert()>
4908 gaussian blur - L<Imager::Filters/gaussian>
4910 hatch fills - L<Imager::Fill/"Hatched fills">
4912 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4914 invert image - L<Imager::Filters/hardinvert>,
4915 L<Imager::Filters/hardinvertall>
4917 JPEG - L<Imager::Files/"JPEG">
4919 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4921 lines, drawing - L<Imager::Draw/line()>
4923 matrix - L<Imager::Matrix2d>,
4924 L<Imager::Engines/"Matrix Transformations">,
4925 L<Imager::Font/transform()>
4927 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
4929 mosaic - L<Imager::Filters/mosaic>
4931 noise, filter - L<Imager::Filters/noise>
4933 noise, rendered - L<Imager::Filters/turbnoise>,
4934 L<Imager::Filters/radnoise>
4936 paste - L<Imager::Transformations/paste()>,
4937 L<Imager::Transformations/rubthrough()>
4939 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4940 L<Imager::ImageTypes/new()>
4942 =for stopwords posterize
4944 posterize - L<Imager::Filters/postlevels>
4946 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4948 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4950 rectangles, drawing - L<Imager::Draw/box()>
4952 resizing an image - L<Imager::Transformations/scale()>,
4953 L<Imager::Transformations/crop()>
4955 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4957 saving an image - L<Imager::Files>
4959 scaling - L<Imager::Transformations/scale()>
4961 security - L<Imager::Security>
4963 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4965 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4967 size, image - L<Imager::ImageTypes/getwidth()>,
4968 L<Imager::ImageTypes/getheight()>
4970 size, text - L<Imager::Font/bounding_box()>
4972 tags, image metadata - L<Imager::ImageTypes/"Tags">
4974 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4975 L<Imager::Font::Wrap>
4977 text, wrapping text in an area - L<Imager::Font::Wrap>
4979 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4981 threads - L<Imager::Threads>
4983 tiles, color - L<Imager::Filters/mosaic>
4985 transparent images - L<Imager::ImageTypes>,
4986 L<Imager::Cookbook/"Transparent PNG">
4988 =for stopwords unsharp
4990 unsharp mask - L<Imager::Filters/unsharpmask>
4992 watermark - L<Imager::Filters/watermark>
4994 writing an image to a file - L<Imager::Files>
4998 The best place to get help with Imager is the mailing list.
5000 To subscribe send a message with C<subscribe> in the body to:
5002 imager-devel+request@molar.is
5008 L<http://www.molar.is/en/lists/imager-devel/>
5012 where you can also find the mailing list archive.
5014 You can report bugs by pointing your browser at:
5018 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5022 or by sending an email to:
5026 bug-Imager@rt.cpan.org
5030 Please remember to include the versions of Imager, perl, supporting
5031 libraries, and any relevant code. If you have specific images that
5032 cause the problems, please include those too.
5034 If you don't want to publish your email address on a mailing list you
5035 can use CPAN::Forum:
5037 http://www.cpanforum.com/dist/Imager
5039 You will need to register to post.
5041 =head1 CONTRIBUTING TO IMAGER
5047 If you like or dislike Imager, you can add a public review of Imager
5050 http://cpanratings.perl.org/dist/Imager
5052 =for stopwords Bitcard
5054 This requires a Bitcard account (http://www.bitcard.org).
5056 You can also send email to the maintainer below.
5058 If you send me a bug report via email, it will be copied to Request
5063 I accept patches, preferably against the master branch in git. Please
5064 include an explanation of the reason for why the patch is needed or
5067 Your patch should include regression tests where possible, otherwise
5068 it will be delayed until I get a chance to write them.
5070 To browse Imager's git repository:
5072 http://git.imager.perl.org/imager.git
5076 git clone git://git.imager.perl.org/imager.git
5078 My preference is that patches are provided in the format produced by
5079 C<git format-patch>, for example, if you made your changes in a branch
5080 from master you might do:
5082 git format-patch -k --stdout master >my-patch.txt
5084 and then attach that to your bug report, either by adding it as an
5085 attachment in your email client, or by using the Request Tracker
5086 attachment mechanism.
5090 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5092 Arnar M. Hrafnkelsson is the original author of Imager.
5094 Many others have contributed to Imager, please see the C<README> for a
5099 Imager is licensed under the same terms as perl itself.
5102 makeblendedfont Fontforge
5104 A test font, generated by the Debian packaged Fontforge,
5105 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5106 copyrighted by Adobe. See F<adobe.txt> in the source for license
5111 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5112 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5113 L<Imager::Font>(3), L<Imager::Transformations>(3),
5114 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5115 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5117 L<http://imager.perl.org/>
5119 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5121 Other perl imaging modules include:
5123 L<GD>(3), L<Image::Magick>(3),
5124 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5125 L<Prima::Image>, L<IPA>.
5127 For manipulating image metadata see L<Image::ExifTool>.
5129 If you're trying to use Imager for array processing, you should
5130 probably using L<PDL>.