4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
113 # registered file readers
116 # registered file writers
119 # modules we attempted to autoload
120 my %attempted_to_load;
122 # library keys that are image file formats
123 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
125 # image pixel combine types
127 qw/none normal multiply dissolve add subtract diff lighten darken
128 hue saturation value color/;
130 @combine_types{@combine_types} = 0 .. $#combine_types;
131 $combine_types{mult} = $combine_types{multiply};
132 $combine_types{'sub'} = $combine_types{subtract};
133 $combine_types{sat} = $combine_types{saturation};
135 # this will be used to store global defaults at some point
140 my $ex_version = eval $Exporter::VERSION;
141 if ($ex_version < 5.57) {
147 XSLoader::load(Imager => $VERSION);
151 push @ISA, 'DynaLoader';
152 bootstrap Imager $VERSION;
159 png => "Imager::File::PNG",
160 gif => "Imager::File::GIF",
161 tiff => "Imager::File::TIFF",
162 jpeg => "Imager::File::JPEG",
163 w32 => "Imager::Font::W32",
164 ft2 => "Imager::Font::FT2",
165 t1 => "Imager::Font::T1",
168 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
171 for(i_list_formats()) { $formats_low{$_}++; }
173 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
177 # the members of the subhashes under %filters are:
178 # callseq - a list of the parameters to the underlying filter in the
179 # order they are passed
180 # callsub - a code ref that takes a named parameter list and calls the
182 # defaults - a hash of default values
183 # names - defines names for value of given parameters so if the names
184 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
185 # foo parameter, the filter will receive 1 for the foo
188 callseq => ['image','intensity'],
189 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
193 callseq => ['image', 'amount', 'subtype'],
194 defaults => { amount=>3,subtype=>0 },
195 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
198 $filters{hardinvert} ={
199 callseq => ['image'],
201 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
204 $filters{hardinvertall} =
206 callseq => ['image'],
208 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
211 $filters{autolevels} ={
212 callseq => ['image','lsat','usat','skew'],
213 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
214 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
217 $filters{turbnoise} ={
218 callseq => ['image'],
219 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
220 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
223 $filters{radnoise} ={
224 callseq => ['image'],
225 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
226 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
231 callseq => ['image', 'coef'],
236 i_conv($hsh{image},$hsh{coef})
237 or die Imager->_error_as_msg() . "\n";
243 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
244 defaults => { dist => 0 },
248 my @colors = @{$hsh{colors}};
251 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
255 $filters{nearest_color} =
257 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
262 # make sure the segments are specified with colors
264 for my $color (@{$hsh{colors}}) {
265 my $new_color = _color($color)
266 or die $Imager::ERRSTR."\n";
267 push @colors, $new_color;
270 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
272 or die Imager->_error_as_msg() . "\n";
275 $filters{gaussian} = {
276 callseq => [ 'image', 'stddev' ],
278 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
282 callseq => [ qw(image size) ],
283 defaults => { size => 20 },
284 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
288 callseq => [ qw(image bump elevation lightx lighty st) ],
289 defaults => { elevation=>0, st=> 2 },
292 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
293 $hsh{lightx}, $hsh{lighty}, $hsh{st});
296 $filters{bumpmap_complex} =
298 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
315 for my $cname (qw/Ia Il Is/) {
316 my $old = $hsh{$cname};
317 my $new_color = _color($old)
318 or die $Imager::ERRSTR, "\n";
319 $hsh{$cname} = $new_color;
321 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
322 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
323 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
327 $filters{postlevels} =
329 callseq => [ qw(image levels) ],
330 defaults => { levels => 10 },
331 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
333 $filters{watermark} =
335 callseq => [ qw(image wmark tx ty pixdiff) ],
336 defaults => { pixdiff=>10, tx=>0, ty=>0 },
340 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
346 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
348 ftype => { linear => 0,
354 repeat => { none => 0,
369 multiply => 2, mult => 2,
372 subtract => 5, 'sub' => 5,
382 defaults => { ftype => 0, repeat => 0, combine => 0,
383 super_sample => 0, ssample_param => 4,
396 # make sure the segments are specified with colors
398 for my $segment (@{$hsh{segments}}) {
399 my @new_segment = @$segment;
401 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
402 push @segments, \@new_segment;
405 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
406 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
407 $hsh{ssample_param}, \@segments)
408 or die Imager->_error_as_msg() . "\n";
411 $filters{unsharpmask} =
413 callseq => [ qw(image stddev scale) ],
414 defaults => { stddev=>2.0, scale=>1.0 },
418 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
422 $FORMATGUESS=\&def_guess_type;
432 # NOTE: this might be moved to an import override later on
437 if ($_[$i] eq '-log-stderr') {
445 goto &Exporter::import;
449 Imager->open_log(log => $_[0], level => $_[1]);
454 my %parms=(loglevel=>1,@_);
456 Imager->open_log(log => $parms{log}, level => $parms{loglevel});
459 if (exists $parms{'warn_obsolete'}) {
460 $warn_obsolete = $parms{'warn_obsolete'};
463 if (exists $parms{'t1log'}) {
465 Imager::Font::T1::i_init_t1($parms{'t1log'});
475 my (%opts) = ( loglevel => 1, @_ );
477 $is_logging = i_init_log($opts{log}, $opts{loglevel});
478 unless ($is_logging) {
479 Imager->_set_error(Imager->_error_as_msg());
483 Imager->log("Imager $VERSION starting\n", 1);
489 i_init_log(undef, -1);
494 my ($class, $message, $level) = @_;
496 defined $level or $level = 1;
498 i_log_entry($message, $level);
508 print "shutdown code\n";
509 # for(keys %instances) { $instances{$_}->DESTROY(); }
510 malloc_state(); # how do decide if this should be used? -- store something from the import
511 print "Imager exiting\n";
515 # Load a filter plugin
520 my ($DSO_handle,$str)=DSO_open($filename);
521 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
522 my %funcs=DSO_funclist($DSO_handle);
523 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
525 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
527 $DSOs{$filename}=[$DSO_handle,\%funcs];
530 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
531 $DEBUG && print "eval string:\n",$evstr,"\n";
543 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
544 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
545 for(keys %{$funcref}) {
547 $DEBUG && print "unloading: $_\n";
549 my $rc=DSO_close($DSO_handle);
550 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
554 # take the results of i_error() and make a message out of it
556 return join(": ", map $_->[0], i_errors());
559 # this function tries to DWIM for color parameters
560 # color objects are used as is
561 # simple scalars are simply treated as single parameters to Imager::Color->new
562 # hashrefs are treated as named argument lists to Imager::Color->new
563 # arrayrefs are treated as list arguments to Imager::Color->new iff any
565 # other arrayrefs are treated as list arguments to Imager::Color::Float
569 # perl 5.6.0 seems to do weird things to $arg if we don't make an
570 # explicitly stringified copy
571 # I vaguely remember a bug on this on p5p, but couldn't find it
572 # through bugs.perl.org (I had trouble getting it to find any bugs)
573 my $copy = $arg . "";
577 if (UNIVERSAL::isa($arg, "Imager::Color")
578 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
582 if ($copy =~ /^HASH\(/) {
583 $result = Imager::Color->new(%$arg);
585 elsif ($copy =~ /^ARRAY\(/) {
586 $result = Imager::Color->new(@$arg);
589 $Imager::ERRSTR = "Not a color";
594 # assume Imager::Color::new knows how to handle it
595 $result = Imager::Color->new($arg);
602 my ($self, $combine, $default) = @_;
604 if (!defined $combine && ref $self) {
605 $combine = $self->{combine};
607 defined $combine or $combine = $defaults{combine};
608 defined $combine or $combine = $default;
610 if (exists $combine_types{$combine}) {
611 $combine = $combine_types{$combine};
620 $self->{IMG} and return 1;
622 $self->_set_error('empty input image');
627 # returns first defined parameter
630 return $_ if defined $_;
636 # Methods to be called on objects.
639 # Create a new Imager object takes very few parameters.
640 # usually you call this method and then call open from
641 # the resulting object
648 $self->{IMG}=undef; # Just to indicate what exists
649 $self->{ERRSTR}=undef; #
650 $self->{DEBUG}=$DEBUG;
651 $self->{DEBUG} and print "Initialized Imager\n";
652 if (defined $hsh{xsize} || defined $hsh{ysize}) {
653 unless ($self->img_set(%hsh)) {
654 $Imager::ERRSTR = $self->{ERRSTR};
658 elsif (defined $hsh{file} ||
661 defined $hsh{callback} ||
662 defined $hsh{readcb} ||
663 defined $hsh{data}) {
664 # allow $img = Imager->new(file => $filename)
667 # type is already used as a parameter to new(), rename it for the
669 if ($hsh{filetype}) {
670 $extras{type} = $hsh{filetype};
672 unless ($self->read(%hsh, %extras)) {
673 $Imager::ERRSTR = $self->{ERRSTR};
681 # Copy an entire image with no changes
682 # - if an image has magic the copy of it will not be magical
686 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
688 unless (defined wantarray) {
690 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
694 my $newcopy=Imager->new();
695 $newcopy->{IMG} = i_copy($self->{IMG});
704 unless ($self->{IMG}) {
705 $self->_set_error('empty input image');
708 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
709 my $src = $input{img} || $input{src};
711 $self->_set_error("no source image");
714 $input{left}=0 if $input{left} <= 0;
715 $input{top}=0 if $input{top} <= 0;
717 my($r,$b)=i_img_info($src->{IMG});
718 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
719 my ($src_right, $src_bottom);
720 if ($input{src_coords}) {
721 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
724 if (defined $input{src_maxx}) {
725 $src_right = $input{src_maxx};
727 elsif (defined $input{width}) {
728 if ($input{width} <= 0) {
729 $self->_set_error("paste: width must me positive");
732 $src_right = $src_left + $input{width};
737 if (defined $input{src_maxy}) {
738 $src_bottom = $input{src_maxy};
740 elsif (defined $input{height}) {
741 if ($input{height} < 0) {
742 $self->_set_error("paste: height must be positive");
745 $src_bottom = $src_top + $input{height};
752 $src_right > $r and $src_right = $r;
753 $src_bottom > $b and $src_bottom = $b;
755 if ($src_right <= $src_left
756 || $src_bottom < $src_top) {
757 $self->_set_error("nothing to paste");
761 i_copyto($self->{IMG}, $src->{IMG},
762 $src_left, $src_top, $src_right, $src_bottom,
763 $input{left}, $input{top});
765 return $self; # What should go here??
768 # Crop an image - i.e. return a new image that is smaller
772 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
774 unless (defined wantarray) {
776 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
782 my ($w, $h, $l, $r, $b, $t) =
783 @hsh{qw(width height left right bottom top)};
785 # work through the various possibilities
790 elsif (!defined $r) {
791 $r = $self->getwidth;
803 $l = int(0.5+($self->getwidth()-$w)/2);
808 $r = $self->getwidth;
814 elsif (!defined $b) {
815 $b = $self->getheight;
827 $t=int(0.5+($self->getheight()-$h)/2);
832 $b = $self->getheight;
835 ($l,$r)=($r,$l) if $l>$r;
836 ($t,$b)=($b,$t) if $t>$b;
839 $r > $self->getwidth and $r = $self->getwidth;
841 $b > $self->getheight and $b = $self->getheight;
843 if ($l == $r || $t == $b) {
844 $self->_set_error("resulting image would have no content");
847 if( $r < $l or $b < $t ) {
848 $self->_set_error("attempting to crop outside of the image");
851 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
853 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
858 my ($self, %opts) = @_;
860 $self->{IMG} or return $self->_set_error("Not a valid image");
862 my $x = $opts{xsize} || $self->getwidth;
863 my $y = $opts{ysize} || $self->getheight;
864 my $channels = $opts{channels} || $self->getchannels;
866 my $out = Imager->new;
867 if ($channels == $self->getchannels) {
868 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
871 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
873 unless ($out->{IMG}) {
874 $self->{ERRSTR} = $self->_error_as_msg;
881 # Sets an image to a certain size and channel number
882 # if there was previously data in the image it is discarded
887 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
889 if (defined($self->{IMG})) {
890 # let IIM_DESTROY destroy it, it's possible this image is
891 # referenced from a virtual image (like masked)
892 #i_img_destroy($self->{IMG});
896 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
897 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
898 $hsh{maxcolors} || 256);
900 elsif ($hsh{bits} eq 'double') {
901 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
903 elsif ($hsh{bits} == 16) {
904 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
907 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
911 unless ($self->{IMG}) {
912 $self->{ERRSTR} = Imager->_error_as_msg();
919 # created a masked version of the current image
923 $self or return undef;
924 my %opts = (left => 0,
926 right => $self->getwidth,
927 bottom => $self->getheight,
929 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
931 my $result = Imager->new;
932 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
933 $opts{top}, $opts{right} - $opts{left},
934 $opts{bottom} - $opts{top});
935 unless ($result->{IMG}) {
936 $self->_set_error(Imager->_error_as_msg);
940 # keep references to the mask and base images so they don't
942 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
947 # convert an RGB image into a paletted image
951 if (@_ != 1 && !ref $_[0]) {
958 unless (defined wantarray) {
960 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
967 my $result = Imager->new;
968 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
969 $self->_set_error(Imager->_error_as_msg);
976 # convert a paletted (or any image) to an 8-bit/channel RGB image
980 unless (defined wantarray) {
982 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
989 my $result = Imager->new;
990 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
991 $self->_set_error(Imager->_error_as_msg());
998 # convert a paletted (or any image) to a 16-bit/channel RGB image
1002 unless (defined wantarray) {
1003 my @caller = caller;
1004 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1011 my $result = Imager->new;
1012 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1013 $self->_set_error(Imager->_error_as_msg());
1020 # convert a paletted (or any image) to an double/channel RGB image
1024 unless (defined wantarray) {
1025 my @caller = caller;
1026 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1033 my $result = Imager->new;
1034 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1035 $self->_set_error(Imager->_error_as_msg());
1044 my %opts = (colors=>[], @_);
1046 unless ($self->{IMG}) {
1047 $self->_set_error("empty input image");
1051 my @colors = @{$opts{colors}}
1054 for my $color (@colors) {
1055 $color = _color($color);
1057 $self->_set_error($Imager::ERRSTR);
1062 return i_addcolors($self->{IMG}, @colors);
1067 my %opts = (start=>0, colors=>[], @_);
1069 unless ($self->{IMG}) {
1070 $self->_set_error("empty input image");
1074 my @colors = @{$opts{colors}}
1077 for my $color (@colors) {
1078 $color = _color($color);
1080 $self->_set_error($Imager::ERRSTR);
1085 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1091 if (!exists $opts{start} && !exists $opts{count}) {
1094 $opts{count} = $self->colorcount;
1096 elsif (!exists $opts{count}) {
1099 elsif (!exists $opts{start}) {
1104 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1108 i_colorcount($_[0]{IMG});
1112 i_maxcolors($_[0]{IMG});
1118 $opts{color} or return undef;
1120 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1125 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1126 if ($bits && $bits == length(pack("d", 1)) * 8) {
1135 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1141 $self->{IMG} and i_img_virtual($self->{IMG});
1147 $self->{IMG} or return;
1149 return i_img_is_monochrome($self->{IMG});
1153 my ($self, %opts) = @_;
1155 $self->{IMG} or return;
1157 if (defined $opts{name}) {
1161 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1162 push @result, (i_tags_get($self->{IMG}, $found))[1];
1165 return wantarray ? @result : $result[0];
1167 elsif (defined $opts{code}) {
1171 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1172 push @result, (i_tags_get($self->{IMG}, $found))[1];
1179 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1182 return i_tags_count($self->{IMG});
1191 return -1 unless $self->{IMG};
1193 if (defined $opts{value}) {
1194 if ($opts{value} =~ /^\d+$/) {
1196 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1199 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1202 elsif (defined $opts{data}) {
1203 # force addition as a string
1204 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1207 $self->{ERRSTR} = "No value supplied";
1211 elsif ($opts{code}) {
1212 if (defined $opts{value}) {
1213 if ($opts{value} =~ /^\d+$/) {
1215 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1218 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1221 elsif (defined $opts{data}) {
1222 # force addition as a string
1223 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1226 $self->{ERRSTR} = "No value supplied";
1239 return 0 unless $self->{IMG};
1241 if (defined $opts{'index'}) {
1242 return i_tags_delete($self->{IMG}, $opts{'index'});
1244 elsif (defined $opts{name}) {
1245 return i_tags_delbyname($self->{IMG}, $opts{name});
1247 elsif (defined $opts{code}) {
1248 return i_tags_delbycode($self->{IMG}, $opts{code});
1251 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1257 my ($self, %opts) = @_;
1260 $self->deltag(name=>$opts{name});
1261 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1263 elsif (defined $opts{code}) {
1264 $self->deltag(code=>$opts{code});
1265 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1273 sub _get_reader_io {
1274 my ($self, $input) = @_;
1277 return $input->{io}, undef;
1279 elsif ($input->{fd}) {
1280 return io_new_fd($input->{fd});
1282 elsif ($input->{fh}) {
1283 my $fd = fileno($input->{fh});
1284 unless (defined $fd) {
1285 $self->_set_error("Handle in fh option not opened");
1288 return io_new_fd($fd);
1290 elsif ($input->{file}) {
1291 my $file = IO::File->new($input->{file}, "r");
1293 $self->_set_error("Could not open $input->{file}: $!");
1297 return (io_new_fd(fileno($file)), $file);
1299 elsif ($input->{data}) {
1300 return io_new_buffer($input->{data});
1302 elsif ($input->{callback} || $input->{readcb}) {
1303 if (!$input->{seekcb}) {
1304 $self->_set_error("Need a seekcb parameter");
1306 if ($input->{maxbuffer}) {
1307 return io_new_cb($input->{writecb},
1308 $input->{callback} || $input->{readcb},
1309 $input->{seekcb}, $input->{closecb},
1310 $input->{maxbuffer});
1313 return io_new_cb($input->{writecb},
1314 $input->{callback} || $input->{readcb},
1315 $input->{seekcb}, $input->{closecb});
1319 $self->_set_error("file/fd/fh/data/callback parameter missing");
1324 sub _get_writer_io {
1325 my ($self, $input, $type) = @_;
1328 return $input->{io};
1330 elsif ($input->{fd}) {
1331 return io_new_fd($input->{fd});
1333 elsif ($input->{fh}) {
1334 my $fd = fileno($input->{fh});
1335 unless (defined $fd) {
1336 $self->_set_error("Handle in fh option not opened");
1340 my $oldfh = select($input->{fh});
1341 # flush anything that's buffered, and make sure anything else is flushed
1344 return io_new_fd($fd);
1346 elsif ($input->{file}) {
1347 my $fh = new IO::File($input->{file},"w+");
1349 $self->_set_error("Could not open file $input->{file}: $!");
1352 binmode($fh) or die;
1353 return (io_new_fd(fileno($fh)), $fh);
1355 elsif ($input->{data}) {
1356 return io_new_bufchain();
1358 elsif ($input->{callback} || $input->{writecb}) {
1359 if ($input->{maxbuffer}) {
1360 return io_new_cb($input->{callback} || $input->{writecb},
1362 $input->{seekcb}, $input->{closecb},
1363 $input->{maxbuffer});
1366 return io_new_cb($input->{callback} || $input->{writecb},
1368 $input->{seekcb}, $input->{closecb});
1372 $self->_set_error("file/fd/fh/data/callback parameter missing");
1377 # Read an image from file
1383 if (defined($self->{IMG})) {
1384 # let IIM_DESTROY do the destruction, since the image may be
1385 # referenced from elsewhere
1386 #i_img_destroy($self->{IMG});
1387 undef($self->{IMG});
1390 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1392 unless ($input{'type'}) {
1393 $input{'type'} = i_test_format_probe($IO, -1);
1396 unless ($input{'type'}) {
1397 $self->_set_error('type parameter missing and not possible to guess from extension');
1401 _reader_autoload($input{type});
1403 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1404 return $readers{$input{type}}{single}->($self, $IO, %input);
1407 unless ($formats_low{$input{'type'}}) {
1408 my $read_types = join ', ', sort Imager->read_types();
1409 $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading");
1413 my $allow_incomplete = $input{allow_incomplete};
1414 defined $allow_incomplete or $allow_incomplete = 0;
1416 if ( $input{'type'} eq 'pnm' ) {
1417 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1418 if ( !defined($self->{IMG}) ) {
1419 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1422 $self->{DEBUG} && print "loading a pnm file\n";
1426 if ( $input{'type'} eq 'bmp' ) {
1427 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1428 if ( !defined($self->{IMG}) ) {
1429 $self->{ERRSTR}=$self->_error_as_msg();
1432 $self->{DEBUG} && print "loading a bmp file\n";
1435 if ( $input{'type'} eq 'gif' ) {
1436 if ($input{colors} && !ref($input{colors})) {
1437 # must be a reference to a scalar that accepts the colour map
1438 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1441 if ($input{'gif_consolidate'}) {
1442 if ($input{colors}) {
1444 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1446 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1450 $self->{IMG} =i_readgif_wiol( $IO );
1454 my $page = $input{'page'};
1455 defined $page or $page = 0;
1456 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1457 if ($self->{IMG} && $input{colors}) {
1458 ${ $input{colors} } =
1459 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1463 if ( !defined($self->{IMG}) ) {
1464 $self->{ERRSTR}=$self->_error_as_msg();
1467 $self->{DEBUG} && print "loading a gif file\n";
1470 if ( $input{'type'} eq 'tga' ) {
1471 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1472 if ( !defined($self->{IMG}) ) {
1473 $self->{ERRSTR}=$self->_error_as_msg();
1476 $self->{DEBUG} && print "loading a tga file\n";
1479 if ( $input{'type'} eq 'raw' ) {
1480 unless ( $input{xsize} && $input{ysize} ) {
1481 $self->_set_error('missing xsize or ysize parameter for raw');
1485 my $interleave = _first($input{raw_interleave}, $input{interleave});
1486 unless (defined $interleave) {
1487 my @caller = caller;
1488 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1491 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1492 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1494 $self->{IMG} = i_readraw_wiol( $IO,
1500 if ( !defined($self->{IMG}) ) {
1501 $self->{ERRSTR}=$self->_error_as_msg();
1504 $self->{DEBUG} && print "loading a raw file\n";
1510 sub register_reader {
1511 my ($class, %opts) = @_;
1514 or die "register_reader called with no type parameter\n";
1516 my $type = $opts{type};
1518 defined $opts{single} || defined $opts{multiple}
1519 or die "register_reader called with no single or multiple parameter\n";
1521 $readers{$type} = { };
1522 if ($opts{single}) {
1523 $readers{$type}{single} = $opts{single};
1525 if ($opts{multiple}) {
1526 $readers{$type}{multiple} = $opts{multiple};
1532 sub register_writer {
1533 my ($class, %opts) = @_;
1536 or die "register_writer called with no type parameter\n";
1538 my $type = $opts{type};
1540 defined $opts{single} || defined $opts{multiple}
1541 or die "register_writer called with no single or multiple parameter\n";
1543 $writers{$type} = { };
1544 if ($opts{single}) {
1545 $writers{$type}{single} = $opts{single};
1547 if ($opts{multiple}) {
1548 $writers{$type}{multiple} = $opts{multiple};
1559 grep($file_formats{$_}, keys %formats),
1560 qw(ico sgi), # formats not handled directly, but supplied with Imager
1571 grep($file_formats{$_}, keys %formats),
1572 qw(ico sgi), # formats not handled directly, but supplied with Imager
1578 # probes for an Imager::File::whatever module
1579 sub _reader_autoload {
1582 return if $formats_low{$type} || $readers{$type};
1584 return unless $type =~ /^\w+$/;
1586 my $file = "Imager/File/\U$type\E.pm";
1588 unless ($attempted_to_load{$file}) {
1590 ++$attempted_to_load{$file};
1594 # try to get a reader specific module
1595 my $file = "Imager/File/\U$type\EReader.pm";
1596 unless ($attempted_to_load{$file}) {
1598 ++$attempted_to_load{$file};
1606 # probes for an Imager::File::whatever module
1607 sub _writer_autoload {
1610 return if $formats_low{$type} || $readers{$type};
1612 return unless $type =~ /^\w+$/;
1614 my $file = "Imager/File/\U$type\E.pm";
1616 unless ($attempted_to_load{$file}) {
1618 ++$attempted_to_load{$file};
1622 # try to get a writer specific module
1623 my $file = "Imager/File/\U$type\EWriter.pm";
1624 unless ($attempted_to_load{$file}) {
1626 ++$attempted_to_load{$file};
1634 sub _fix_gif_positions {
1635 my ($opts, $opt, $msg, @imgs) = @_;
1637 my $positions = $opts->{'gif_positions'};
1639 for my $pos (@$positions) {
1640 my ($x, $y) = @$pos;
1641 my $img = $imgs[$index++];
1642 $img->settag(name=>'gif_left', value=>$x);
1643 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1645 $$msg .= "replaced with the gif_left and gif_top tags";
1650 gif_each_palette=>'gif_local_map',
1651 interlace => 'gif_interlace',
1652 gif_delays => 'gif_delay',
1653 gif_positions => \&_fix_gif_positions,
1654 gif_loop_count => 'gif_loop',
1657 # options that should be converted to colors
1658 my %color_opts = map { $_ => 1 } qw/i_background/;
1661 my ($self, $opts, $prefix, @imgs) = @_;
1663 for my $opt (keys %$opts) {
1665 if ($obsolete_opts{$opt}) {
1666 my $new = $obsolete_opts{$opt};
1667 my $msg = "Obsolete option $opt ";
1669 $new->($opts, $opt, \$msg, @imgs);
1672 $msg .= "replaced with the $new tag ";
1675 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1676 warn $msg if $warn_obsolete && $^W;
1678 next unless $tagname =~ /^\Q$prefix/;
1679 my $value = $opts->{$opt};
1680 if ($color_opts{$opt}) {
1681 $value = _color($value);
1683 $self->_set_error($Imager::ERRSTR);
1688 if (UNIVERSAL::isa($value, "Imager::Color")) {
1689 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1690 for my $img (@imgs) {
1691 $img->settag(name=>$tagname, value=>$tag);
1694 elsif (ref($value) eq 'ARRAY') {
1695 for my $i (0..$#$value) {
1696 my $val = $value->[$i];
1698 if (UNIVERSAL::isa($val, "Imager::Color")) {
1699 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1701 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1704 $self->_set_error("Unknown reference type " . ref($value) .
1705 " supplied in array for $opt");
1711 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1716 $self->_set_error("Unknown reference type " . ref($value) .
1717 " supplied for $opt");
1722 # set it as a tag for every image
1723 for my $img (@imgs) {
1724 $img->settag(name=>$tagname, value=>$value);
1732 # Write an image to file
1735 my %input=(jpegquality=>75,
1745 $self->_set_opts(\%input, "i_", $self)
1748 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1750 if (!$input{'type'} and $input{file}) {
1751 $input{'type'}=$FORMATGUESS->($input{file});
1753 if (!$input{'type'}) {
1754 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1758 _writer_autoload($input{type});
1761 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1762 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1765 $writers{$input{type}}{single}->($self, $IO, %input)
1769 if (!$formats_low{$input{'type'}}) {
1770 my $write_types = join ', ', sort Imager->write_types();
1771 $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing");
1775 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1778 if ( $input{'type'} eq 'pnm' ) {
1779 $self->_set_opts(\%input, "pnm_", $self)
1781 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1782 $self->{ERRSTR} = $self->_error_as_msg();
1785 $self->{DEBUG} && print "writing a pnm file\n";
1786 } elsif ( $input{'type'} eq 'raw' ) {
1787 $self->_set_opts(\%input, "raw_", $self)
1789 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1790 $self->{ERRSTR} = $self->_error_as_msg();
1793 $self->{DEBUG} && print "writing a raw file\n";
1794 } elsif ( $input{'type'} eq 'jpeg' ) {
1795 $self->_set_opts(\%input, "jpeg_", $self)
1797 $self->_set_opts(\%input, "exif_", $self)
1799 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1800 $self->{ERRSTR} = $self->_error_as_msg();
1803 $self->{DEBUG} && print "writing a jpeg file\n";
1804 } elsif ( $input{'type'} eq 'bmp' ) {
1805 $self->_set_opts(\%input, "bmp_", $self)
1807 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1808 $self->{ERRSTR} = $self->_error_as_msg;
1811 $self->{DEBUG} && print "writing a bmp file\n";
1812 } elsif ( $input{'type'} eq 'tga' ) {
1813 $self->_set_opts(\%input, "tga_", $self)
1816 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1817 $self->{ERRSTR}=$self->_error_as_msg();
1820 $self->{DEBUG} && print "writing a tga file\n";
1821 } elsif ( $input{'type'} eq 'gif' ) {
1822 $self->_set_opts(\%input, "gif_", $self)
1824 # compatibility with the old interfaces
1825 if ($input{gifquant} eq 'lm') {
1826 $input{make_colors} = 'addi';
1827 $input{translate} = 'perturb';
1828 $input{perturb} = $input{lmdither};
1829 } elsif ($input{gifquant} eq 'gen') {
1830 # just pass options through
1832 $input{make_colors} = 'webmap'; # ignored
1833 $input{translate} = 'giflib';
1835 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1836 $self->{ERRSTR} = $self->_error_as_msg;
1842 if (exists $input{'data'}) {
1843 my $data = io_slurp($IO);
1845 $self->{ERRSTR}='Could not slurp from buffer';
1848 ${$input{data}} = $data;
1854 my ($class, $opts, @images) = @_;
1856 my $type = $opts->{type};
1858 if (!$type && $opts->{'file'}) {
1859 $type = $FORMATGUESS->($opts->{'file'});
1862 $class->_set_error('type parameter missing and not possible to guess from extension');
1865 # translate to ImgRaw
1866 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1867 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1870 $class->_set_opts($opts, "i_", @images)
1872 my @work = map $_->{IMG}, @images;
1874 _writer_autoload($type);
1877 if ($writers{$type} && $writers{$type}{multiple}) {
1878 ($IO, $file) = $class->_get_writer_io($opts, $type)
1881 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1885 if (!$formats{$type}) {
1886 my $write_types = join ', ', sort Imager->write_types();
1887 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1891 ($IO, $file) = $class->_get_writer_io($opts, $type)
1894 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1898 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1903 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1909 if (exists $opts->{'data'}) {
1910 my $data = io_slurp($IO);
1912 Imager->_set_error('Could not slurp from buffer');
1915 ${$opts->{data}} = $data;
1920 # read multiple images from a file
1922 my ($class, %opts) = @_;
1924 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1927 my $type = $opts{'type'};
1929 $type = i_test_format_probe($IO, -1);
1932 if ($opts{file} && !$type) {
1934 $type = $FORMATGUESS->($opts{file});
1938 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1942 _reader_autoload($type);
1944 if ($readers{$type} && $readers{$type}{multiple}) {
1945 return $readers{$type}{multiple}->($IO, %opts);
1948 unless ($formats{$type}) {
1949 my $read_types = join ', ', sort Imager->read_types();
1950 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1955 if ($type eq 'pnm') {
1956 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1959 my $img = Imager->new;
1960 if ($img->read(%opts, io => $IO, type => $type)) {
1963 Imager->_set_error($img->errstr);
1968 $ERRSTR = _error_as_msg();
1972 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1976 # Destroy an Imager object
1980 # delete $instances{$self};
1981 if (defined($self->{IMG})) {
1982 # the following is now handled by the XS DESTROY method for
1983 # Imager::ImgRaw object
1984 # Re-enabling this will break virtual images
1985 # tested for in t/t020masked.t
1986 # i_img_destroy($self->{IMG});
1987 undef($self->{IMG});
1989 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1993 # Perform an inplace filter of an image
1994 # that is the image will be overwritten with the data
2000 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2002 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2004 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2005 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2008 if ($filters{$input{'type'}}{names}) {
2009 my $names = $filters{$input{'type'}}{names};
2010 for my $name (keys %$names) {
2011 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2012 $input{$name} = $names->{$name}{$input{$name}};
2016 if (defined($filters{$input{'type'}}{defaults})) {
2017 %hsh=( image => $self->{IMG},
2019 %{$filters{$input{'type'}}{defaults}},
2022 %hsh=( image => $self->{IMG},
2027 my @cs=@{$filters{$input{'type'}}{callseq}};
2030 if (!defined($hsh{$_})) {
2031 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2036 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2037 &{$filters{$input{'type'}}{callsub}}(%hsh);
2040 chomp($self->{ERRSTR} = $@);
2046 $self->{DEBUG} && print "callseq is: @cs\n";
2047 $self->{DEBUG} && print "matching callseq is: @b\n";
2052 sub register_filter {
2054 my %hsh = ( defaults => {}, @_ );
2057 or die "register_filter() with no type\n";
2058 defined $hsh{callsub}
2059 or die "register_filter() with no callsub\n";
2060 defined $hsh{callseq}
2061 or die "register_filter() with no callseq\n";
2063 exists $filters{$hsh{type}}
2066 $filters{$hsh{type}} = \%hsh;
2071 sub scale_calculate {
2074 my %opts = ('type'=>'max', @_);
2076 # none of these should be references
2077 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2078 if (defined $opts{$name} && ref $opts{$name}) {
2079 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2084 my ($x_scale, $y_scale);
2085 my $width = $opts{width};
2086 my $height = $opts{height};
2088 defined $width or $width = $self->getwidth;
2089 defined $height or $height = $self->getheight;
2092 unless (defined $width && defined $height) {
2093 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2098 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2099 $x_scale = $opts{'xscalefactor'};
2100 $y_scale = $opts{'yscalefactor'};
2102 elsif ($opts{'xscalefactor'}) {
2103 $x_scale = $opts{'xscalefactor'};
2104 $y_scale = $opts{'scalefactor'} || $x_scale;
2106 elsif ($opts{'yscalefactor'}) {
2107 $y_scale = $opts{'yscalefactor'};
2108 $x_scale = $opts{'scalefactor'} || $y_scale;
2111 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2114 # work out the scaling
2115 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2116 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2117 $opts{ypixels} / $height );
2118 if ($opts{'type'} eq 'min') {
2119 $x_scale = $y_scale = _min($xpix,$ypix);
2121 elsif ($opts{'type'} eq 'max') {
2122 $x_scale = $y_scale = _max($xpix,$ypix);
2124 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2129 $self->_set_error('invalid value for type parameter');
2132 } elsif ($opts{xpixels}) {
2133 $x_scale = $y_scale = $opts{xpixels} / $width;
2135 elsif ($opts{ypixels}) {
2136 $x_scale = $y_scale = $opts{ypixels}/$height;
2138 elsif ($opts{constrain} && ref $opts{constrain}
2139 && $opts{constrain}->can('constrain')) {
2140 # we've been passed an Image::Math::Constrain object or something
2141 # that looks like one
2143 (undef, undef, $scalefactor)
2144 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2145 unless ($scalefactor) {
2146 $self->_set_error('constrain method failed on constrain parameter');
2149 $x_scale = $y_scale = $scalefactor;
2152 my $new_width = int($x_scale * $width + 0.5);
2153 $new_width > 0 or $new_width = 1;
2154 my $new_height = int($y_scale * $height + 0.5);
2155 $new_height > 0 or $new_height = 1;
2157 return ($x_scale, $y_scale, $new_width, $new_height);
2161 # Scale an image to requested size and return the scaled version
2165 my %opts = (qtype=>'normal' ,@_);
2166 my $img = Imager->new();
2167 my $tmp = Imager->new();
2169 unless (defined wantarray) {
2170 my @caller = caller;
2171 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2175 unless ($self->{IMG}) {
2176 $self->_set_error('empty input image');
2180 my ($x_scale, $y_scale, $new_width, $new_height) =
2181 $self->scale_calculate(%opts)
2184 if ($opts{qtype} eq 'normal') {
2185 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2186 if ( !defined($tmp->{IMG}) ) {
2187 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2190 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2191 if ( !defined($img->{IMG}) ) {
2192 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2198 elsif ($opts{'qtype'} eq 'preview') {
2199 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2200 if ( !defined($img->{IMG}) ) {
2201 $self->{ERRSTR}='unable to scale image';
2206 elsif ($opts{'qtype'} eq 'mixing') {
2207 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2208 unless ($img->{IMG}) {
2209 $self->_set_error(Imager->_error_as_msg);
2215 $self->_set_error('invalid value for qtype parameter');
2220 # Scales only along the X axis
2224 my %opts = ( scalefactor=>0.5, @_ );
2226 unless (defined wantarray) {
2227 my @caller = caller;
2228 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2232 unless ($self->{IMG}) {
2233 $self->{ERRSTR} = 'empty input image';
2237 my $img = Imager->new();
2239 my $scalefactor = $opts{scalefactor};
2241 if ($opts{pixels}) {
2242 $scalefactor = $opts{pixels} / $self->getwidth();
2245 unless ($self->{IMG}) {
2246 $self->{ERRSTR}='empty input image';
2250 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2252 if ( !defined($img->{IMG}) ) {
2253 $self->{ERRSTR} = 'unable to scale image';
2260 # Scales only along the Y axis
2264 my %opts = ( scalefactor => 0.5, @_ );
2266 unless (defined wantarray) {
2267 my @caller = caller;
2268 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2272 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2274 my $img = Imager->new();
2276 my $scalefactor = $opts{scalefactor};
2278 if ($opts{pixels}) {
2279 $scalefactor = $opts{pixels} / $self->getheight();
2282 unless ($self->{IMG}) {
2283 $self->{ERRSTR} = 'empty input image';
2286 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2288 if ( !defined($img->{IMG}) ) {
2289 $self->{ERRSTR} = 'unable to scale image';
2296 # Transform returns a spatial transformation of the input image
2297 # this moves pixels to a new location in the returned image.
2298 # NOTE - should make a utility function to check transforms for
2303 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2305 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2307 # print Dumper(\%opts);
2310 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2312 eval ("use Affix::Infix2Postfix;");
2315 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2318 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2319 {op=>'-',trans=>'Sub'},
2320 {op=>'*',trans=>'Mult'},
2321 {op=>'/',trans=>'Div'},
2322 {op=>'-','type'=>'unary',trans=>'u-'},
2324 {op=>'func','type'=>'unary'}],
2325 'grouping'=>[qw( \( \) )],
2326 'func'=>[qw( sin cos )],
2331 @xt=$I2P->translate($opts{'xexpr'});
2332 @yt=$I2P->translate($opts{'yexpr'});
2334 $numre=$I2P->{'numre'};
2337 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2338 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2339 @{$opts{'parm'}}=@pt;
2342 # print Dumper(\%opts);
2344 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2345 $self->{ERRSTR}='transform: no xopcodes given.';
2349 @op=@{$opts{'xopcodes'}};
2351 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2352 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2355 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2361 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2362 $self->{ERRSTR}='transform: no yopcodes given.';
2366 @op=@{$opts{'yopcodes'}};
2368 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2369 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2372 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2377 if ( !exists $opts{'parm'}) {
2378 $self->{ERRSTR}='transform: no parameter arg given.';
2382 # print Dumper(\@ropx);
2383 # print Dumper(\@ropy);
2384 # print Dumper(\@ropy);
2386 my $img = Imager->new();
2387 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2388 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2394 my ($opts, @imgs) = @_;
2396 require "Imager/Expr.pm";
2398 $opts->{variables} = [ qw(x y) ];
2399 my ($width, $height) = @{$opts}{qw(width height)};
2401 $width ||= $imgs[0]->getwidth();
2402 $height ||= $imgs[0]->getheight();
2404 for my $img (@imgs) {
2405 $opts->{constants}{"w$img_num"} = $img->getwidth();
2406 $opts->{constants}{"h$img_num"} = $img->getheight();
2407 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2408 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2413 $opts->{constants}{w} = $width;
2414 $opts->{constants}{cx} = $width/2;
2417 $Imager::ERRSTR = "No width supplied";
2421 $opts->{constants}{h} = $height;
2422 $opts->{constants}{cy} = $height/2;
2425 $Imager::ERRSTR = "No height supplied";
2428 my $code = Imager::Expr->new($opts);
2430 $Imager::ERRSTR = Imager::Expr::error();
2433 my $channels = $opts->{channels} || 3;
2434 unless ($channels >= 1 && $channels <= 4) {
2435 return Imager->_set_error("channels must be an integer between 1 and 4");
2438 my $img = Imager->new();
2439 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2440 $channels, $code->code(),
2441 $code->nregs(), $code->cregs(),
2442 [ map { $_->{IMG} } @imgs ]);
2443 if (!defined $img->{IMG}) {
2444 $Imager::ERRSTR = Imager->_error_as_msg();
2455 unless ($self->{IMG}) {
2456 $self->{ERRSTR}='empty input image';
2459 unless ($opts{src} && $opts{src}->{IMG}) {
2460 $self->{ERRSTR}='empty input image for src';
2464 %opts = (src_minx => 0,
2466 src_maxx => $opts{src}->getwidth(),
2467 src_maxy => $opts{src}->getheight(),
2471 defined $tx or $tx = $opts{left};
2472 defined $tx or $tx = 0;
2475 defined $ty or $ty = $opts{top};
2476 defined $ty or $ty = 0;
2478 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2479 $opts{src_minx}, $opts{src_miny},
2480 $opts{src_maxx}, $opts{src_maxy})) {
2481 $self->_set_error($self->_error_as_msg());
2498 unless ($self->{IMG}) {
2499 $self->_set_error("compose: empty input image");
2503 unless ($opts{src}) {
2504 $self->_set_error("compose: src parameter missing");
2508 unless ($opts{src}{IMG}) {
2509 $self->_set_error("compose: src parameter empty image");
2512 my $src = $opts{src};
2514 my $left = $opts{left};
2515 defined $left or $left = $opts{tx};
2516 defined $left or $left = 0;
2518 my $top = $opts{top};
2519 defined $top or $top = $opts{ty};
2520 defined $top or $top = 0;
2522 my $src_left = $opts{src_left};
2523 defined $src_left or $src_left = $opts{src_minx};
2524 defined $src_left or $src_left = 0;
2526 my $src_top = $opts{src_top};
2527 defined $src_top or $src_top = $opts{src_miny};
2528 defined $src_top or $src_top = 0;
2530 my $width = $opts{width};
2531 if (!defined $width && defined $opts{src_maxx}) {
2532 $width = $opts{src_maxx} - $src_left;
2534 defined $width or $width = $src->getwidth() - $src_left;
2536 my $height = $opts{height};
2537 if (!defined $height && defined $opts{src_maxy}) {
2538 $height = $opts{src_maxy} - $src_top;
2540 defined $height or $height = $src->getheight() - $src_top;
2542 my $combine = $self->_combine($opts{combine}, 'normal');
2545 unless ($opts{mask}{IMG}) {
2546 $self->_set_error("compose: mask parameter empty image");
2550 my $mask_left = $opts{mask_left};
2551 defined $mask_left or $mask_left = $opts{mask_minx};
2552 defined $mask_left or $mask_left = 0;
2554 my $mask_top = $opts{mask_top};
2555 defined $mask_top or $mask_top = $opts{mask_miny};
2556 defined $mask_top or $mask_top = 0;
2558 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2559 $left, $top, $src_left, $src_top,
2560 $mask_left, $mask_top, $width, $height,
2561 $combine, $opts{opacity})) {
2562 $self->_set_error(Imager->_error_as_msg);
2567 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2568 $width, $height, $combine, $opts{opacity})) {
2569 $self->_set_error(Imager->_error_as_msg);
2580 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2582 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2583 $dir = $xlate{$opts{'dir'}};
2584 return $self if i_flipxy($self->{IMG}, $dir);
2592 unless (defined wantarray) {
2593 my @caller = caller;
2594 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2598 if (defined $opts{right}) {
2599 my $degrees = $opts{right};
2601 $degrees += 360 * int(((-$degrees)+360)/360);
2603 $degrees = $degrees % 360;
2604 if ($degrees == 0) {
2605 return $self->copy();
2607 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2608 my $result = Imager->new();
2609 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2613 $self->{ERRSTR} = $self->_error_as_msg();
2618 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2622 elsif (defined $opts{radians} || defined $opts{degrees}) {
2623 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2625 my $back = $opts{back};
2626 my $result = Imager->new;
2628 $back = _color($back);
2630 $self->_set_error(Imager->errstr);
2634 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2637 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2639 if ($result->{IMG}) {
2643 $self->{ERRSTR} = $self->_error_as_msg();
2648 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2653 sub matrix_transform {
2657 unless (defined wantarray) {
2658 my @caller = caller;
2659 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2663 if ($opts{matrix}) {
2664 my $xsize = $opts{xsize} || $self->getwidth;
2665 my $ysize = $opts{ysize} || $self->getheight;
2667 my $result = Imager->new;
2669 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2670 $opts{matrix}, $opts{back})
2674 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2682 $self->{ERRSTR} = "matrix parameter required";
2688 *yatf = \&matrix_transform;
2690 # These two are supported for legacy code only
2693 return Imager::Color->new(@_);
2697 return Imager::Color::set(@_);
2700 # Draws a box between the specified corner points.
2703 my $raw = $self->{IMG};
2706 $self->{ERRSTR}='empty input image';
2712 my ($xmin, $ymin, $xmax, $ymax);
2713 if (exists $opts{'box'}) {
2714 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2715 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2716 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2717 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2720 defined($xmin = $opts{xmin}) or $xmin = 0;
2721 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2722 defined($ymin = $opts{ymin}) or $ymin = 0;
2723 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2726 if ($opts{filled}) {
2727 my $color = $opts{'color'};
2729 if (defined $color) {
2730 unless (_is_color_object($color)) {
2731 $color = _color($color);
2733 $self->{ERRSTR} = $Imager::ERRSTR;
2739 $color = i_color_new(255,255,255,255);
2742 if ($color->isa("Imager::Color")) {
2743 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2746 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2749 elsif ($opts{fill}) {
2750 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2751 # assume it's a hash ref
2752 require 'Imager/Fill.pm';
2753 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2754 $self->{ERRSTR} = $Imager::ERRSTR;
2758 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2761 my $color = $opts{'color'};
2762 if (defined $color) {
2763 unless (_is_color_object($color)) {
2764 $color = _color($color);
2766 $self->{ERRSTR} = $Imager::ERRSTR;
2772 $color = i_color_new(255, 255, 255, 255);
2775 $self->{ERRSTR} = $Imager::ERRSTR;
2778 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2786 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2787 my $dflcl= [ 255, 255, 255, 255];
2792 'r'=>_min($self->getwidth(),$self->getheight())/3,
2793 'x'=>$self->getwidth()/2,
2794 'y'=>$self->getheight()/2,
2801 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2802 # assume it's a hash ref
2803 require 'Imager/Fill.pm';
2804 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2805 $self->{ERRSTR} = $Imager::ERRSTR;
2809 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2810 $opts{'d2'}, $opts{fill}{fill});
2812 elsif ($opts{filled}) {
2813 my $color = _color($opts{'color'});
2815 $self->{ERRSTR} = $Imager::ERRSTR;
2818 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2819 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2823 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2824 $opts{'d1'}, $opts{'d2'}, $color);
2828 my $color = _color($opts{'color'});
2829 if ($opts{d2} - $opts{d1} >= 360) {
2830 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2833 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2839 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2840 # assume it's a hash ref
2841 require 'Imager/Fill.pm';
2842 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2843 $self->{ERRSTR} = $Imager::ERRSTR;
2847 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2848 $opts{'d2'}, $opts{fill}{fill});
2851 my $color = _color($opts{'color'});
2853 $self->{ERRSTR} = $Imager::ERRSTR;
2856 if ($opts{filled}) {
2857 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2858 $opts{'d1'}, $opts{'d2'}, $color);
2861 if ($opts{d1} == 0 && $opts{d2} == 361) {
2862 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2865 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2871 $self->_set_error($self->_error_as_msg);
2878 # Draws a line from one point to the other
2879 # the endpoint is set if the endp parameter is set which it is by default.
2880 # to turn of the endpoint being set use endp=>0 when calling line.
2884 my $dflcl=i_color_new(0,0,0,0);
2885 my %opts=(color=>$dflcl,
2888 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2890 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2891 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2893 my $color = _color($opts{'color'});
2895 $self->{ERRSTR} = $Imager::ERRSTR;
2899 $opts{antialias} = $opts{aa} if defined $opts{aa};
2900 if ($opts{antialias}) {
2901 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2902 $color, $opts{endp});
2904 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2905 $color, $opts{endp});
2910 # Draws a line between an ordered set of points - It more or less just transforms this
2911 # into a list of lines.
2915 my ($pt,$ls,@points);
2916 my $dflcl=i_color_new(0,0,0,0);
2917 my %opts=(color=>$dflcl,@_);
2919 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2921 if (exists($opts{points})) { @points=@{$opts{points}}; }
2922 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2923 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2926 # print Dumper(\@points);
2928 my $color = _color($opts{'color'});
2930 $self->{ERRSTR} = $Imager::ERRSTR;
2933 $opts{antialias} = $opts{aa} if defined $opts{aa};
2934 if ($opts{antialias}) {
2937 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2944 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2954 my ($pt,$ls,@points);
2955 my $dflcl = i_color_new(0,0,0,0);
2956 my %opts = (color=>$dflcl, @_);
2958 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2960 if (exists($opts{points})) {
2961 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2962 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2965 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2966 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2969 if ($opts{'fill'}) {
2970 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2971 # assume it's a hash ref
2972 require 'Imager/Fill.pm';
2973 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2974 $self->{ERRSTR} = $Imager::ERRSTR;
2978 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2979 $opts{'fill'}{'fill'});
2982 my $color = _color($opts{'color'});
2984 $self->{ERRSTR} = $Imager::ERRSTR;
2987 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2994 # this the multipoint bezier curve
2995 # this is here more for testing that actual usage since
2996 # this is not a good algorithm. Usually the curve would be
2997 # broken into smaller segments and each done individually.
3001 my ($pt,$ls,@points);
3002 my $dflcl=i_color_new(0,0,0,0);
3003 my %opts=(color=>$dflcl,@_);
3005 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3007 if (exists $opts{points}) {
3008 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3009 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3012 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3013 $self->{ERRSTR}='Missing or invalid points.';
3017 my $color = _color($opts{'color'});
3019 $self->{ERRSTR} = $Imager::ERRSTR;
3022 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3028 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3031 unless (exists $opts{'x'} && exists $opts{'y'}) {
3032 $self->{ERRSTR} = "missing seed x and y parameters";
3036 if ($opts{border}) {
3037 my $border = _color($opts{border});
3039 $self->_set_error($Imager::ERRSTR);
3043 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3044 # assume it's a hash ref
3045 require Imager::Fill;
3046 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3047 $self->{ERRSTR} = $Imager::ERRSTR;
3051 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3052 $opts{fill}{fill}, $border);
3055 my $color = _color($opts{'color'});
3057 $self->{ERRSTR} = $Imager::ERRSTR;
3060 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3067 $self->{ERRSTR} = $self->_error_as_msg();
3073 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3074 # assume it's a hash ref
3075 require 'Imager/Fill.pm';
3076 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3077 $self->{ERRSTR} = $Imager::ERRSTR;
3081 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3084 my $color = _color($opts{'color'});
3086 $self->{ERRSTR} = $Imager::ERRSTR;
3089 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3095 $self->{ERRSTR} = $self->_error_as_msg();
3102 my ($self, %opts) = @_;
3104 my $color = $opts{color};
3105 unless (defined $color) {
3106 $color = $self->{fg};
3107 defined $color or $color = NC(255, 255, 255);
3110 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3111 $color = _color($color)
3115 unless (exists $opts{'x'} && exists $opts{'y'}) {
3116 $self->{ERRSTR} = 'missing x and y parameters';
3122 if (ref $x && ref $y) {
3123 unless (@$x == @$y) {
3124 $self->{ERRSTR} = 'length of x and y mismatch';
3128 if ($color->isa('Imager::Color')) {
3129 for my $i (0..$#{$opts{'x'}}) {
3130 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3135 for my $i (0..$#{$opts{'x'}}) {
3136 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3144 if ($color->isa('Imager::Color')) {
3145 i_ppix($self->{IMG}, $x, $y, $color)
3149 i_ppixf($self->{IMG}, $x, $y, $color)
3160 my %opts = ( "type"=>'8bit', @_);
3162 unless (exists $opts{'x'} && exists $opts{'y'}) {
3163 $self->{ERRSTR} = 'missing x and y parameters';
3169 if (ref $x && ref $y) {
3170 unless (@$x == @$y) {
3171 $self->{ERRSTR} = 'length of x and y mismatch';
3175 if ($opts{"type"} eq '8bit') {
3176 for my $i (0..$#{$opts{'x'}}) {
3177 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3181 for my $i (0..$#{$opts{'x'}}) {
3182 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3185 return wantarray ? @result : \@result;
3188 if ($opts{"type"} eq '8bit') {
3189 return i_get_pixel($self->{IMG}, $x, $y);
3192 return i_gpixf($self->{IMG}, $x, $y);
3201 my %opts = ( type => '8bit', x=>0, @_);
3203 $self->_valid_image or return;
3205 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3207 unless (defined $opts{'y'}) {
3208 $self->_set_error("missing y parameter");
3212 if ($opts{type} eq '8bit') {
3213 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3216 elsif ($opts{type} eq 'float') {
3217 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3220 elsif ($opts{type} eq 'index') {
3221 unless (i_img_type($self->{IMG})) {
3222 $self->_set_error("type => index only valid on paletted images");
3225 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3229 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3236 my %opts = ( x=>0, @_);
3238 $self->_valid_image or return;
3240 unless (defined $opts{'y'}) {
3241 $self->_set_error("missing y parameter");
3246 if (ref $opts{pixels} && @{$opts{pixels}}) {
3247 # try to guess the type
3248 if ($opts{pixels}[0]->isa('Imager::Color')) {
3249 $opts{type} = '8bit';
3251 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3252 $opts{type} = 'float';
3255 $self->_set_error("missing type parameter and could not guess from pixels");
3261 $opts{type} = '8bit';
3265 if ($opts{type} eq '8bit') {
3266 if (ref $opts{pixels}) {
3267 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3270 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3273 elsif ($opts{type} eq 'float') {
3274 if (ref $opts{pixels}) {
3275 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3278 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3281 elsif ($opts{type} eq 'index') {
3282 if (ref $opts{pixels}) {
3283 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3286 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3290 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3297 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3299 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3301 unless (defined $opts{'y'}) {
3302 $self->_set_error("missing y parameter");
3306 unless ($opts{channels}) {
3307 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3310 if ($opts{target}) {
3311 my $target = $opts{target};
3312 my $offset = $opts{offset};
3313 if ($opts{type} eq '8bit') {
3314 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3315 $opts{y}, @{$opts{channels}})
3317 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3318 return scalar(@samples);
3320 elsif ($opts{type} eq 'float') {
3321 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3322 $opts{y}, @{$opts{channels}});
3323 @{$target}{$offset .. $offset + @samples - 1} = @samples;
3324 return scalar(@samples);
3326 elsif ($opts{type} =~ /^(\d+)bit$/) {
3330 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3331 $opts{y}, $bits, $target,
3332 $offset, @{$opts{channels}});
3333 unless (defined $count) {
3334 $self->_set_error(Imager->_error_as_msg);
3341 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3346 if ($opts{type} eq '8bit') {
3347 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3348 $opts{y}, @{$opts{channels}});
3350 elsif ($opts{type} eq 'float') {
3351 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3352 $opts{y}, @{$opts{channels}});
3354 elsif ($opts{type} =~ /^(\d+)bit$/) {
3358 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3359 $opts{y}, $bits, \@data, 0, @{$opts{channels}})
3364 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3372 my %opts = ( x => 0, offset => 0, @_ );
3374 unless ($self->{IMG}) {
3375 $self->_set_error('setsamples: empty input image');
3379 unless(defined $opts{data} && ref $opts{data}) {
3380 $self->_set_error('setsamples: data parameter missing or invalid');
3384 unless ($opts{channels}) {
3385 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3388 unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
3389 $self->_set_error('setsamples: type parameter missing or invalid');
3394 unless (defined $opts{width}) {
3395 $opts{width} = $self->getwidth() - $opts{x};
3398 my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3399 $opts{channels}, $opts{data}, $opts{offset},
3401 unless (defined $count) {
3402 $self->_set_error(Imager->_error_as_msg);
3409 # make an identity matrix of the given size
3413 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3414 for my $c (0 .. ($size-1)) {
3415 $matrix->[$c][$c] = 1;
3420 # general function to convert an image
3422 my ($self, %opts) = @_;
3425 unless (defined wantarray) {
3426 my @caller = caller;
3427 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3431 # the user can either specify a matrix or preset
3432 # the matrix overrides the preset
3433 if (!exists($opts{matrix})) {
3434 unless (exists($opts{preset})) {
3435 $self->{ERRSTR} = "convert() needs a matrix or preset";
3439 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3440 # convert to greyscale, keeping the alpha channel if any
3441 if ($self->getchannels == 3) {
3442 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3444 elsif ($self->getchannels == 4) {
3445 # preserve the alpha channel
3446 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3451 $matrix = _identity($self->getchannels);
3454 elsif ($opts{preset} eq 'noalpha') {
3455 # strip the alpha channel
3456 if ($self->getchannels == 2 or $self->getchannels == 4) {
3457 $matrix = _identity($self->getchannels);
3458 pop(@$matrix); # lose the alpha entry
3461 $matrix = _identity($self->getchannels);
3464 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3466 $matrix = [ [ 1 ] ];
3468 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3469 $matrix = [ [ 0, 1 ] ];
3471 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3472 $matrix = [ [ 0, 0, 1 ] ];
3474 elsif ($opts{preset} eq 'alpha') {
3475 if ($self->getchannels == 2 or $self->getchannels == 4) {
3476 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3479 # the alpha is just 1 <shrug>
3480 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3483 elsif ($opts{preset} eq 'rgb') {
3484 if ($self->getchannels == 1) {
3485 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3487 elsif ($self->getchannels == 2) {
3488 # preserve the alpha channel
3489 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3492 $matrix = _identity($self->getchannels);
3495 elsif ($opts{preset} eq 'addalpha') {
3496 if ($self->getchannels == 1) {
3497 $matrix = _identity(2);
3499 elsif ($self->getchannels == 3) {
3500 $matrix = _identity(4);
3503 $matrix = _identity($self->getchannels);
3507 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3513 $matrix = $opts{matrix};
3516 my $new = Imager->new;
3517 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3518 unless ($new->{IMG}) {
3519 # most likely a bad matrix
3520 $self->{ERRSTR} = _error_as_msg();
3526 # combine channels from multiple input images, a class method
3528 my ($class, %opts) = @_;
3530 my $src = delete $opts{src};
3532 $class->_set_error("src parameter missing");
3537 for my $img (@$src) {
3538 unless (eval { $img->isa("Imager") }) {
3539 $class->_set_error("src must contain image objects");
3542 unless ($img->{IMG}) {
3543 $class->_set_error("empty input image");
3546 push @imgs, $img->{IMG};
3549 if (my $channels = delete $opts{channels}) {
3550 $result = i_combine(\@imgs, $channels);
3553 $result = i_combine(\@imgs);
3556 $class->_set_error($class->_error_as_msg);
3560 my $img = $class->new;
3561 $img->{IMG} = $result;
3567 # general function to map an image through lookup tables
3570 my ($self, %opts) = @_;
3571 my @chlist = qw( red green blue alpha );
3573 if (!exists($opts{'maps'})) {
3574 # make maps from channel maps
3576 for $chnum (0..$#chlist) {
3577 if (exists $opts{$chlist[$chnum]}) {
3578 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3579 } elsif (exists $opts{'all'}) {
3580 $opts{'maps'}[$chnum] = $opts{'all'};
3584 if ($opts{'maps'} and $self->{IMG}) {
3585 i_map($self->{IMG}, $opts{'maps'} );
3591 my ($self, %opts) = @_;
3593 defined $opts{mindist} or $opts{mindist} = 0;
3595 defined $opts{other}
3596 or return $self->_set_error("No 'other' parameter supplied");
3597 defined $opts{other}{IMG}
3598 or return $self->_set_error("No image data in 'other' image");
3601 or return $self->_set_error("No image data");
3603 my $result = Imager->new;
3604 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3606 or return $self->_set_error($self->_error_as_msg());
3611 # destructive border - image is shrunk by one pixel all around
3614 my ($self,%opts)=@_;
3615 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3616 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3620 # Get the width of an image
3625 if (my $raw = $self->{IMG}) {
3626 return i_img_get_width($raw);
3629 $self->{ERRSTR} = 'image is empty'; return undef;
3633 # Get the height of an image
3638 if (my $raw = $self->{IMG}) {
3639 return i_img_get_height($raw);
3642 $self->{ERRSTR} = 'image is empty'; return undef;
3646 # Get number of channels in an image
3650 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3651 return i_img_getchannels($self->{IMG});
3658 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3659 return i_img_getmask($self->{IMG});
3667 if (!defined($self->{IMG})) {
3668 $self->{ERRSTR} = 'image is empty';
3671 unless (defined $opts{mask}) {
3672 $self->_set_error("mask parameter required");
3675 i_img_setmask( $self->{IMG} , $opts{mask} );
3680 # Get number of colors in an image
3684 my %opts=('maxcolors'=>2**30,@_);
3685 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3686 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3687 return ($rc==-1? undef : $rc);
3690 # Returns a reference to a hash. The keys are colour named (packed) and the
3691 # values are the number of pixels in this colour.
3692 sub getcolorusagehash {
3695 my %opts = ( maxcolors => 2**30, @_ );
3696 my $max_colors = $opts{maxcolors};
3697 unless (defined $max_colors && $max_colors > 0) {
3698 $self->_set_error('maxcolors must be a positive integer');
3702 unless (defined $self->{IMG}) {
3703 $self->_set_error('empty input image');
3707 my $channels= $self->getchannels;
3708 # We don't want to look at the alpha channel, because some gifs using it
3709 # doesn't define it for every colour (but only for some)
3710 $channels -= 1 if $channels == 2 or $channels == 4;
3712 my $height = $self->getheight;
3713 for my $y (0 .. $height - 1) {
3714 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3715 while (length $colors) {
3716 $color_use{ substr($colors, 0, $channels, '') }++;
3718 keys %color_use > $max_colors
3724 # This will return a ordered array of the colour usage. Kind of the sorted
3725 # version of the values of the hash returned by getcolorusagehash.
3726 # You might want to add safety checks and change the names, etc...
3730 my %opts = ( maxcolors => 2**30, @_ );
3731 my $max_colors = $opts{maxcolors};
3732 unless (defined $max_colors && $max_colors > 0) {
3733 $self->_set_error('maxcolors must be a positive integer');
3737 unless (defined $self->{IMG}) {
3738 $self->_set_error('empty input image');
3742 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3745 # draw string to an image
3749 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3751 my %input=('x'=>0, 'y'=>0, @_);
3752 defined($input{string}) or $input{string} = $input{text};
3754 unless(defined $input{string}) {
3755 $self->{ERRSTR}="missing required parameter 'string'";
3759 unless($input{font}) {
3760 $self->{ERRSTR}="missing required parameter 'font'";
3764 unless ($input{font}->draw(image=>$self, %input)) {
3776 unless ($self->{IMG}) {
3777 $self->{ERRSTR}='empty input image';
3786 my %input=('x'=>0, 'y'=>0, @_);
3787 defined $input{string}
3788 or $input{string} = $input{text};
3790 unless(exists $input{string}) {
3791 $self->_set_error("missing required parameter 'string'");
3795 unless($input{font}) {
3796 $self->_set_error("missing required parameter 'font'");
3801 unless (@result = $input{font}->align(image=>$img, %input)) {
3805 return wantarray ? @result : $result[0];
3808 my @file_limit_names = qw/width height bytes/;
3810 sub set_file_limits {
3817 @values{@file_limit_names} = (0) x @file_limit_names;
3820 @values{@file_limit_names} = i_get_image_file_limits();
3823 for my $key (keys %values) {
3824 defined $opts{$key} and $values{$key} = $opts{$key};
3827 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3830 sub get_file_limits {
3831 i_get_image_file_limits();
3834 # Shortcuts that can be exported
3836 sub newcolor { Imager::Color->new(@_); }
3837 sub newfont { Imager::Font->new(@_); }
3839 require Imager::Color::Float;
3840 return Imager::Color::Float->new(@_);
3843 *NC=*newcolour=*newcolor;
3850 #### Utility routines
3853 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3857 my ($self, $msg) = @_;
3860 $self->{ERRSTR} = $msg;
3868 # Default guess for the type of an image from extension
3870 sub def_guess_type {
3873 $ext=($name =~ m/\.([^\.]+)$/)[0];
3874 return 'tiff' if ($ext =~ m/^tiff?$/);
3875 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3876 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3877 return 'png' if ($ext eq "png");
3878 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3879 return 'tga' if ($ext eq "tga");
3880 return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
3881 return 'gif' if ($ext eq "gif");
3882 return 'raw' if ($ext eq "raw");
3883 return lc $ext; # best guess
3888 return @combine_types;
3891 # get the minimum of a list
3895 for(@_) { if ($_<$mx) { $mx=$_; }}
3899 # get the maximum of a list
3903 for(@_) { if ($_>$mx) { $mx=$_; }}
3907 # string stuff for iptc headers
3911 $str = substr($str,3);
3912 $str =~ s/[\n\r]//g;
3919 # A little hack to parse iptc headers.
3924 my($caption,$photogr,$headln,$credit);
3926 my $str=$self->{IPTCRAW};
3931 @ar=split(/8BIM/,$str);
3936 @sar=split(/\034\002/);
3937 foreach $item (@sar) {
3938 if ($item =~ m/^x/) {
3939 $caption = _clean($item);
3942 if ($item =~ m/^P/) {
3943 $photogr = _clean($item);
3946 if ($item =~ m/^i/) {
3947 $headln = _clean($item);
3950 if ($item =~ m/^n/) {
3951 $credit = _clean($item);
3957 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3964 or die "Only C language supported";
3966 require Imager::ExtUtils;
3967 return Imager::ExtUtils->inline_config;
3970 # threads shouldn't try to close raw Imager objects
3971 sub Imager::ImgRaw::CLONE_SKIP { 1 }
3974 # this serves two purposes:
3975 # - a class method to load the file support modules included with Image
3976 # (or were included, once the library dependent modules are split out)
3977 # - something for Module::ScanDeps to analyze
3978 # https://rt.cpan.org/Ticket/Display.html?id=6566
3980 eval { require Imager::File::GIF };
3981 eval { require Imager::File::JPEG };
3982 eval { require Imager::File::PNG };
3983 eval { require Imager::File::SGI };
3984 eval { require Imager::File::TIFF };
3985 eval { require Imager::File::ICO };
3986 eval { require Imager::Font::W32 };
3987 eval { require Imager::Font::FT2 };
3988 eval { require Imager::Font::T1 };
3991 # backward compatibility for %formats
3992 package Imager::FORMATS;
3994 use constant IX_FORMATS => 0;
3995 use constant IX_LIST => 1;
3996 use constant IX_INDEX => 2;
3997 use constant IX_CLASSES => 3;
4000 my ($class, $formats, $classes) = @_;
4002 return bless [ $formats, [ ], 0, $classes ], $class;
4006 my ($self, $key) = @_;
4008 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4010 if (eval { require $file; 1 }) {
4016 $self->[IX_FORMATS]{$key} = $value;
4022 my ($self, $key) = @_;
4024 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4026 $self->[IX_CLASSES]{$key} or return undef;
4028 return $self->_check($key);
4032 die "%Imager::formats is not user monifiable";
4036 die "%Imager::formats is not user monifiable";
4040 die "%Imager::formats is not user monifiable";
4044 my ($self, $key) = @_;
4046 if (exists $self->[IX_FORMATS]{$key}) {
4047 my $value = $self->[IX_FORMATS]{$key}
4052 $self->_check($key) or return 1==0;
4060 unless (@{$self->[IX_LIST]}) {
4062 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4063 keys %{$self->[IX_FORMATS]};
4065 for my $key (keys %{$self->[IX_CLASSES]}) {
4066 $self->[IX_FORMATS]{$key} and next;
4068 and push @{$self->[IX_LIST]}, $key;
4072 @{$self->[IX_LIST]} or return;
4073 $self->[IX_INDEX] = 1;
4074 return $self->[IX_LIST][0];
4080 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4083 return $self->[IX_LIST][$self->[IX_INDEX]++];
4089 return scalar @{$self->[IX_LIST]};
4094 # Below is the stub of documentation for your module. You better edit it!
4098 Imager - Perl extension for Generating 24 bit Images
4108 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4113 # see Imager::Files for information on the read() method
4114 my $img = Imager->new(file=>$file)
4115 or die Imager->errstr();
4117 $file =~ s/\.[^.]*$//;
4119 # Create smaller version
4120 # documented in Imager::Transformations
4121 my $thumb = $img->scale(scalefactor=>.3);
4123 # Autostretch individual channels
4124 $thumb->filter(type=>'autolevels');
4126 # try to save in one of these formats
4129 for $format ( qw( png gif jpeg tiff ppm ) ) {
4130 # Check if given format is supported
4131 if ($Imager::formats{$format}) {
4132 $file.="_low.$format";
4133 print "Storing image as: $file\n";
4134 # documented in Imager::Files
4135 $thumb->write(file=>$file) or
4143 Imager is a module for creating and altering images. It can read and
4144 write various image formats, draw primitive shapes like lines,and
4145 polygons, blend multiple images together in various ways, scale, crop,
4146 render text and more.
4148 =head2 Overview of documentation
4154 Imager - This document - Synopsis, Example, Table of Contents and
4159 L<Imager::Tutorial> - a brief introduction to Imager.
4163 L<Imager::Cookbook> - how to do various things with Imager.
4167 L<Imager::ImageTypes> - Basics of constructing image objects with
4168 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4169 8/16/double bits/channel, color maps, channel masks, image tags, color
4170 quantization. Also discusses basic image information methods.
4174 L<Imager::Files> - IO interaction, reading/writing images, format
4179 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4184 L<Imager::Color> - Color specification.
4188 L<Imager::Fill> - Fill pattern specification.
4192 L<Imager::Font> - General font rendering, bounding boxes and font
4197 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4198 blending, pasting, convert and map.
4202 L<Imager::Engines> - Programmable transformations through
4203 C<transform()>, C<transform2()> and C<matrix_transform()>.
4207 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4212 L<Imager::Expr> - Expressions for evaluation engine used by
4217 L<Imager::Matrix2d> - Helper class for affine transformations.
4221 L<Imager::Fountain> - Helper for making gradient profiles.
4225 L<Imager::API> - using Imager's C API
4229 L<Imager::APIRef> - API function reference
4233 L<Imager::Inline> - using Imager's C API from Inline::C
4237 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4241 =head2 Basic Overview
4243 An Image object is created with C<$img = Imager-E<gt>new()>.
4246 $img=Imager->new(); # create empty image
4247 $img->read(file=>'lena.png',type=>'png') or # read image from file
4248 die $img->errstr(); # give an explanation
4249 # if something failed
4251 or if you want to create an empty image:
4253 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4255 This example creates a completely black image of width 400 and height
4258 =head1 ERROR HANDLING
4260 In general a method will return false when it fails, if it does use
4261 the C<errstr()> method to find out why:
4267 Returns the last error message in that context.
4269 If the last error you received was from calling an object method, such
4270 as read, call errstr() as an object method to find out why:
4272 my $image = Imager->new;
4273 $image->read(file => 'somefile.gif')
4274 or die $image->errstr;
4276 If it was a class method then call errstr() as a class method:
4278 my @imgs = Imager->read_multi(file => 'somefile.gif')
4279 or die Imager->errstr;
4281 Note that in some cases object methods are implemented in terms of
4282 class methods so a failing object method may set both.
4286 The C<Imager-E<gt>new> method is described in detail in
4287 L<Imager::ImageTypes>.
4291 Where to find information on methods for Imager class objects.
4293 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4296 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4298 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4301 arc() - L<Imager::Draw/arc()> - draw a filled arc
4303 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4306 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4308 circle() - L<Imager::Draw/circle()> - draw a filled circle
4310 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4313 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4314 colors in an image's palette (paletted images only)
4316 combine() - L<Imager::Transformations/combine()> - combine channels
4317 from one or more images.
4319 combines() - L<Imager::Draw/combines()> - return a list of the
4320 different combine type keywords
4322 compose() - L<Imager::Transformations/compose()> - compose one image
4325 convert() - L<Imager::Transformations/"Color transformations"> -
4326 transform the color space
4328 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4331 crop() - L<Imager::Transformations/crop()> - extract part of an image
4333 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4334 used to guess the output file format based on the output file name
4336 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4338 difference() - L<Imager::Filters/"Image Difference"> - produce a
4339 difference images from two input images.
4341 errstr() - L</"Basic Overview"> - the error from the last failed
4344 filter() - L<Imager::Filters> - image filtering
4346 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4347 palette, if it has one
4349 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4352 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4355 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4356 samples per pixel for an image
4358 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4359 different colors used by an image (works for direct color images)
4361 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4362 palette, if it has one
4364 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4366 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4368 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4370 getheight() - L<Imager::ImageTypes/getwidth()> - height of the image in
4373 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4375 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4378 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4379 row or partial row of pixels.
4381 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4382 row or partial row of pixels.
4384 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4387 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4390 init() - L<Imager::ImageTypes/init()>
4392 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4393 image write functions should write the image in their bilevel (blank
4394 and white, no gray levels) format
4396 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4399 line() - L<Imager::Draw/line()> - draw an interval
4401 load_plugin() - L<Imager::Filters/load_plugin()>
4403 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4406 map() - L<Imager::Transformations/"Color Mappings"> - remap color
4409 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4411 matrix_transform() - L<Imager::Engines/matrix_transform()>
4413 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4415 NC() - L<Imager::Handy/NC()>
4417 NCF() - L<Imager::Handy/NCF()>
4419 new() - L<Imager::ImageTypes/new()>
4421 newcolor() - L<Imager::Handy/newcolor()>
4423 newcolour() - L<Imager::Handy/newcolour()>
4425 newfont() - L<Imager::Handy/newfont()>
4427 NF() - L<Imager::Handy/NF()>
4429 open() - L<Imager::Files> - an alias for read()
4431 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4435 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4438 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4441 polygon() - L<Imager::Draw/polygon()>
4443 polyline() - L<Imager::Draw/polyline()>
4445 preload() - L<Imager::Files/preload()>
4447 read() - L<Imager::Files> - read a single image from an image file
4449 read_multi() - L<Imager::Files> - read multiple images from an image
4452 read_types() - L<Imager::Files/read_types()> - list image types Imager
4455 register_filter() - L<Imager::Filters/register_filter()>
4457 register_reader() - L<Imager::Files/register_reader()>
4459 register_writer() - L<Imager::Files/register_writer()>
4461 rotate() - L<Imager::Transformations/rotate()>
4463 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4464 onto an image and use the alpha channel
4466 scale() - L<Imager::Transformations/scale()>
4468 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4470 scaleX() - L<Imager::Transformations/scaleX()>
4472 scaleY() - L<Imager::Transformations/scaleY()>
4474 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4477 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
4479 setmask() - L<Imager::ImageTypes/setmask()>
4481 setpixel() - L<Imager::Draw/setpixel()>
4483 setsamples() - L<Imager::Draw/setsamples()>
4485 setscanline() - L<Imager::Draw/setscanline()>
4487 settag() - L<Imager::ImageTypes/settag()>
4489 string() - L<Imager::Draw/string()> - draw text on an image
4491 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4493 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4495 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4497 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4499 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4500 double per sample image.
4502 transform() - L<Imager::Engines/"transform()">
4504 transform2() - L<Imager::Engines/"transform2()">
4506 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4508 unload_plugin() - L<Imager::Filters/unload_plugin()>
4510 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4513 write() - L<Imager::Files> - write an image to a file
4515 write_multi() - L<Imager::Files> - write multiple image to an image
4518 write_types() - L<Imager::Files/read_types()> - list image types Imager
4521 =head1 CONCEPT INDEX
4523 animated GIF - L<Imager::Files/"Writing an animated GIF">
4525 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4526 L<Imager::ImageTypes/"Common Tags">.
4528 blend - alpha blending one image onto another
4529 L<Imager::Transformations/rubthrough()>
4531 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4533 boxes, drawing - L<Imager::Draw/box()>
4535 changes between image - L<Imager::Filters/"Image Difference">
4537 channels, combine into one image - L<Imager::Transformations/combine()>
4539 color - L<Imager::Color>
4541 color names - L<Imager::Color>, L<Imager::Color::Table>
4543 combine modes - L<Imager::Draw/"Combine Types">
4545 compare images - L<Imager::Filters/"Image Difference">
4547 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4549 convolution - L<Imager::Filters/conv>
4551 cropping - L<Imager::Transformations/crop()>
4553 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4555 C<diff> images - L<Imager::Filters/"Image Difference">
4557 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4558 L<Imager::Cookbook/"Image spatial resolution">
4560 drawing boxes - L<Imager::Draw/box()>
4562 drawing lines - L<Imager::Draw/line()>
4564 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4566 error message - L</"ERROR HANDLING">
4568 files, font - L<Imager::Font>
4570 files, image - L<Imager::Files>
4572 filling, types of fill - L<Imager::Fill>
4574 filling, boxes - L<Imager::Draw/box()>
4576 filling, flood fill - L<Imager::Draw/flood_fill()>
4578 flood fill - L<Imager::Draw/flood_fill()>
4580 fonts - L<Imager::Font>
4582 fonts, drawing with - L<Imager::Draw/string()>,
4583 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4585 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4587 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4589 fountain fill - L<Imager::Fill/"Fountain fills">,
4590 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4591 L<Imager::Filters/gradgen>
4593 GIF files - L<Imager::Files/"GIF">
4595 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4597 gradient fill - L<Imager::Fill/"Fountain fills">,
4598 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4599 L<Imager::Filters/gradgen>
4601 gray scale, convert image to - L<Imager::Transformations/convert()>
4603 gaussian blur - L<Imager::Filters/gaussian>
4605 hatch fills - L<Imager::Fill/"Hatched fills">
4607 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4609 invert image - L<Imager::Filters/hardinvert>,
4610 L<Imager::Filters/hardinvertall>
4612 JPEG - L<Imager::Files/"JPEG">
4614 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4616 lines, drawing - L<Imager::Draw/line()>
4618 matrix - L<Imager::Matrix2d>,
4619 L<Imager::Engines/"Matrix Transformations">,
4620 L<Imager::Font/transform()>
4622 metadata, image - L<Imager::ImageTypes/"Tags">
4624 mosaic - L<Imager::Filters/mosaic>
4626 noise, filter - L<Imager::Filters/noise>
4628 noise, rendered - L<Imager::Filters/turbnoise>,
4629 L<Imager::Filters/radnoise>
4631 paste - L<Imager::Transformations/paste()>,
4632 L<Imager::Transformations/rubthrough()>
4634 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4635 L<Imager::ImageTypes/new()>
4637 =for stopwords posterize
4639 posterize - L<Imager::Filters/postlevels>
4641 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4643 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4645 rectangles, drawing - L<Imager::Draw/box()>
4647 resizing an image - L<Imager::Transformations/scale()>,
4648 L<Imager::Transformations/crop()>
4650 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4652 saving an image - L<Imager::Files>
4654 scaling - L<Imager::Transformations/scale()>
4656 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4658 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4660 size, image - L<Imager::ImageTypes/getwidth()>,
4661 L<Imager::ImageTypes/getheight()>
4663 size, text - L<Imager::Font/bounding_box()>
4665 tags, image metadata - L<Imager::ImageTypes/"Tags">
4667 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4668 L<Imager::Font::Wrap>
4670 text, wrapping text in an area - L<Imager::Font::Wrap>
4672 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4674 tiles, color - L<Imager::Filters/mosaic>
4676 transparent images - L<Imager::ImageTypes>,
4677 L<Imager::Cookbook/"Transparent PNG">
4679 =for stopwords unsharp
4681 unsharp mask - L<Imager::Filters/unsharpmask>
4683 watermark - L<Imager::Filters/watermark>
4685 writing an image to a file - L<Imager::Files>
4689 Imager doesn't support perl threads.
4691 Imager has limited code to prevent double frees if you create images,
4692 colors etc, and then create a thread, but has no code to prevent two
4693 threads entering Imager's error handling code, and none is likely to
4698 The best place to get help with Imager is the mailing list.
4700 To subscribe send a message with C<subscribe> in the body to:
4702 imager-devel+request@molar.is
4708 L<http://www.molar.is/en/lists/imager-devel/>
4712 where you can also find the mailing list archive.
4714 You can report bugs by pointing your browser at:
4718 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4722 or by sending an email to:
4726 bug-Imager@rt.cpan.org
4730 Please remember to include the versions of Imager, perl, supporting
4731 libraries, and any relevant code. If you have specific images that
4732 cause the problems, please include those too.
4734 If you don't want to publish your email address on a mailing list you
4735 can use CPAN::Forum:
4737 http://www.cpanforum.com/dist/Imager
4739 You will need to register to post.
4741 =head1 CONTRIBUTING TO IMAGER
4747 If you like or dislike Imager, you can add a public review of Imager
4750 http://cpanratings.perl.org/dist/Imager
4752 =for stopwords Bitcard
4754 This requires a Bitcard account (http://www.bitcard.org).
4756 You can also send email to the maintainer below.
4758 If you send me a bug report via email, it will be copied to Request
4763 I accept patches, preferably against the main branch in subversion.
4764 You should include an explanation of the reason for why the patch is
4767 Your patch should include regression tests where possible, otherwise
4768 it will be delayed until I get a chance to write them.
4772 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
4774 Arnar M. Hrafnkelsson is the original author of Imager.
4776 Many others have contributed to Imager, please see the C<README> for a
4781 Imager is licensed under the same terms as perl itself.
4784 makeblendedfont Fontforge
4786 A test font, FT2/fontfiles/MMOne.pfb, contains a Postscript operator
4787 definition copyrighted by Adobe. See F<adobe.txt> in the source for
4788 license information.
4792 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4793 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4794 L<Imager::Font>(3), L<Imager::Transformations>(3),
4795 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4796 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4798 L<http://imager.perl.org/>
4800 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4802 Other perl imaging modules include:
4804 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).