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 if ($opts{d1} == 0 && $opts{d2} == 361) {
2898 i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2902 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2903 $opts{'d2'}, $opts{fill}{fill});
2906 elsif ($opts{filled}) {
2907 my $color = _color($opts{'color'});
2909 $self->{ERRSTR} = $Imager::ERRSTR;
2912 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2913 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2917 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2918 $opts{'d1'}, $opts{'d2'}, $color);
2922 my $color = _color($opts{'color'});
2923 if ($opts{d2} - $opts{d1} >= 360) {
2924 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2927 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2933 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2934 # assume it's a hash ref
2935 require 'Imager/Fill.pm';
2936 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2937 $self->{ERRSTR} = $Imager::ERRSTR;
2941 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2942 $opts{'d2'}, $opts{fill}{fill});
2945 my $color = _color($opts{'color'});
2947 $self->{ERRSTR} = $Imager::ERRSTR;
2950 if ($opts{filled}) {
2951 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2952 $opts{'d1'}, $opts{'d2'}, $color);
2955 if ($opts{d1} == 0 && $opts{d2} == 361) {
2956 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2959 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2965 $self->_set_error($self->_error_as_msg);
2972 # Draws a line from one point to the other
2973 # the endpoint is set if the endp parameter is set which it is by default.
2974 # to turn of the endpoint being set use endp=>0 when calling line.
2978 my $dflcl=i_color_new(0,0,0,0);
2979 my %opts=(color=>$dflcl,
2983 $self->_valid_image("line")
2986 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2987 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2989 my $color = _color($opts{'color'});
2991 $self->{ERRSTR} = $Imager::ERRSTR;
2995 $opts{antialias} = $opts{aa} if defined $opts{aa};
2996 if ($opts{antialias}) {
2997 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2998 $color, $opts{endp});
3000 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3001 $color, $opts{endp});
3006 # Draws a line between an ordered set of points - It more or less just transforms this
3007 # into a list of lines.
3011 my ($pt,$ls,@points);
3012 my $dflcl=i_color_new(0,0,0,0);
3013 my %opts=(color=>$dflcl,@_);
3015 $self->_valid_image("polyline")
3018 if (exists($opts{points})) { @points=@{$opts{points}}; }
3019 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3020 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3023 # print Dumper(\@points);
3025 my $color = _color($opts{'color'});
3027 $self->{ERRSTR} = $Imager::ERRSTR;
3030 $opts{antialias} = $opts{aa} if defined $opts{aa};
3031 if ($opts{antialias}) {
3034 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3041 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3051 my ($pt,$ls,@points);
3052 my $dflcl = i_color_new(0,0,0,0);
3053 my %opts = (color=>$dflcl, @_);
3055 $self->_valid_image("polygon")
3058 if (exists($opts{points})) {
3059 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3060 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3063 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3064 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3067 if ($opts{'fill'}) {
3068 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3069 # assume it's a hash ref
3070 require 'Imager/Fill.pm';
3071 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3072 $self->{ERRSTR} = $Imager::ERRSTR;
3076 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
3077 $opts{'fill'}{'fill'});
3080 my $color = _color($opts{'color'});
3082 $self->{ERRSTR} = $Imager::ERRSTR;
3085 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3092 # this the multipoint bezier curve
3093 # this is here more for testing that actual usage since
3094 # this is not a good algorithm. Usually the curve would be
3095 # broken into smaller segments and each done individually.
3099 my ($pt,$ls,@points);
3100 my $dflcl=i_color_new(0,0,0,0);
3101 my %opts=(color=>$dflcl,@_);
3103 $self->_valid_image("polybezier")
3106 if (exists $opts{points}) {
3107 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3108 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3111 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3112 $self->{ERRSTR}='Missing or invalid points.';
3116 my $color = _color($opts{'color'});
3118 $self->{ERRSTR} = $Imager::ERRSTR;
3121 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3127 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3130 $self->_valid_image("flood_fill")
3133 unless (exists $opts{'x'} && exists $opts{'y'}) {
3134 $self->{ERRSTR} = "missing seed x and y parameters";
3138 if ($opts{border}) {
3139 my $border = _color($opts{border});
3141 $self->_set_error($Imager::ERRSTR);
3145 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3146 # assume it's a hash ref
3147 require Imager::Fill;
3148 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3149 $self->{ERRSTR} = $Imager::ERRSTR;
3153 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3154 $opts{fill}{fill}, $border);
3157 my $color = _color($opts{'color'});
3159 $self->{ERRSTR} = $Imager::ERRSTR;
3162 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3169 $self->{ERRSTR} = $self->_error_as_msg();
3175 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3176 # assume it's a hash ref
3177 require 'Imager/Fill.pm';
3178 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3179 $self->{ERRSTR} = $Imager::ERRSTR;
3183 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3186 my $color = _color($opts{'color'});
3188 $self->{ERRSTR} = $Imager::ERRSTR;
3191 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3197 $self->{ERRSTR} = $self->_error_as_msg();
3204 my ($self, %opts) = @_;
3206 $self->_valid_image("setpixel")
3209 my $color = $opts{color};
3210 unless (defined $color) {
3211 $color = $self->{fg};
3212 defined $color or $color = NC(255, 255, 255);
3215 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3216 unless ($color = _color($color, 'setpixel')) {
3217 $self->_set_error("setpixel: " . Imager->errstr);
3222 unless (exists $opts{'x'} && exists $opts{'y'}) {
3223 $self->_set_error('setpixel: missing x or y parameter');
3229 if (ref $x || ref $y) {
3230 $x = ref $x ? $x : [ $x ];
3231 $y = ref $y ? $y : [ $y ];
3233 $self->_set_error("setpixel: x is a reference to an empty array");
3237 $self->_set_error("setpixel: y is a reference to an empty array");
3241 # make both the same length, replicating the last element
3243 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3246 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3250 if ($color->isa('Imager::Color')) {
3251 for my $i (0..$#$x) {
3252 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3257 for my $i (0..$#$x) {
3258 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3266 if ($color->isa('Imager::Color')) {
3267 i_ppix($self->{IMG}, $x, $y, $color)
3268 and return "0 but true";
3271 i_ppixf($self->{IMG}, $x, $y, $color)
3272 and return "0 but true";
3282 my %opts = ( "type"=>'8bit', @_);
3284 $self->_valid_image("getpixel")
3287 unless (exists $opts{'x'} && exists $opts{'y'}) {
3288 $self->_set_error('getpixel: missing x or y parameter');
3294 my $type = $opts{'type'};
3295 if (ref $x || ref $y) {
3296 $x = ref $x ? $x : [ $x ];
3297 $y = ref $y ? $y : [ $y ];
3299 $self->_set_error("getpixel: x is a reference to an empty array");
3303 $self->_set_error("getpixel: y is a reference to an empty array");
3307 # make both the same length, replicating the last element
3309 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3312 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3316 if ($type eq '8bit') {
3317 for my $i (0..$#$x) {
3318 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3321 elsif ($type eq 'float' || $type eq 'double') {
3322 for my $i (0..$#$x) {
3323 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3327 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3330 return wantarray ? @result : \@result;
3333 if ($type eq '8bit') {
3334 return i_get_pixel($self->{IMG}, $x, $y);
3336 elsif ($type eq 'float' || $type eq 'double') {
3337 return i_gpixf($self->{IMG}, $x, $y);
3340 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3348 my %opts = ( type => '8bit', x=>0, @_);
3350 $self->_valid_image("getscanline")
3353 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3355 unless (defined $opts{'y'}) {
3356 $self->_set_error("missing y parameter");
3360 if ($opts{type} eq '8bit') {
3361 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3364 elsif ($opts{type} eq 'float') {
3365 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3368 elsif ($opts{type} eq 'index') {
3369 unless (i_img_type($self->{IMG})) {
3370 $self->_set_error("type => index only valid on paletted images");
3373 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3377 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3384 my %opts = ( x=>0, @_);
3386 $self->_valid_image("setscanline")
3389 unless (defined $opts{'y'}) {
3390 $self->_set_error("missing y parameter");
3395 if (ref $opts{pixels} && @{$opts{pixels}}) {
3396 # try to guess the type
3397 if ($opts{pixels}[0]->isa('Imager::Color')) {
3398 $opts{type} = '8bit';
3400 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3401 $opts{type} = 'float';
3404 $self->_set_error("missing type parameter and could not guess from pixels");
3410 $opts{type} = '8bit';
3414 if ($opts{type} eq '8bit') {
3415 if (ref $opts{pixels}) {
3416 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3419 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3422 elsif ($opts{type} eq 'float') {
3423 if (ref $opts{pixels}) {
3424 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3427 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3430 elsif ($opts{type} eq 'index') {
3431 if (ref $opts{pixels}) {
3432 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3435 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3439 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3446 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3448 $self->_valid_image("getsamples")
3451 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3453 unless (defined $opts{'y'}) {
3454 $self->_set_error("missing y parameter");
3458 if ($opts{target}) {
3459 my $target = $opts{target};
3460 my $offset = $opts{offset};
3461 if ($opts{type} eq '8bit') {
3462 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3463 $opts{y}, $opts{channels})
3465 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3466 return scalar(@samples);
3468 elsif ($opts{type} eq 'float') {
3469 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3470 $opts{y}, $opts{channels});
3471 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3472 return scalar(@samples);
3474 elsif ($opts{type} =~ /^(\d+)bit$/) {
3478 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3479 $opts{y}, $bits, $target,
3480 $offset, $opts{channels});
3481 unless (defined $count) {
3482 $self->_set_error(Imager->_error_as_msg);
3489 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3494 if ($opts{type} eq '8bit') {
3495 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3496 $opts{y}, $opts{channels});
3498 elsif ($opts{type} eq 'float') {
3499 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3500 $opts{y}, $opts{channels});
3502 elsif ($opts{type} =~ /^(\d+)bit$/) {
3506 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3507 $opts{y}, $bits, \@data, 0, $opts{channels})
3512 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3521 $self->_valid_image("setsamples")
3524 my %opts = ( x => 0, offset => 0 );
3526 # avoid duplicating the data parameter, it may be a large scalar
3528 while ($i < @_ -1) {
3529 if ($_[$i] eq 'data') {
3533 $opts{$_[$i]} = $_[$i+1];
3539 unless(defined $data_index) {
3540 $self->_set_error('setsamples: data parameter missing');
3543 unless (defined $_[$data_index]) {
3544 $self->_set_error('setsamples: data parameter not defined');
3548 my $type = $opts{type};
3549 defined $type or $type = '8bit';
3551 my $width = defined $opts{width} ? $opts{width}
3552 : $self->getwidth() - $opts{x};
3555 if ($type eq '8bit') {
3556 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3557 $_[$data_index], $opts{offset}, $width);
3559 elsif ($type eq 'float') {
3560 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3561 $_[$data_index], $opts{offset}, $width);
3563 elsif ($type =~ /^([0-9]+)bit$/) {
3566 unless (ref $_[$data_index]) {
3567 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3571 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3572 $opts{channels}, $_[$data_index], $opts{offset},
3576 $self->_set_error('setsamples: type parameter invalid');
3580 unless (defined $count) {
3581 $self->_set_error(Imager->_error_as_msg);
3588 # make an identity matrix of the given size
3592 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3593 for my $c (0 .. ($size-1)) {
3594 $matrix->[$c][$c] = 1;
3599 # general function to convert an image
3601 my ($self, %opts) = @_;
3604 $self->_valid_image("convert")
3607 unless (defined wantarray) {
3608 my @caller = caller;
3609 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3613 # the user can either specify a matrix or preset
3614 # the matrix overrides the preset
3615 if (!exists($opts{matrix})) {
3616 unless (exists($opts{preset})) {
3617 $self->{ERRSTR} = "convert() needs a matrix or preset";
3621 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3622 # convert to greyscale, keeping the alpha channel if any
3623 if ($self->getchannels == 3) {
3624 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3626 elsif ($self->getchannels == 4) {
3627 # preserve the alpha channel
3628 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3633 $matrix = _identity($self->getchannels);
3636 elsif ($opts{preset} eq 'noalpha') {
3637 # strip the alpha channel
3638 if ($self->getchannels == 2 or $self->getchannels == 4) {
3639 $matrix = _identity($self->getchannels);
3640 pop(@$matrix); # lose the alpha entry
3643 $matrix = _identity($self->getchannels);
3646 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3648 $matrix = [ [ 1 ] ];
3650 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3651 $matrix = [ [ 0, 1 ] ];
3653 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3654 $matrix = [ [ 0, 0, 1 ] ];
3656 elsif ($opts{preset} eq 'alpha') {
3657 if ($self->getchannels == 2 or $self->getchannels == 4) {
3658 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3661 # the alpha is just 1 <shrug>
3662 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3665 elsif ($opts{preset} eq 'rgb') {
3666 if ($self->getchannels == 1) {
3667 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3669 elsif ($self->getchannels == 2) {
3670 # preserve the alpha channel
3671 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3674 $matrix = _identity($self->getchannels);
3677 elsif ($opts{preset} eq 'addalpha') {
3678 if ($self->getchannels == 1) {
3679 $matrix = _identity(2);
3681 elsif ($self->getchannels == 3) {
3682 $matrix = _identity(4);
3685 $matrix = _identity($self->getchannels);
3689 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3695 $matrix = $opts{matrix};
3698 my $new = Imager->new;
3699 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3700 unless ($new->{IMG}) {
3701 # most likely a bad matrix
3702 i_push_error(0, "convert");
3703 $self->{ERRSTR} = _error_as_msg();
3709 # combine channels from multiple input images, a class method
3711 my ($class, %opts) = @_;
3713 my $src = delete $opts{src};
3715 $class->_set_error("src parameter missing");
3720 for my $img (@$src) {
3721 unless (eval { $img->isa("Imager") }) {
3722 $class->_set_error("src must contain image objects");
3725 unless ($img->_valid_image("combine")) {
3726 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3729 push @imgs, $img->{IMG};
3732 if (my $channels = delete $opts{channels}) {
3733 $result = i_combine(\@imgs, $channels);
3736 $result = i_combine(\@imgs);
3739 $class->_set_error($class->_error_as_msg);
3743 my $img = $class->new;
3744 $img->{IMG} = $result;
3750 # general function to map an image through lookup tables
3753 my ($self, %opts) = @_;
3754 my @chlist = qw( red green blue alpha );
3756 $self->_valid_image("map")
3759 if (!exists($opts{'maps'})) {
3760 # make maps from channel maps
3762 for $chnum (0..$#chlist) {
3763 if (exists $opts{$chlist[$chnum]}) {
3764 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3765 } elsif (exists $opts{'all'}) {
3766 $opts{'maps'}[$chnum] = $opts{'all'};
3770 if ($opts{'maps'} and $self->{IMG}) {
3771 i_map($self->{IMG}, $opts{'maps'} );
3777 my ($self, %opts) = @_;
3779 $self->_valid_image("difference")
3782 defined $opts{mindist} or $opts{mindist} = 0;
3784 defined $opts{other}
3785 or return $self->_set_error("No 'other' parameter supplied");
3786 unless ($opts{other}->_valid_image("difference")) {
3787 $self->_set_error($opts{other}->errstr . " (other image)");
3791 my $result = Imager->new;
3792 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3794 or return $self->_set_error($self->_error_as_msg());
3799 # destructive border - image is shrunk by one pixel all around
3802 my ($self,%opts)=@_;
3803 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3804 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3808 # Get the width of an image
3813 $self->_valid_image("getwidth")
3816 return i_img_get_width($self->{IMG});
3819 # Get the height of an image
3824 $self->_valid_image("getheight")
3827 return i_img_get_height($self->{IMG});
3830 # Get number of channels in an image
3835 $self->_valid_image("getchannels")
3838 return i_img_getchannels($self->{IMG});
3846 $self->_valid_image("getmask")
3849 return i_img_getmask($self->{IMG});
3858 $self->_valid_image("setmask")
3861 unless (defined $opts{mask}) {
3862 $self->_set_error("mask parameter required");
3866 i_img_setmask( $self->{IMG} , $opts{mask} );
3871 # Get number of colors in an image
3875 my %opts=('maxcolors'=>2**30,@_);
3877 $self->_valid_image("getcolorcount")
3880 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3881 return ($rc==-1? undef : $rc);
3884 # Returns a reference to a hash. The keys are colour named (packed) and the
3885 # values are the number of pixels in this colour.
3886 sub getcolorusagehash {
3889 $self->_valid_image("getcolorusagehash")
3892 my %opts = ( maxcolors => 2**30, @_ );
3893 my $max_colors = $opts{maxcolors};
3894 unless (defined $max_colors && $max_colors > 0) {
3895 $self->_set_error('maxcolors must be a positive integer');
3899 my $channels= $self->getchannels;
3900 # We don't want to look at the alpha channel, because some gifs using it
3901 # doesn't define it for every colour (but only for some)
3902 $channels -= 1 if $channels == 2 or $channels == 4;
3904 my $height = $self->getheight;
3905 for my $y (0 .. $height - 1) {
3906 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3907 while (length $colors) {
3908 $color_use{ substr($colors, 0, $channels, '') }++;
3910 keys %color_use > $max_colors
3916 # This will return a ordered array of the colour usage. Kind of the sorted
3917 # version of the values of the hash returned by getcolorusagehash.
3918 # You might want to add safety checks and change the names, etc...
3922 $self->_valid_image("getcolorusage")
3925 my %opts = ( maxcolors => 2**30, @_ );
3926 my $max_colors = $opts{maxcolors};
3927 unless (defined $max_colors && $max_colors > 0) {
3928 $self->_set_error('maxcolors must be a positive integer');
3932 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3935 # draw string to an image
3940 $self->_valid_image("string")
3943 my %input=('x'=>0, 'y'=>0, @_);
3944 defined($input{string}) or $input{string} = $input{text};
3946 unless(defined $input{string}) {
3947 $self->{ERRSTR}="missing required parameter 'string'";
3951 unless($input{font}) {
3952 $self->{ERRSTR}="missing required parameter 'font'";
3956 unless ($input{font}->draw(image=>$self, %input)) {
3968 $self->_valid_image("align_string")
3977 my %input=('x'=>0, 'y'=>0, @_);
3978 defined $input{string}
3979 or $input{string} = $input{text};
3981 unless(exists $input{string}) {
3982 $self->_set_error("missing required parameter 'string'");
3986 unless($input{font}) {
3987 $self->_set_error("missing required parameter 'font'");
3992 unless (@result = $input{font}->align(image=>$img, %input)) {
3996 return wantarray ? @result : $result[0];
3999 my @file_limit_names = qw/width height bytes/;
4001 sub set_file_limits {
4008 @values{@file_limit_names} = (0) x @file_limit_names;
4011 @values{@file_limit_names} = i_get_image_file_limits();
4014 for my $key (keys %values) {
4015 defined $opts{$key} and $values{$key} = $opts{$key};
4018 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4021 sub get_file_limits {
4022 i_get_image_file_limits();
4025 my @check_args = qw(width height channels sample_size);
4027 sub check_file_limits {
4037 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4038 $opts{sample_size} = length(pack("d", 0));
4041 for my $name (@check_args) {
4042 unless (defined $opts{$name}) {
4043 $class->_set_error("check_file_limits: $name must be defined");
4046 unless ($opts{$name} == int($opts{$name})) {
4047 $class->_set_error("check_file_limits: $name must be a positive integer");
4052 my $result = i_int_check_image_file_limits(@opts{@check_args});
4054 $class->_set_error($class->_error_as_msg());
4060 # Shortcuts that can be exported
4062 sub newcolor { Imager::Color->new(@_); }
4063 sub newfont { Imager::Font->new(@_); }
4065 require Imager::Color::Float;
4066 return Imager::Color::Float->new(@_);
4069 *NC=*newcolour=*newcolor;
4076 #### Utility routines
4079 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4083 my ($self, $msg) = @_;
4086 $self->{ERRSTR} = $msg;
4094 # Default guess for the type of an image from extension
4096 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4100 ( map { $_ => $_ } @simple_types ),
4106 pnm => "pnm", # technically wrong, but historically it works in Imager
4119 sub def_guess_type {
4122 my ($ext) = $name =~ /\.([^.]+)$/
4125 my $type = $ext_types{$ext}
4132 return @combine_types;
4135 # get the minimum of a list
4139 for(@_) { if ($_<$mx) { $mx=$_; }}
4143 # get the maximum of a list
4147 for(@_) { if ($_>$mx) { $mx=$_; }}
4151 # string stuff for iptc headers
4155 $str = substr($str,3);
4156 $str =~ s/[\n\r]//g;
4163 # A little hack to parse iptc headers.
4168 my($caption,$photogr,$headln,$credit);
4170 my $str=$self->{IPTCRAW};
4175 @ar=split(/8BIM/,$str);
4180 @sar=split(/\034\002/);
4181 foreach $item (@sar) {
4182 if ($item =~ m/^x/) {
4183 $caption = _clean($item);
4186 if ($item =~ m/^P/) {
4187 $photogr = _clean($item);
4190 if ($item =~ m/^i/) {
4191 $headln = _clean($item);
4194 if ($item =~ m/^n/) {
4195 $credit = _clean($item);
4201 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4205 # Inline added a new argument at the beginning
4209 or die "Only C language supported";
4211 require Imager::ExtUtils;
4212 return Imager::ExtUtils->inline_config;
4215 # threads shouldn't try to close raw Imager objects
4216 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4219 # this serves two purposes:
4220 # - a class method to load the file support modules included with Imager
4221 # (or were included, once the library dependent modules are split out)
4222 # - something for Module::ScanDeps to analyze
4223 # https://rt.cpan.org/Ticket/Display.html?id=6566
4225 eval { require Imager::File::GIF };
4226 eval { require Imager::File::JPEG };
4227 eval { require Imager::File::PNG };
4228 eval { require Imager::File::SGI };
4229 eval { require Imager::File::TIFF };
4230 eval { require Imager::File::ICO };
4231 eval { require Imager::Font::W32 };
4232 eval { require Imager::Font::FT2 };
4233 eval { require Imager::Font::T1 };
4240 my ($class, $fh) = @_;
4243 return $class->new_cb
4248 return print $fh $_[0];
4252 my $count = CORE::read $fh, $tmp, $_[1];
4260 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4261 unless (CORE::seek $fh, $_[0], $_[1]) {
4272 return $class->_new_perlio($fh);
4276 # backward compatibility for %formats
4277 package Imager::FORMATS;
4279 use constant IX_FORMATS => 0;
4280 use constant IX_LIST => 1;
4281 use constant IX_INDEX => 2;
4282 use constant IX_CLASSES => 3;
4285 my ($class, $formats, $classes) = @_;
4287 return bless [ $formats, [ ], 0, $classes ], $class;
4291 my ($self, $key) = @_;
4293 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4296 my $loaded = Imager::_load_file($file, \$error);
4301 if ($error =~ /^Can't locate /) {
4302 $error = "Can't locate $file";
4304 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4307 $self->[IX_FORMATS]{$key} = $value;
4313 my ($self, $key) = @_;
4315 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4317 $self->[IX_CLASSES]{$key} or return undef;
4319 return $self->_check($key);
4323 die "%Imager::formats is not user monifiable";
4327 die "%Imager::formats is not user monifiable";
4331 die "%Imager::formats is not user monifiable";
4335 my ($self, $key) = @_;
4337 if (exists $self->[IX_FORMATS]{$key}) {
4338 my $value = $self->[IX_FORMATS]{$key}
4343 $self->_check($key) or return 1==0;
4351 unless (@{$self->[IX_LIST]}) {
4353 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4354 keys %{$self->[IX_FORMATS]};
4356 for my $key (keys %{$self->[IX_CLASSES]}) {
4357 $self->[IX_FORMATS]{$key} and next;
4359 and push @{$self->[IX_LIST]}, $key;
4363 @{$self->[IX_LIST]} or return;
4364 $self->[IX_INDEX] = 1;
4365 return $self->[IX_LIST][0];
4371 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4374 return $self->[IX_LIST][$self->[IX_INDEX]++];
4380 return scalar @{$self->[IX_LIST]};
4385 # Below is the stub of documentation for your module. You better edit it!
4389 Imager - Perl extension for Generating 24 bit Images
4399 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4404 # see Imager::Files for information on the read() method
4405 my $img = Imager->new(file=>$file)
4406 or die Imager->errstr();
4408 $file =~ s/\.[^.]*$//;
4410 # Create smaller version
4411 # documented in Imager::Transformations
4412 my $thumb = $img->scale(scalefactor=>.3);
4414 # Autostretch individual channels
4415 $thumb->filter(type=>'autolevels');
4417 # try to save in one of these formats
4420 for $format ( qw( png gif jpeg tiff ppm ) ) {
4421 # Check if given format is supported
4422 if ($Imager::formats{$format}) {
4423 $file.="_low.$format";
4424 print "Storing image as: $file\n";
4425 # documented in Imager::Files
4426 $thumb->write(file=>$file) or
4434 Imager is a module for creating and altering images. It can read and
4435 write various image formats, draw primitive shapes like lines,and
4436 polygons, blend multiple images together in various ways, scale, crop,
4437 render text and more.
4439 =head2 Overview of documentation
4445 Imager - This document - Synopsis, Example, Table of Contents and
4450 L<Imager::Install> - installation notes for Imager.
4454 L<Imager::Tutorial> - a brief introduction to Imager.
4458 L<Imager::Cookbook> - how to do various things with Imager.
4462 L<Imager::ImageTypes> - Basics of constructing image objects with
4463 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4464 8/16/double bits/channel, color maps, channel masks, image tags, color
4465 quantization. Also discusses basic image information methods.
4469 L<Imager::Files> - IO interaction, reading/writing images, format
4474 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4479 L<Imager::Color> - Color specification.
4483 L<Imager::Fill> - Fill pattern specification.
4487 L<Imager::Font> - General font rendering, bounding boxes and font
4492 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4493 blending, pasting, convert and map.
4497 L<Imager::Engines> - Programmable transformations through
4498 C<transform()>, C<transform2()> and C<matrix_transform()>.
4502 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4507 L<Imager::Expr> - Expressions for evaluation engine used by
4512 L<Imager::Matrix2d> - Helper class for affine transformations.
4516 L<Imager::Fountain> - Helper for making gradient profiles.
4520 L<Imager::IO> - Imager I/O abstraction.
4524 L<Imager::API> - using Imager's C API
4528 L<Imager::APIRef> - API function reference
4532 L<Imager::Inline> - using Imager's C API from Inline::C
4536 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4540 L<Imager::Security> - brief security notes.
4544 L<Imager::Threads> - brief information on working with threads.
4548 =head2 Basic Overview
4550 An Image object is created with C<$img = Imager-E<gt>new()>.
4553 $img=Imager->new(); # create empty image
4554 $img->read(file=>'lena.png',type=>'png') or # read image from file
4555 die $img->errstr(); # give an explanation
4556 # if something failed
4558 or if you want to create an empty image:
4560 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4562 This example creates a completely black image of width 400 and height
4565 =head1 ERROR HANDLING
4567 In general a method will return false when it fails, if it does use
4568 the C<errstr()> method to find out why:
4574 Returns the last error message in that context.
4576 If the last error you received was from calling an object method, such
4577 as read, call errstr() as an object method to find out why:
4579 my $image = Imager->new;
4580 $image->read(file => 'somefile.gif')
4581 or die $image->errstr;
4583 If it was a class method then call errstr() as a class method:
4585 my @imgs = Imager->read_multi(file => 'somefile.gif')
4586 or die Imager->errstr;
4588 Note that in some cases object methods are implemented in terms of
4589 class methods so a failing object method may set both.
4593 The C<Imager-E<gt>new> method is described in detail in
4594 L<Imager::ImageTypes>.
4598 Where to find information on methods for Imager class objects.
4600 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4603 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4605 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4608 arc() - L<Imager::Draw/arc()> - draw a filled arc
4610 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4613 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4615 check_file_limits() - L<Imager::Files/check_file_limits()>
4617 circle() - L<Imager::Draw/circle()> - draw a filled circle
4619 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4622 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4623 colors in an image's palette (paletted images only)
4625 combine() - L<Imager::Transformations/combine()> - combine channels
4626 from one or more images.
4628 combines() - L<Imager::Draw/combines()> - return a list of the
4629 different combine type keywords
4631 compose() - L<Imager::Transformations/compose()> - compose one image
4634 convert() - L<Imager::Transformations/convert()> - transform the color
4637 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4640 crop() - L<Imager::Transformations/crop()> - extract part of an image
4642 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4643 used to guess the output file format based on the output file name
4645 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4647 difference() - L<Imager::Filters/difference()> - produce a difference
4648 images from two input images.
4650 errstr() - L</errstr()> - the error from the last failed operation.
4652 filter() - L<Imager::Filters/filter()> - image filtering
4654 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4655 palette, if it has one
4657 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4660 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4663 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4664 samples per pixel for an image
4666 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4667 different colors used by an image (works for direct color images)
4669 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4670 palette, if it has one
4672 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4674 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4676 get_file_limits() - L<Imager::Files/get_file_limits()>
4678 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4681 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4683 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4686 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4687 row or partial row of pixels.
4689 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4690 row or partial row of pixels.
4692 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4695 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4698 init() - L<Imager::ImageTypes/init()>
4700 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4701 image write functions should write the image in their bilevel (blank
4702 and white, no gray levels) format
4704 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4707 line() - L<Imager::Draw/line()> - draw an interval
4709 load_plugin() - L<Imager::Filters/load_plugin()>
4711 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4714 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4715 color palette from one or more input images.
4717 map() - L<Imager::Transformations/map()> - remap color
4720 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4722 matrix_transform() - L<Imager::Engines/matrix_transform()>
4724 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4726 NC() - L<Imager::Handy/NC()>
4728 NCF() - L<Imager::Handy/NCF()>
4730 new() - L<Imager::ImageTypes/new()>
4732 newcolor() - L<Imager::Handy/newcolor()>
4734 newcolour() - L<Imager::Handy/newcolour()>
4736 newfont() - L<Imager::Handy/newfont()>
4738 NF() - L<Imager::Handy/NF()>
4740 open() - L<Imager::Files/read()> - an alias for read()
4742 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4746 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4749 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4752 polygon() - L<Imager::Draw/polygon()>
4754 polyline() - L<Imager::Draw/polyline()>
4756 preload() - L<Imager::Files/preload()>
4758 read() - L<Imager::Files/read()> - read a single image from an image file
4760 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4763 read_types() - L<Imager::Files/read_types()> - list image types Imager
4766 register_filter() - L<Imager::Filters/register_filter()>
4768 register_reader() - L<Imager::Files/register_reader()>
4770 register_writer() - L<Imager::Files/register_writer()>
4772 rotate() - L<Imager::Transformations/rotate()>
4774 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4775 onto an image and use the alpha channel
4777 scale() - L<Imager::Transformations/scale()>
4779 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4781 scaleX() - L<Imager::Transformations/scaleX()>
4783 scaleY() - L<Imager::Transformations/scaleY()>
4785 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4788 set_file_limits() - L<Imager::Files/set_file_limits()>
4790 setmask() - L<Imager::ImageTypes/setmask()>
4792 setpixel() - L<Imager::Draw/setpixel()>
4794 setsamples() - L<Imager::Draw/setsamples()>
4796 setscanline() - L<Imager::Draw/setscanline()>
4798 settag() - L<Imager::ImageTypes/settag()>
4800 string() - L<Imager::Draw/string()> - draw text on an image
4802 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4804 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4806 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4808 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4810 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4811 double per sample image.
4813 transform() - L<Imager::Engines/"transform()">
4815 transform2() - L<Imager::Engines/"transform2()">
4817 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4819 unload_plugin() - L<Imager::Filters/unload_plugin()>
4821 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4824 write() - L<Imager::Files/write()> - write an image to a file
4826 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4829 write_types() - L<Imager::Files/read_types()> - list image types Imager
4832 =head1 CONCEPT INDEX
4834 animated GIF - L<Imager::Files/"Writing an animated GIF">
4836 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4837 L<Imager::ImageTypes/"Common Tags">.
4839 blend - alpha blending one image onto another
4840 L<Imager::Transformations/rubthrough()>
4842 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4844 boxes, drawing - L<Imager::Draw/box()>
4846 changes between image - L<Imager::Filters/"Image Difference">
4848 channels, combine into one image - L<Imager::Transformations/combine()>
4850 color - L<Imager::Color>
4852 color names - L<Imager::Color>, L<Imager::Color::Table>
4854 combine modes - L<Imager::Draw/"Combine Types">
4856 compare images - L<Imager::Filters/"Image Difference">
4858 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4860 convolution - L<Imager::Filters/conv>
4862 cropping - L<Imager::Transformations/crop()>
4864 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4866 C<diff> images - L<Imager::Filters/"Image Difference">
4868 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4869 L<Imager::Cookbook/"Image spatial resolution">
4871 drawing boxes - L<Imager::Draw/box()>
4873 drawing lines - L<Imager::Draw/line()>
4875 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4877 error message - L</"ERROR HANDLING">
4879 files, font - L<Imager::Font>
4881 files, image - L<Imager::Files>
4883 filling, types of fill - L<Imager::Fill>
4885 filling, boxes - L<Imager::Draw/box()>
4887 filling, flood fill - L<Imager::Draw/flood_fill()>
4889 flood fill - L<Imager::Draw/flood_fill()>
4891 fonts - L<Imager::Font>
4893 fonts, drawing with - L<Imager::Draw/string()>,
4894 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4896 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4898 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4900 fountain fill - L<Imager::Fill/"Fountain fills">,
4901 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4902 L<Imager::Filters/gradgen>
4904 GIF files - L<Imager::Files/"GIF">
4906 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4908 gradient fill - L<Imager::Fill/"Fountain fills">,
4909 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4910 L<Imager::Filters/gradgen>
4912 gray scale, convert image to - L<Imager::Transformations/convert()>
4914 gaussian blur - L<Imager::Filters/gaussian>
4916 hatch fills - L<Imager::Fill/"Hatched fills">
4918 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4920 invert image - L<Imager::Filters/hardinvert>,
4921 L<Imager::Filters/hardinvertall>
4923 JPEG - L<Imager::Files/"JPEG">
4925 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4927 lines, drawing - L<Imager::Draw/line()>
4929 matrix - L<Imager::Matrix2d>,
4930 L<Imager::Engines/"Matrix Transformations">,
4931 L<Imager::Font/transform()>
4933 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
4935 mosaic - L<Imager::Filters/mosaic>
4937 noise, filter - L<Imager::Filters/noise>
4939 noise, rendered - L<Imager::Filters/turbnoise>,
4940 L<Imager::Filters/radnoise>
4942 paste - L<Imager::Transformations/paste()>,
4943 L<Imager::Transformations/rubthrough()>
4945 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4946 L<Imager::ImageTypes/new()>
4948 =for stopwords posterize
4950 posterize - L<Imager::Filters/postlevels>
4952 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4954 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4956 rectangles, drawing - L<Imager::Draw/box()>
4958 resizing an image - L<Imager::Transformations/scale()>,
4959 L<Imager::Transformations/crop()>
4961 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4963 saving an image - L<Imager::Files>
4965 scaling - L<Imager::Transformations/scale()>
4967 security - L<Imager::Security>
4969 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4971 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4973 size, image - L<Imager::ImageTypes/getwidth()>,
4974 L<Imager::ImageTypes/getheight()>
4976 size, text - L<Imager::Font/bounding_box()>
4978 tags, image metadata - L<Imager::ImageTypes/"Tags">
4980 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4981 L<Imager::Font::Wrap>
4983 text, wrapping text in an area - L<Imager::Font::Wrap>
4985 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4987 threads - L<Imager::Threads>
4989 tiles, color - L<Imager::Filters/mosaic>
4991 transparent images - L<Imager::ImageTypes>,
4992 L<Imager::Cookbook/"Transparent PNG">
4994 =for stopwords unsharp
4996 unsharp mask - L<Imager::Filters/unsharpmask>
4998 watermark - L<Imager::Filters/watermark>
5000 writing an image to a file - L<Imager::Files>
5004 The best place to get help with Imager is the mailing list.
5006 To subscribe send a message with C<subscribe> in the body to:
5008 imager-devel+request@molar.is
5014 L<http://www.molar.is/en/lists/imager-devel/>
5018 where you can also find the mailing list archive.
5020 You can report bugs by pointing your browser at:
5024 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
5028 or by sending an email to:
5032 bug-Imager@rt.cpan.org
5036 Please remember to include the versions of Imager, perl, supporting
5037 libraries, and any relevant code. If you have specific images that
5038 cause the problems, please include those too.
5040 If you don't want to publish your email address on a mailing list you
5041 can use CPAN::Forum:
5043 http://www.cpanforum.com/dist/Imager
5045 You will need to register to post.
5047 =head1 CONTRIBUTING TO IMAGER
5053 If you like or dislike Imager, you can add a public review of Imager
5056 http://cpanratings.perl.org/dist/Imager
5058 =for stopwords Bitcard
5060 This requires a Bitcard account (http://www.bitcard.org).
5062 You can also send email to the maintainer below.
5064 If you send me a bug report via email, it will be copied to Request
5069 I accept patches, preferably against the master branch in git. Please
5070 include an explanation of the reason for why the patch is needed or
5073 Your patch should include regression tests where possible, otherwise
5074 it will be delayed until I get a chance to write them.
5076 To browse Imager's git repository:
5078 http://git.imager.perl.org/imager.git
5082 git clone git://git.imager.perl.org/imager.git
5084 My preference is that patches are provided in the format produced by
5085 C<git format-patch>, for example, if you made your changes in a branch
5086 from master you might do:
5088 git format-patch -k --stdout master >my-patch.txt
5090 and then attach that to your bug report, either by adding it as an
5091 attachment in your email client, or by using the Request Tracker
5092 attachment mechanism.
5096 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5098 Arnar M. Hrafnkelsson is the original author of Imager.
5100 Many others have contributed to Imager, please see the C<README> for a
5105 Imager is licensed under the same terms as perl itself.
5108 makeblendedfont Fontforge
5110 A test font, generated by the Debian packaged Fontforge,
5111 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5112 copyrighted by Adobe. See F<adobe.txt> in the source for license
5117 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5118 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5119 L<Imager::Font>(3), L<Imager::Transformations>(3),
5120 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5121 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5123 L<http://imager.perl.org/>
5125 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5127 Other perl imaging modules include:
5129 L<GD>(3), L<Image::Magick>(3),
5130 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
5131 L<Prima::Image>, L<IPA>.
5133 For manipulating image metadata see L<Image::ExifTool>.
5135 If you're trying to use Imager for array processing, you should
5136 probably using L<PDL>.