4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
108 # registered file readers
111 # registered file writers
114 # modules we attempted to autoload
115 my %attempted_to_load;
117 # errors from loading files
118 my %file_load_errors;
120 # what happened when we tried to load
121 my %reader_load_errors;
122 my %writer_load_errors;
124 # library keys that are image file formats
125 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
127 # image pixel combine types
129 qw/none normal multiply dissolve add subtract diff lighten darken
130 hue saturation value color/;
132 @combine_types{@combine_types} = 0 .. $#combine_types;
133 $combine_types{mult} = $combine_types{multiply};
134 $combine_types{'sub'} = $combine_types{subtract};
135 $combine_types{sat} = $combine_types{saturation};
137 # this will be used to store global defaults at some point
142 my $ex_version = eval $Exporter::VERSION;
143 if ($ex_version < 5.57) {
148 XSLoader::load(Imager => $VERSION);
154 png => "Imager::File::PNG",
155 gif => "Imager::File::GIF",
156 tiff => "Imager::File::TIFF",
157 jpeg => "Imager::File::JPEG",
158 w32 => "Imager::Font::W32",
159 ft2 => "Imager::Font::FT2",
160 t1 => "Imager::Font::T1",
163 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
166 for(i_list_formats()) { $formats_low{$_}++; }
168 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
172 # the members of the subhashes under %filters are:
173 # callseq - a list of the parameters to the underlying filter in the
174 # order they are passed
175 # callsub - a code ref that takes a named parameter list and calls the
177 # defaults - a hash of default values
178 # names - defines names for value of given parameters so if the names
179 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
180 # foo parameter, the filter will receive 1 for the foo
183 callseq => ['image','intensity'],
184 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
188 callseq => ['image', 'amount', 'subtype'],
189 defaults => { amount=>3,subtype=>0 },
190 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
193 $filters{hardinvert} ={
194 callseq => ['image'],
196 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
199 $filters{hardinvertall} =
201 callseq => ['image'],
203 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
206 $filters{autolevels} ={
207 callseq => ['image','lsat','usat','skew'],
208 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
209 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
212 $filters{turbnoise} ={
213 callseq => ['image'],
214 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
215 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
218 $filters{radnoise} ={
219 callseq => ['image'],
220 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
221 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
226 callseq => ['image', 'coef'],
231 i_conv($hsh{image},$hsh{coef})
232 or die Imager->_error_as_msg() . "\n";
238 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
239 defaults => { dist => 0 },
243 my @colors = @{$hsh{colors}};
246 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
250 $filters{nearest_color} =
252 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
257 # make sure the segments are specified with colors
259 for my $color (@{$hsh{colors}}) {
260 my $new_color = _color($color)
261 or die $Imager::ERRSTR."\n";
262 push @colors, $new_color;
265 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
267 or die Imager->_error_as_msg() . "\n";
270 $filters{gaussian} = {
271 callseq => [ 'image', 'stddev' ],
273 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
277 callseq => [ qw(image size) ],
278 defaults => { size => 20 },
279 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
283 callseq => [ qw(image bump elevation lightx lighty st) ],
284 defaults => { elevation=>0, st=> 2 },
287 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
288 $hsh{lightx}, $hsh{lighty}, $hsh{st});
291 $filters{bumpmap_complex} =
293 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
310 for my $cname (qw/Ia Il Is/) {
311 my $old = $hsh{$cname};
312 my $new_color = _color($old)
313 or die $Imager::ERRSTR, "\n";
314 $hsh{$cname} = $new_color;
316 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
317 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
318 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
322 $filters{postlevels} =
324 callseq => [ qw(image levels) ],
325 defaults => { levels => 10 },
326 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
328 $filters{watermark} =
330 callseq => [ qw(image wmark tx ty pixdiff) ],
331 defaults => { pixdiff=>10, tx=>0, ty=>0 },
335 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
341 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
343 ftype => { linear => 0,
349 repeat => { none => 0,
364 multiply => 2, mult => 2,
367 subtract => 5, 'sub' => 5,
377 defaults => { ftype => 0, repeat => 0, combine => 0,
378 super_sample => 0, ssample_param => 4,
391 # make sure the segments are specified with colors
393 for my $segment (@{$hsh{segments}}) {
394 my @new_segment = @$segment;
396 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
397 push @segments, \@new_segment;
400 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
401 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
402 $hsh{ssample_param}, \@segments)
403 or die Imager->_error_as_msg() . "\n";
406 $filters{unsharpmask} =
408 callseq => [ qw(image stddev scale) ],
409 defaults => { stddev=>2.0, scale=>1.0 },
413 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
417 $FORMATGUESS=\&def_guess_type;
427 # NOTE: this might be moved to an import override later on
432 if ($_[$i] eq '-log-stderr') {
440 goto &Exporter::import;
444 Imager->open_log(log => $_[0], level => $_[1]);
449 my %parms=(loglevel=>1,@_);
451 if (exists $parms{'warn_obsolete'}) {
452 $warn_obsolete = $parms{'warn_obsolete'};
456 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
460 if (exists $parms{'t1log'}) {
462 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
463 Imager->_set_error(Imager->_error_as_msg);
477 my (%opts) = ( loglevel => 1, @_ );
479 $is_logging = i_init_log($opts{log}, $opts{loglevel});
480 unless ($is_logging) {
481 Imager->_set_error(Imager->_error_as_msg());
485 Imager->log("Imager $VERSION starting\n", 1);
491 i_init_log(undef, -1);
496 my ($class, $message, $level) = @_;
498 defined $level or $level = 1;
500 i_log_entry($message, $level);
510 print "shutdown code\n";
511 # for(keys %instances) { $instances{$_}->DESTROY(); }
512 malloc_state(); # how do decide if this should be used? -- store something from the import
513 print "Imager exiting\n";
517 # Load a filter plugin
522 my ($DSO_handle,$str)=DSO_open($filename);
523 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
524 my %funcs=DSO_funclist($DSO_handle);
525 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
527 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
529 $DSOs{$filename}=[$DSO_handle,\%funcs];
532 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
533 $DEBUG && print "eval string:\n",$evstr,"\n";
545 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
546 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
547 for(keys %{$funcref}) {
549 $DEBUG && print "unloading: $_\n";
551 my $rc=DSO_close($DSO_handle);
552 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
556 # take the results of i_error() and make a message out of it
558 return join(": ", map $_->[0], i_errors());
561 # this function tries to DWIM for color parameters
562 # color objects are used as is
563 # simple scalars are simply treated as single parameters to Imager::Color->new
564 # hashrefs are treated as named argument lists to Imager::Color->new
565 # arrayrefs are treated as list arguments to Imager::Color->new iff any
567 # other arrayrefs are treated as list arguments to Imager::Color::Float
571 # perl 5.6.0 seems to do weird things to $arg if we don't make an
572 # explicitly stringified copy
573 # I vaguely remember a bug on this on p5p, but couldn't find it
574 # through bugs.perl.org (I had trouble getting it to find any bugs)
575 my $copy = $arg . "";
579 if (UNIVERSAL::isa($arg, "Imager::Color")
580 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
584 if ($copy =~ /^HASH\(/) {
585 $result = Imager::Color->new(%$arg);
587 elsif ($copy =~ /^ARRAY\(/) {
588 $result = Imager::Color->new(@$arg);
591 $Imager::ERRSTR = "Not a color";
596 # assume Imager::Color::new knows how to handle it
597 $result = Imager::Color->new($arg);
604 my ($self, $combine, $default) = @_;
606 if (!defined $combine && ref $self) {
607 $combine = $self->{combine};
609 defined $combine or $combine = $defaults{combine};
610 defined $combine or $combine = $default;
612 if (exists $combine_types{$combine}) {
613 $combine = $combine_types{$combine};
620 my ($self, $method) = @_;
622 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
624 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
625 $msg = "$method: $msg" if $method;
626 $self->_set_error($msg);
631 # returns first defined parameter
634 return $_ if defined $_;
640 # Methods to be called on objects.
643 # Create a new Imager object takes very few parameters.
644 # usually you call this method and then call open from
645 # the resulting object
652 $self->{IMG}=undef; # Just to indicate what exists
653 $self->{ERRSTR}=undef; #
654 $self->{DEBUG}=$DEBUG;
655 $self->{DEBUG} and print "Initialized Imager\n";
656 if (defined $hsh{xsize} || defined $hsh{ysize}) {
657 unless ($self->img_set(%hsh)) {
658 $Imager::ERRSTR = $self->{ERRSTR};
662 elsif (defined $hsh{file} ||
665 defined $hsh{callback} ||
666 defined $hsh{readcb} ||
667 defined $hsh{data}) {
668 # allow $img = Imager->new(file => $filename)
671 # type is already used as a parameter to new(), rename it for the
673 if ($hsh{filetype}) {
674 $extras{type} = $hsh{filetype};
676 unless ($self->read(%hsh, %extras)) {
677 $Imager::ERRSTR = $self->{ERRSTR};
685 # Copy an entire image with no changes
686 # - if an image has magic the copy of it will not be magical
691 $self->_valid_image("copy")
694 unless (defined wantarray) {
696 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
700 my $newcopy=Imager->new();
701 $newcopy->{IMG} = i_copy($self->{IMG});
710 $self->_valid_image("paste")
713 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
714 my $src = $input{img} || $input{src};
716 $self->_set_error("no source image");
719 unless ($src->_valid_image("paste")) {
720 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
723 $input{left}=0 if $input{left} <= 0;
724 $input{top}=0 if $input{top} <= 0;
726 my($r,$b)=i_img_info($src->{IMG});
727 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
728 my ($src_right, $src_bottom);
729 if ($input{src_coords}) {
730 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
733 if (defined $input{src_maxx}) {
734 $src_right = $input{src_maxx};
736 elsif (defined $input{width}) {
737 if ($input{width} <= 0) {
738 $self->_set_error("paste: width must me positive");
741 $src_right = $src_left + $input{width};
746 if (defined $input{src_maxy}) {
747 $src_bottom = $input{src_maxy};
749 elsif (defined $input{height}) {
750 if ($input{height} < 0) {
751 $self->_set_error("paste: height must be positive");
754 $src_bottom = $src_top + $input{height};
761 $src_right > $r and $src_right = $r;
762 $src_bottom > $b and $src_bottom = $b;
764 if ($src_right <= $src_left
765 || $src_bottom < $src_top) {
766 $self->_set_error("nothing to paste");
770 i_copyto($self->{IMG}, $src->{IMG},
771 $src_left, $src_top, $src_right, $src_bottom,
772 $input{left}, $input{top});
774 return $self; # What should go here??
777 # Crop an image - i.e. return a new image that is smaller
782 $self->_valid_image("crop")
785 unless (defined wantarray) {
787 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
793 my ($w, $h, $l, $r, $b, $t) =
794 @hsh{qw(width height left right bottom top)};
796 # work through the various possibilities
801 elsif (!defined $r) {
802 $r = $self->getwidth;
814 $l = int(0.5+($self->getwidth()-$w)/2);
819 $r = $self->getwidth;
825 elsif (!defined $b) {
826 $b = $self->getheight;
838 $t=int(0.5+($self->getheight()-$h)/2);
843 $b = $self->getheight;
846 ($l,$r)=($r,$l) if $l>$r;
847 ($t,$b)=($b,$t) if $t>$b;
850 $r > $self->getwidth and $r = $self->getwidth;
852 $b > $self->getheight and $b = $self->getheight;
854 if ($l == $r || $t == $b) {
855 $self->_set_error("resulting image would have no content");
858 if( $r < $l or $b < $t ) {
859 $self->_set_error("attempting to crop outside of the image");
862 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
864 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
869 my ($self, %opts) = @_;
874 my $x = $opts{xsize} || $self->getwidth;
875 my $y = $opts{ysize} || $self->getheight;
876 my $channels = $opts{channels} || $self->getchannels;
878 my $out = Imager->new;
879 if ($channels == $self->getchannels) {
880 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
883 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
885 unless ($out->{IMG}) {
886 $self->{ERRSTR} = $self->_error_as_msg;
893 # Sets an image to a certain size and channel number
894 # if there was previously data in the image it is discarded
899 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
901 if (defined($self->{IMG})) {
902 # let IIM_DESTROY destroy it, it's possible this image is
903 # referenced from a virtual image (like masked)
904 #i_img_destroy($self->{IMG});
908 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
909 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
910 $hsh{maxcolors} || 256);
912 elsif ($hsh{bits} eq 'double') {
913 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
915 elsif ($hsh{bits} == 16) {
916 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
919 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
923 unless ($self->{IMG}) {
924 $self->{ERRSTR} = Imager->_error_as_msg();
931 # created a masked version of the current image
935 $self->_valid_image("masked")
938 my %opts = (left => 0,
940 right => $self->getwidth,
941 bottom => $self->getheight,
943 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
945 my $result = Imager->new;
946 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
947 $opts{top}, $opts{right} - $opts{left},
948 $opts{bottom} - $opts{top});
949 unless ($result->{IMG}) {
950 $self->_set_error(Imager->_error_as_msg);
954 # keep references to the mask and base images so they don't
956 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
961 # convert an RGB image into a paletted image
965 if (@_ != 1 && !ref $_[0]) {
972 unless (defined wantarray) {
974 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
978 $self->_valid_image("to_paletted")
981 my $result = Imager->new;
982 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
983 $self->_set_error(Imager->_error_as_msg);
991 my ($class, $quant, @images) = @_;
994 Imager->_set_error("make_palette: supply at least one image");
998 for my $img (@images) {
999 unless ($img->{IMG}) {
1000 Imager->_set_error("make_palette: image $index is empty");
1006 return i_img_make_palette($quant, map $_->{IMG}, @images);
1009 # convert a paletted (or any image) to an 8-bit/channel RGB image
1013 unless (defined wantarray) {
1014 my @caller = caller;
1015 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1019 $self->_valid_image("to_rgb8")
1022 my $result = Imager->new;
1023 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1024 $self->_set_error(Imager->_error_as_msg());
1031 # convert a paletted (or any image) to a 16-bit/channel RGB image
1035 unless (defined wantarray) {
1036 my @caller = caller;
1037 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1041 $self->_valid_image("to_rgb16")
1044 my $result = Imager->new;
1045 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1046 $self->_set_error(Imager->_error_as_msg());
1053 # convert a paletted (or any image) to an double/channel RGB image
1057 unless (defined wantarray) {
1058 my @caller = caller;
1059 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1063 $self->_valid_image("to_rgb_double")
1066 my $result = Imager->new;
1067 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1068 $self->_set_error(Imager->_error_as_msg());
1077 my %opts = (colors=>[], @_);
1079 $self->_valid_image("addcolors")
1082 my @colors = @{$opts{colors}}
1085 for my $color (@colors) {
1086 $color = _color($color);
1088 $self->_set_error($Imager::ERRSTR);
1093 return i_addcolors($self->{IMG}, @colors);
1098 my %opts = (start=>0, colors=>[], @_);
1100 $self->_valid_image("setcolors")
1103 my @colors = @{$opts{colors}}
1106 for my $color (@colors) {
1107 $color = _color($color);
1109 $self->_set_error($Imager::ERRSTR);
1114 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1121 $self->_valid_image("getcolors")
1124 if (!exists $opts{start} && !exists $opts{count}) {
1127 $opts{count} = $self->colorcount;
1129 elsif (!exists $opts{count}) {
1132 elsif (!exists $opts{start}) {
1136 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1142 $self->_valid_image("colorcount")
1145 return i_colorcount($self->{IMG});
1151 $self->_valid_image("maxcolors")
1154 i_maxcolors($self->{IMG});
1161 $self->_valid_image("findcolor")
1164 unless ($opts{color}) {
1165 $self->_set_error("findcolor: no color parameter");
1169 my $color = _color($opts{color})
1172 return i_findcolor($self->{IMG}, $color);
1178 $self->_valid_image("bits")
1181 my $bits = i_img_bits($self->{IMG});
1182 if ($bits && $bits == length(pack("d", 1)) * 8) {
1191 $self->_valid_image("type")
1194 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1200 $self->_valid_image("virtual")
1203 return i_img_virtual($self->{IMG});
1209 $self->_valid_image("is_bilevel")
1212 return i_img_is_monochrome($self->{IMG});
1216 my ($self, %opts) = @_;
1218 $self->_valid_image("tags")
1221 if (defined $opts{name}) {
1225 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1226 push @result, (i_tags_get($self->{IMG}, $found))[1];
1229 return wantarray ? @result : $result[0];
1231 elsif (defined $opts{code}) {
1235 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1236 push @result, (i_tags_get($self->{IMG}, $found))[1];
1243 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1246 return i_tags_count($self->{IMG});
1255 $self->_valid_image("addtag")
1259 if (defined $opts{value}) {
1260 if ($opts{value} =~ /^\d+$/) {
1262 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1265 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1268 elsif (defined $opts{data}) {
1269 # force addition as a string
1270 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1273 $self->{ERRSTR} = "No value supplied";
1277 elsif ($opts{code}) {
1278 if (defined $opts{value}) {
1279 if ($opts{value} =~ /^\d+$/) {
1281 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1284 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1287 elsif (defined $opts{data}) {
1288 # force addition as a string
1289 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1292 $self->{ERRSTR} = "No value supplied";
1305 $self->_valid_image("deltag")
1308 if (defined $opts{'index'}) {
1309 return i_tags_delete($self->{IMG}, $opts{'index'});
1311 elsif (defined $opts{name}) {
1312 return i_tags_delbyname($self->{IMG}, $opts{name});
1314 elsif (defined $opts{code}) {
1315 return i_tags_delbycode($self->{IMG}, $opts{code});
1318 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1324 my ($self, %opts) = @_;
1326 $self->_valid_image("settag")
1330 $self->deltag(name=>$opts{name});
1331 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1333 elsif (defined $opts{code}) {
1334 $self->deltag(code=>$opts{code});
1335 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1343 sub _get_reader_io {
1344 my ($self, $input) = @_;
1347 return $input->{io}, undef;
1349 elsif ($input->{fd}) {
1350 return io_new_fd($input->{fd});
1352 elsif ($input->{fh}) {
1353 my $fd = fileno($input->{fh});
1354 unless (defined $fd) {
1355 $self->_set_error("Handle in fh option not opened");
1358 return io_new_fd($fd);
1360 elsif ($input->{file}) {
1361 my $file = IO::File->new($input->{file}, "r");
1363 $self->_set_error("Could not open $input->{file}: $!");
1367 return (io_new_fd(fileno($file)), $file);
1369 elsif ($input->{data}) {
1370 return io_new_buffer($input->{data});
1372 elsif ($input->{callback} || $input->{readcb}) {
1373 if (!$input->{seekcb}) {
1374 $self->_set_error("Need a seekcb parameter");
1376 if ($input->{maxbuffer}) {
1377 return io_new_cb($input->{writecb},
1378 $input->{callback} || $input->{readcb},
1379 $input->{seekcb}, $input->{closecb},
1380 $input->{maxbuffer});
1383 return io_new_cb($input->{writecb},
1384 $input->{callback} || $input->{readcb},
1385 $input->{seekcb}, $input->{closecb});
1389 $self->_set_error("file/fd/fh/data/callback parameter missing");
1394 sub _get_writer_io {
1395 my ($self, $input) = @_;
1397 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1404 elsif ($input->{fd}) {
1405 $io = io_new_fd($input->{fd});
1407 elsif ($input->{fh}) {
1408 my $fd = fileno($input->{fh});
1409 unless (defined $fd) {
1410 $self->_set_error("Handle in fh option not opened");
1414 my $oldfh = select($input->{fh});
1415 # flush anything that's buffered, and make sure anything else is flushed
1418 $io = io_new_fd($fd);
1420 elsif ($input->{file}) {
1421 my $fh = new IO::File($input->{file},"w+");
1423 $self->_set_error("Could not open file $input->{file}: $!");
1426 binmode($fh) or die;
1427 $io = io_new_fd(fileno($fh));
1430 elsif ($input->{data}) {
1431 $io = io_new_bufchain();
1433 elsif ($input->{callback} || $input->{writecb}) {
1434 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1437 $io = io_new_cb($input->{callback} || $input->{writecb},
1439 $input->{seekcb}, $input->{closecb});
1442 $self->_set_error("file/fd/fh/data/callback parameter missing");
1446 unless ($buffered) {
1447 $io->set_buffered(0);
1450 return ($io, @extras);
1453 # Read an image from file
1459 if (defined($self->{IMG})) {
1460 # let IIM_DESTROY do the destruction, since the image may be
1461 # referenced from elsewhere
1462 #i_img_destroy($self->{IMG});
1463 undef($self->{IMG});
1466 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1468 my $type = $input{'type'};
1470 $type = i_test_format_probe($IO, -1);
1473 if ($input{file} && !$type) {
1475 $type = $FORMATGUESS->($input{file});
1479 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1480 $input{file} and $msg .= " or file name";
1481 $self->_set_error($msg);
1485 _reader_autoload($type);
1487 if ($readers{$type} && $readers{$type}{single}) {
1488 return $readers{$type}{single}->($self, $IO, %input);
1491 unless ($formats_low{$type}) {
1492 my $read_types = join ', ', sort Imager->read_types();
1493 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1497 my $allow_incomplete = $input{allow_incomplete};
1498 defined $allow_incomplete or $allow_incomplete = 0;
1500 if ( $type eq 'pnm' ) {
1501 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1502 if ( !defined($self->{IMG}) ) {
1503 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1506 $self->{DEBUG} && print "loading a pnm file\n";
1510 if ( $type eq 'bmp' ) {
1511 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1512 if ( !defined($self->{IMG}) ) {
1513 $self->{ERRSTR}=$self->_error_as_msg();
1516 $self->{DEBUG} && print "loading a bmp file\n";
1519 if ( $type eq 'tga' ) {
1520 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1521 if ( !defined($self->{IMG}) ) {
1522 $self->{ERRSTR}=$self->_error_as_msg();
1525 $self->{DEBUG} && print "loading a tga file\n";
1528 if ( $type eq 'raw' ) {
1529 unless ( $input{xsize} && $input{ysize} ) {
1530 $self->_set_error('missing xsize or ysize parameter for raw');
1534 my $interleave = _first($input{raw_interleave}, $input{interleave});
1535 unless (defined $interleave) {
1536 my @caller = caller;
1537 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1540 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1541 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1543 $self->{IMG} = i_readraw_wiol( $IO,
1549 if ( !defined($self->{IMG}) ) {
1550 $self->{ERRSTR}=$self->_error_as_msg();
1553 $self->{DEBUG} && print "loading a raw file\n";
1559 sub register_reader {
1560 my ($class, %opts) = @_;
1563 or die "register_reader called with no type parameter\n";
1565 my $type = $opts{type};
1567 defined $opts{single} || defined $opts{multiple}
1568 or die "register_reader called with no single or multiple parameter\n";
1570 $readers{$type} = { };
1571 if ($opts{single}) {
1572 $readers{$type}{single} = $opts{single};
1574 if ($opts{multiple}) {
1575 $readers{$type}{multiple} = $opts{multiple};
1581 sub register_writer {
1582 my ($class, %opts) = @_;
1585 or die "register_writer called with no type parameter\n";
1587 my $type = $opts{type};
1589 defined $opts{single} || defined $opts{multiple}
1590 or die "register_writer called with no single or multiple parameter\n";
1592 $writers{$type} = { };
1593 if ($opts{single}) {
1594 $writers{$type}{single} = $opts{single};
1596 if ($opts{multiple}) {
1597 $writers{$type}{multiple} = $opts{multiple};
1608 grep($file_formats{$_}, keys %formats),
1609 qw(ico sgi), # formats not handled directly, but supplied with Imager
1620 grep($file_formats{$_}, keys %formats),
1621 qw(ico sgi), # formats not handled directly, but supplied with Imager
1628 my ($file, $error) = @_;
1630 if ($attempted_to_load{$file}) {
1631 if ($file_load_errors{$file}) {
1632 $$error = $file_load_errors{$file};
1640 local $SIG{__DIE__};
1642 ++$attempted_to_load{$file};
1650 my $work = $@ || "Unknown error";
1652 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1653 $work =~ s/\n/\\n/g;
1654 $work =~ s/\s*\.?\z/ loading $file/;
1655 $file_load_errors{$file} = $work;
1662 # probes for an Imager::File::whatever module
1663 sub _reader_autoload {
1666 return if $formats_low{$type} || $readers{$type};
1668 return unless $type =~ /^\w+$/;
1670 my $file = "Imager/File/\U$type\E.pm";
1673 my $loaded = _load_file($file, \$error);
1674 if (!$loaded && $error =~ /^Can't locate /) {
1675 my $filer = "Imager/File/\U$type\EReader.pm";
1676 $loaded = _load_file($filer, \$error);
1677 if ($error =~ /^Can't locate /) {
1678 $error = "Can't locate $file or $filer";
1682 $reader_load_errors{$type} = $error;
1686 # probes for an Imager::File::whatever module
1687 sub _writer_autoload {
1690 return if $formats_low{$type} || $writers{$type};
1692 return unless $type =~ /^\w+$/;
1694 my $file = "Imager/File/\U$type\E.pm";
1697 my $loaded = _load_file($file, \$error);
1698 if (!$loaded && $error =~ /^Can't locate /) {
1699 my $filew = "Imager/File/\U$type\EWriter.pm";
1700 $loaded = _load_file($filew, \$error);
1701 if ($error =~ /^Can't locate /) {
1702 $error = "Can't locate $file or $filew";
1706 $writer_load_errors{$type} = $error;
1710 sub _fix_gif_positions {
1711 my ($opts, $opt, $msg, @imgs) = @_;
1713 my $positions = $opts->{'gif_positions'};
1715 for my $pos (@$positions) {
1716 my ($x, $y) = @$pos;
1717 my $img = $imgs[$index++];
1718 $img->settag(name=>'gif_left', value=>$x);
1719 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1721 $$msg .= "replaced with the gif_left and gif_top tags";
1726 gif_each_palette=>'gif_local_map',
1727 interlace => 'gif_interlace',
1728 gif_delays => 'gif_delay',
1729 gif_positions => \&_fix_gif_positions,
1730 gif_loop_count => 'gif_loop',
1733 # options that should be converted to colors
1734 my %color_opts = map { $_ => 1 } qw/i_background/;
1737 my ($self, $opts, $prefix, @imgs) = @_;
1739 for my $opt (keys %$opts) {
1741 if ($obsolete_opts{$opt}) {
1742 my $new = $obsolete_opts{$opt};
1743 my $msg = "Obsolete option $opt ";
1745 $new->($opts, $opt, \$msg, @imgs);
1748 $msg .= "replaced with the $new tag ";
1751 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1752 warn $msg if $warn_obsolete && $^W;
1754 next unless $tagname =~ /^\Q$prefix/;
1755 my $value = $opts->{$opt};
1756 if ($color_opts{$opt}) {
1757 $value = _color($value);
1759 $self->_set_error($Imager::ERRSTR);
1764 if (UNIVERSAL::isa($value, "Imager::Color")) {
1765 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1766 for my $img (@imgs) {
1767 $img->settag(name=>$tagname, value=>$tag);
1770 elsif (ref($value) eq 'ARRAY') {
1771 for my $i (0..$#$value) {
1772 my $val = $value->[$i];
1774 if (UNIVERSAL::isa($val, "Imager::Color")) {
1775 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1777 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1780 $self->_set_error("Unknown reference type " . ref($value) .
1781 " supplied in array for $opt");
1787 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1792 $self->_set_error("Unknown reference type " . ref($value) .
1793 " supplied for $opt");
1798 # set it as a tag for every image
1799 for my $img (@imgs) {
1800 $img->settag(name=>$tagname, value=>$value);
1808 # Write an image to file
1811 my %input=(jpegquality=>75,
1821 $self->_valid_image("write")
1824 $self->_set_opts(\%input, "i_", $self)
1827 my $type = $input{'type'};
1828 if (!$type and $input{file}) {
1829 $type = $FORMATGUESS->($input{file});
1832 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1836 _writer_autoload($type);
1839 if ($writers{$type} && $writers{$type}{single}) {
1840 ($IO, $fh) = $self->_get_writer_io(\%input)
1843 $writers{$type}{single}->($self, $IO, %input, type => $type)
1847 if (!$formats_low{$type}) {
1848 my $write_types = join ', ', sort Imager->write_types();
1849 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1853 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1856 if ( $type eq 'pnm' ) {
1857 $self->_set_opts(\%input, "pnm_", $self)
1859 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1860 $self->{ERRSTR} = $self->_error_as_msg();
1863 $self->{DEBUG} && print "writing a pnm file\n";
1865 elsif ( $type eq 'raw' ) {
1866 $self->_set_opts(\%input, "raw_", $self)
1868 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1869 $self->{ERRSTR} = $self->_error_as_msg();
1872 $self->{DEBUG} && print "writing a raw file\n";
1874 elsif ( $type eq 'bmp' ) {
1875 $self->_set_opts(\%input, "bmp_", $self)
1877 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1878 $self->{ERRSTR} = $self->_error_as_msg;
1881 $self->{DEBUG} && print "writing a bmp file\n";
1883 elsif ( $type eq 'tga' ) {
1884 $self->_set_opts(\%input, "tga_", $self)
1887 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1888 $self->{ERRSTR}=$self->_error_as_msg();
1891 $self->{DEBUG} && print "writing a tga file\n";
1895 if (exists $input{'data'}) {
1896 my $data = io_slurp($IO);
1898 $self->{ERRSTR}='Could not slurp from buffer';
1901 ${$input{data}} = $data;
1907 my ($class, $opts, @images) = @_;
1909 my $type = $opts->{type};
1911 if (!$type && $opts->{'file'}) {
1912 $type = $FORMATGUESS->($opts->{'file'});
1915 $class->_set_error('type parameter missing and not possible to guess from extension');
1918 # translate to ImgRaw
1920 for my $img (@images) {
1921 unless ($img->_valid_image("write_multi")) {
1922 $class->_set_error($img->errstr . " (image $index)");
1927 $class->_set_opts($opts, "i_", @images)
1929 my @work = map $_->{IMG}, @images;
1931 _writer_autoload($type);
1934 if ($writers{$type} && $writers{$type}{multiple}) {
1935 ($IO, $file) = $class->_get_writer_io($opts, $type)
1938 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1942 if (!$formats{$type}) {
1943 my $write_types = join ', ', sort Imager->write_types();
1944 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1948 ($IO, $file) = $class->_get_writer_io($opts, $type)
1951 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1955 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1960 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1966 if (exists $opts->{'data'}) {
1967 my $data = io_slurp($IO);
1969 Imager->_set_error('Could not slurp from buffer');
1972 ${$opts->{data}} = $data;
1977 # read multiple images from a file
1979 my ($class, %opts) = @_;
1981 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1984 my $type = $opts{'type'};
1986 $type = i_test_format_probe($IO, -1);
1989 if ($opts{file} && !$type) {
1991 $type = $FORMATGUESS->($opts{file});
1995 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1996 $opts{file} and $msg .= " or file name";
1997 Imager->_set_error($msg);
2001 _reader_autoload($type);
2003 if ($readers{$type} && $readers{$type}{multiple}) {
2004 return $readers{$type}{multiple}->($IO, %opts);
2007 unless ($formats{$type}) {
2008 my $read_types = join ', ', sort Imager->read_types();
2009 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2014 if ($type eq 'pnm') {
2015 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2018 my $img = Imager->new;
2019 if ($img->read(%opts, io => $IO, type => $type)) {
2022 Imager->_set_error($img->errstr);
2027 $ERRSTR = _error_as_msg();
2031 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
2035 # Destroy an Imager object
2039 # delete $instances{$self};
2040 if (defined($self->{IMG})) {
2041 # the following is now handled by the XS DESTROY method for
2042 # Imager::ImgRaw object
2043 # Re-enabling this will break virtual images
2044 # tested for in t/t020masked.t
2045 # i_img_destroy($self->{IMG});
2046 undef($self->{IMG});
2048 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2052 # Perform an inplace filter of an image
2053 # that is the image will be overwritten with the data
2060 $self->_valid_image("filter")
2063 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2065 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2066 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2069 if ($filters{$input{'type'}}{names}) {
2070 my $names = $filters{$input{'type'}}{names};
2071 for my $name (keys %$names) {
2072 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2073 $input{$name} = $names->{$name}{$input{$name}};
2077 if (defined($filters{$input{'type'}}{defaults})) {
2078 %hsh=( image => $self->{IMG},
2080 %{$filters{$input{'type'}}{defaults}},
2083 %hsh=( image => $self->{IMG},
2088 my @cs=@{$filters{$input{'type'}}{callseq}};
2091 if (!defined($hsh{$_})) {
2092 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2097 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2098 &{$filters{$input{'type'}}{callsub}}(%hsh);
2101 chomp($self->{ERRSTR} = $@);
2107 $self->{DEBUG} && print "callseq is: @cs\n";
2108 $self->{DEBUG} && print "matching callseq is: @b\n";
2113 sub register_filter {
2115 my %hsh = ( defaults => {}, @_ );
2118 or die "register_filter() with no type\n";
2119 defined $hsh{callsub}
2120 or die "register_filter() with no callsub\n";
2121 defined $hsh{callseq}
2122 or die "register_filter() with no callseq\n";
2124 exists $filters{$hsh{type}}
2127 $filters{$hsh{type}} = \%hsh;
2132 sub scale_calculate {
2135 my %opts = ('type'=>'max', @_);
2137 # none of these should be references
2138 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2139 if (defined $opts{$name} && ref $opts{$name}) {
2140 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2145 my ($x_scale, $y_scale);
2146 my $width = $opts{width};
2147 my $height = $opts{height};
2149 defined $width or $width = $self->getwidth;
2150 defined $height or $height = $self->getheight;
2153 unless (defined $width && defined $height) {
2154 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2159 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2160 $x_scale = $opts{'xscalefactor'};
2161 $y_scale = $opts{'yscalefactor'};
2163 elsif ($opts{'xscalefactor'}) {
2164 $x_scale = $opts{'xscalefactor'};
2165 $y_scale = $opts{'scalefactor'} || $x_scale;
2167 elsif ($opts{'yscalefactor'}) {
2168 $y_scale = $opts{'yscalefactor'};
2169 $x_scale = $opts{'scalefactor'} || $y_scale;
2172 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2175 # work out the scaling
2176 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2177 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2178 $opts{ypixels} / $height );
2179 if ($opts{'type'} eq 'min') {
2180 $x_scale = $y_scale = _min($xpix,$ypix);
2182 elsif ($opts{'type'} eq 'max') {
2183 $x_scale = $y_scale = _max($xpix,$ypix);
2185 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2190 $self->_set_error('invalid value for type parameter');
2193 } elsif ($opts{xpixels}) {
2194 $x_scale = $y_scale = $opts{xpixels} / $width;
2196 elsif ($opts{ypixels}) {
2197 $x_scale = $y_scale = $opts{ypixels}/$height;
2199 elsif ($opts{constrain} && ref $opts{constrain}
2200 && $opts{constrain}->can('constrain')) {
2201 # we've been passed an Image::Math::Constrain object or something
2202 # that looks like one
2204 (undef, undef, $scalefactor)
2205 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2206 unless ($scalefactor) {
2207 $self->_set_error('constrain method failed on constrain parameter');
2210 $x_scale = $y_scale = $scalefactor;
2213 my $new_width = int($x_scale * $width + 0.5);
2214 $new_width > 0 or $new_width = 1;
2215 my $new_height = int($y_scale * $height + 0.5);
2216 $new_height > 0 or $new_height = 1;
2218 return ($x_scale, $y_scale, $new_width, $new_height);
2222 # Scale an image to requested size and return the scaled version
2226 my %opts = (qtype=>'normal' ,@_);
2227 my $img = Imager->new();
2228 my $tmp = Imager->new();
2230 unless (defined wantarray) {
2231 my @caller = caller;
2232 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2236 $self->_valid_image("scale")
2239 my ($x_scale, $y_scale, $new_width, $new_height) =
2240 $self->scale_calculate(%opts)
2243 if ($opts{qtype} eq 'normal') {
2244 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2245 if ( !defined($tmp->{IMG}) ) {
2246 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2249 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2250 if ( !defined($img->{IMG}) ) {
2251 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2257 elsif ($opts{'qtype'} eq 'preview') {
2258 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2259 if ( !defined($img->{IMG}) ) {
2260 $self->{ERRSTR}='unable to scale image';
2265 elsif ($opts{'qtype'} eq 'mixing') {
2266 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2267 unless ($img->{IMG}) {
2268 $self->_set_error(Imager->_error_as_msg);
2274 $self->_set_error('invalid value for qtype parameter');
2279 # Scales only along the X axis
2283 my %opts = ( scalefactor=>0.5, @_ );
2285 unless (defined wantarray) {
2286 my @caller = caller;
2287 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2291 $self->_valid_image("scaleX")
2294 my $img = Imager->new();
2296 my $scalefactor = $opts{scalefactor};
2298 if ($opts{pixels}) {
2299 $scalefactor = $opts{pixels} / $self->getwidth();
2302 unless ($self->{IMG}) {
2303 $self->{ERRSTR}='empty input image';
2307 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2309 if ( !defined($img->{IMG}) ) {
2310 $self->{ERRSTR} = 'unable to scale image';
2317 # Scales only along the Y axis
2321 my %opts = ( scalefactor => 0.5, @_ );
2323 unless (defined wantarray) {
2324 my @caller = caller;
2325 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2329 $self->_valid_image("scaleY")
2332 my $img = Imager->new();
2334 my $scalefactor = $opts{scalefactor};
2336 if ($opts{pixels}) {
2337 $scalefactor = $opts{pixels} / $self->getheight();
2340 unless ($self->{IMG}) {
2341 $self->{ERRSTR} = 'empty input image';
2344 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2346 if ( !defined($img->{IMG}) ) {
2347 $self->{ERRSTR} = 'unable to scale image';
2354 # Transform returns a spatial transformation of the input image
2355 # this moves pixels to a new location in the returned image.
2356 # NOTE - should make a utility function to check transforms for
2362 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2364 # print Dumper(\%opts);
2367 $self->_valid_image("transform")
2370 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2372 eval ("use Affix::Infix2Postfix;");
2375 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2378 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2379 {op=>'-',trans=>'Sub'},
2380 {op=>'*',trans=>'Mult'},
2381 {op=>'/',trans=>'Div'},
2382 {op=>'-','type'=>'unary',trans=>'u-'},
2384 {op=>'func','type'=>'unary'}],
2385 'grouping'=>[qw( \( \) )],
2386 'func'=>[qw( sin cos )],
2391 @xt=$I2P->translate($opts{'xexpr'});
2392 @yt=$I2P->translate($opts{'yexpr'});
2394 $numre=$I2P->{'numre'};
2397 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2398 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2399 @{$opts{'parm'}}=@pt;
2402 # print Dumper(\%opts);
2404 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2405 $self->{ERRSTR}='transform: no xopcodes given.';
2409 @op=@{$opts{'xopcodes'}};
2411 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2412 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2415 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2421 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2422 $self->{ERRSTR}='transform: no yopcodes given.';
2426 @op=@{$opts{'yopcodes'}};
2428 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2429 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2432 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2437 if ( !exists $opts{'parm'}) {
2438 $self->{ERRSTR}='transform: no parameter arg given.';
2442 # print Dumper(\@ropx);
2443 # print Dumper(\@ropy);
2444 # print Dumper(\@ropy);
2446 my $img = Imager->new();
2447 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2448 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2454 my ($opts, @imgs) = @_;
2456 require "Imager/Expr.pm";
2458 $opts->{variables} = [ qw(x y) ];
2459 my ($width, $height) = @{$opts}{qw(width height)};
2462 for my $img (@imgs) {
2463 unless ($img->_valid_image("transform2")) {
2464 Imager->_set_error($img->errstr . " (input image $index)");
2470 $width ||= $imgs[0]->getwidth();
2471 $height ||= $imgs[0]->getheight();
2473 for my $img (@imgs) {
2474 $opts->{constants}{"w$img_num"} = $img->getwidth();
2475 $opts->{constants}{"h$img_num"} = $img->getheight();
2476 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2477 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2482 $opts->{constants}{w} = $width;
2483 $opts->{constants}{cx} = $width/2;
2486 $Imager::ERRSTR = "No width supplied";
2490 $opts->{constants}{h} = $height;
2491 $opts->{constants}{cy} = $height/2;
2494 $Imager::ERRSTR = "No height supplied";
2497 my $code = Imager::Expr->new($opts);
2499 $Imager::ERRSTR = Imager::Expr::error();
2502 my $channels = $opts->{channels} || 3;
2503 unless ($channels >= 1 && $channels <= 4) {
2504 return Imager->_set_error("channels must be an integer between 1 and 4");
2507 my $img = Imager->new();
2508 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2509 $channels, $code->code(),
2510 $code->nregs(), $code->cregs(),
2511 [ map { $_->{IMG} } @imgs ]);
2512 if (!defined $img->{IMG}) {
2513 $Imager::ERRSTR = Imager->_error_as_msg();
2524 $self->_valid_image("rubthrough")
2527 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2528 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2532 %opts = (src_minx => 0,
2534 src_maxx => $opts{src}->getwidth(),
2535 src_maxy => $opts{src}->getheight(),
2539 defined $tx or $tx = $opts{left};
2540 defined $tx or $tx = 0;
2543 defined $ty or $ty = $opts{top};
2544 defined $ty or $ty = 0;
2546 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2547 $opts{src_minx}, $opts{src_miny},
2548 $opts{src_maxx}, $opts{src_maxy})) {
2549 $self->_set_error($self->_error_as_msg());
2566 $self->_valid_image("compose")
2569 unless ($opts{src}) {
2570 $self->_set_error("compose: src parameter missing");
2574 unless ($opts{src}->_valid_image("compose")) {
2575 $self->_set_error($opts{src}->errstr . " (for src)");
2578 my $src = $opts{src};
2580 my $left = $opts{left};
2581 defined $left or $left = $opts{tx};
2582 defined $left or $left = 0;
2584 my $top = $opts{top};
2585 defined $top or $top = $opts{ty};
2586 defined $top or $top = 0;
2588 my $src_left = $opts{src_left};
2589 defined $src_left or $src_left = $opts{src_minx};
2590 defined $src_left or $src_left = 0;
2592 my $src_top = $opts{src_top};
2593 defined $src_top or $src_top = $opts{src_miny};
2594 defined $src_top or $src_top = 0;
2596 my $width = $opts{width};
2597 if (!defined $width && defined $opts{src_maxx}) {
2598 $width = $opts{src_maxx} - $src_left;
2600 defined $width or $width = $src->getwidth() - $src_left;
2602 my $height = $opts{height};
2603 if (!defined $height && defined $opts{src_maxy}) {
2604 $height = $opts{src_maxy} - $src_top;
2606 defined $height or $height = $src->getheight() - $src_top;
2608 my $combine = $self->_combine($opts{combine}, 'normal');
2611 unless ($opts{mask}->_valid_image("compose")) {
2612 $self->_set_error($opts{mask}->errstr . " (for mask)");
2616 my $mask_left = $opts{mask_left};
2617 defined $mask_left or $mask_left = $opts{mask_minx};
2618 defined $mask_left or $mask_left = 0;
2620 my $mask_top = $opts{mask_top};
2621 defined $mask_top or $mask_top = $opts{mask_miny};
2622 defined $mask_top or $mask_top = 0;
2624 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2625 $left, $top, $src_left, $src_top,
2626 $mask_left, $mask_top, $width, $height,
2627 $combine, $opts{opacity})) {
2628 $self->_set_error(Imager->_error_as_msg);
2633 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2634 $width, $height, $combine, $opts{opacity})) {
2635 $self->_set_error(Imager->_error_as_msg);
2647 $self->_valid_image("flip")
2650 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2652 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2653 $dir = $xlate{$opts{'dir'}};
2654 return $self if i_flipxy($self->{IMG}, $dir);
2662 unless (defined wantarray) {
2663 my @caller = caller;
2664 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2668 $self->_valid_image("rotate")
2671 if (defined $opts{right}) {
2672 my $degrees = $opts{right};
2674 $degrees += 360 * int(((-$degrees)+360)/360);
2676 $degrees = $degrees % 360;
2677 if ($degrees == 0) {
2678 return $self->copy();
2680 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2681 my $result = Imager->new();
2682 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2686 $self->{ERRSTR} = $self->_error_as_msg();
2691 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2695 elsif (defined $opts{radians} || defined $opts{degrees}) {
2696 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2698 my $back = $opts{back};
2699 my $result = Imager->new;
2701 $back = _color($back);
2703 $self->_set_error(Imager->errstr);
2707 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2710 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2712 if ($result->{IMG}) {
2716 $self->{ERRSTR} = $self->_error_as_msg();
2721 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2726 sub matrix_transform {
2730 $self->_valid_image("matrix_transform")
2733 unless (defined wantarray) {
2734 my @caller = caller;
2735 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2739 if ($opts{matrix}) {
2740 my $xsize = $opts{xsize} || $self->getwidth;
2741 my $ysize = $opts{ysize} || $self->getheight;
2743 my $result = Imager->new;
2745 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2746 $opts{matrix}, $opts{back})
2750 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2758 $self->{ERRSTR} = "matrix parameter required";
2764 *yatf = \&matrix_transform;
2766 # These two are supported for legacy code only
2769 return Imager::Color->new(@_);
2773 return Imager::Color::set(@_);
2776 # Draws a box between the specified corner points.
2779 my $raw = $self->{IMG};
2781 $self->_valid_image("box")
2786 my ($xmin, $ymin, $xmax, $ymax);
2787 if (exists $opts{'box'}) {
2788 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2789 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2790 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2791 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2794 defined($xmin = $opts{xmin}) or $xmin = 0;
2795 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2796 defined($ymin = $opts{ymin}) or $ymin = 0;
2797 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2800 if ($opts{filled}) {
2801 my $color = $opts{'color'};
2803 if (defined $color) {
2804 unless (_is_color_object($color)) {
2805 $color = _color($color);
2807 $self->{ERRSTR} = $Imager::ERRSTR;
2813 $color = i_color_new(255,255,255,255);
2816 if ($color->isa("Imager::Color")) {
2817 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2820 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2823 elsif ($opts{fill}) {
2824 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2825 # assume it's a hash ref
2826 require 'Imager/Fill.pm';
2827 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2828 $self->{ERRSTR} = $Imager::ERRSTR;
2832 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2835 my $color = $opts{'color'};
2836 if (defined $color) {
2837 unless (_is_color_object($color)) {
2838 $color = _color($color);
2840 $self->{ERRSTR} = $Imager::ERRSTR;
2846 $color = i_color_new(255, 255, 255, 255);
2849 $self->{ERRSTR} = $Imager::ERRSTR;
2852 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2861 $self->_valid_image("arc")
2864 my $dflcl= [ 255, 255, 255, 255];
2869 'r'=>_min($self->getwidth(),$self->getheight())/3,
2870 'x'=>$self->getwidth()/2,
2871 'y'=>$self->getheight()/2,
2878 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2879 # assume it's a hash ref
2880 require 'Imager/Fill.pm';
2881 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2882 $self->{ERRSTR} = $Imager::ERRSTR;
2886 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2887 $opts{'d2'}, $opts{fill}{fill});
2889 elsif ($opts{filled}) {
2890 my $color = _color($opts{'color'});
2892 $self->{ERRSTR} = $Imager::ERRSTR;
2895 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2896 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2900 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2901 $opts{'d1'}, $opts{'d2'}, $color);
2905 my $color = _color($opts{'color'});
2906 if ($opts{d2} - $opts{d1} >= 360) {
2907 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2910 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2916 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2917 # assume it's a hash ref
2918 require 'Imager/Fill.pm';
2919 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2920 $self->{ERRSTR} = $Imager::ERRSTR;
2924 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2925 $opts{'d2'}, $opts{fill}{fill});
2928 my $color = _color($opts{'color'});
2930 $self->{ERRSTR} = $Imager::ERRSTR;
2933 if ($opts{filled}) {
2934 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2935 $opts{'d1'}, $opts{'d2'}, $color);
2938 if ($opts{d1} == 0 && $opts{d2} == 361) {
2939 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2942 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2948 $self->_set_error($self->_error_as_msg);
2955 # Draws a line from one point to the other
2956 # the endpoint is set if the endp parameter is set which it is by default.
2957 # to turn of the endpoint being set use endp=>0 when calling line.
2961 my $dflcl=i_color_new(0,0,0,0);
2962 my %opts=(color=>$dflcl,
2966 $self->_valid_image("line")
2969 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2970 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2972 my $color = _color($opts{'color'});
2974 $self->{ERRSTR} = $Imager::ERRSTR;
2978 $opts{antialias} = $opts{aa} if defined $opts{aa};
2979 if ($opts{antialias}) {
2980 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2981 $color, $opts{endp});
2983 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2984 $color, $opts{endp});
2989 # Draws a line between an ordered set of points - It more or less just transforms this
2990 # into a list of lines.
2994 my ($pt,$ls,@points);
2995 my $dflcl=i_color_new(0,0,0,0);
2996 my %opts=(color=>$dflcl,@_);
2998 $self->_valid_image("polyline")
3001 if (exists($opts{points})) { @points=@{$opts{points}}; }
3002 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
3003 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
3006 # print Dumper(\@points);
3008 my $color = _color($opts{'color'});
3010 $self->{ERRSTR} = $Imager::ERRSTR;
3013 $opts{antialias} = $opts{aa} if defined $opts{aa};
3014 if ($opts{antialias}) {
3017 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3024 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3034 my ($pt,$ls,@points);
3035 my $dflcl = i_color_new(0,0,0,0);
3036 my %opts = (color=>$dflcl, @_);
3038 $self->_valid_image("polygon")
3041 if (exists($opts{points})) {
3042 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
3043 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
3046 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3047 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
3050 if ($opts{'fill'}) {
3051 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3052 # assume it's a hash ref
3053 require 'Imager/Fill.pm';
3054 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
3055 $self->{ERRSTR} = $Imager::ERRSTR;
3059 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
3060 $opts{'fill'}{'fill'});
3063 my $color = _color($opts{'color'});
3065 $self->{ERRSTR} = $Imager::ERRSTR;
3068 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3075 # this the multipoint bezier curve
3076 # this is here more for testing that actual usage since
3077 # this is not a good algorithm. Usually the curve would be
3078 # broken into smaller segments and each done individually.
3082 my ($pt,$ls,@points);
3083 my $dflcl=i_color_new(0,0,0,0);
3084 my %opts=(color=>$dflcl,@_);
3086 $self->_valid_image("polybezier")
3089 if (exists $opts{points}) {
3090 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3091 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3094 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3095 $self->{ERRSTR}='Missing or invalid points.';
3099 my $color = _color($opts{'color'});
3101 $self->{ERRSTR} = $Imager::ERRSTR;
3104 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3110 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3113 $self->_valid_image("flood_fill")
3116 unless (exists $opts{'x'} && exists $opts{'y'}) {
3117 $self->{ERRSTR} = "missing seed x and y parameters";
3121 if ($opts{border}) {
3122 my $border = _color($opts{border});
3124 $self->_set_error($Imager::ERRSTR);
3128 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3129 # assume it's a hash ref
3130 require Imager::Fill;
3131 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3132 $self->{ERRSTR} = $Imager::ERRSTR;
3136 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3137 $opts{fill}{fill}, $border);
3140 my $color = _color($opts{'color'});
3142 $self->{ERRSTR} = $Imager::ERRSTR;
3145 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3152 $self->{ERRSTR} = $self->_error_as_msg();
3158 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3159 # assume it's a hash ref
3160 require 'Imager/Fill.pm';
3161 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3162 $self->{ERRSTR} = $Imager::ERRSTR;
3166 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3169 my $color = _color($opts{'color'});
3171 $self->{ERRSTR} = $Imager::ERRSTR;
3174 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3180 $self->{ERRSTR} = $self->_error_as_msg();
3187 my ($self, %opts) = @_;
3189 $self->_valid_image("setpixel")
3192 my $color = $opts{color};
3193 unless (defined $color) {
3194 $color = $self->{fg};
3195 defined $color or $color = NC(255, 255, 255);
3198 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3199 unless ($color = _color($color, 'setpixel')) {
3200 $self->_set_error("setpixel: " . Imager->errstr);
3205 unless (exists $opts{'x'} && exists $opts{'y'}) {
3206 $self->_set_error('setpixel: missing x or y parameter');
3212 if (ref $x || ref $y) {
3213 $x = ref $x ? $x : [ $x ];
3214 $y = ref $y ? $y : [ $y ];
3216 $self->_set_error("setpixel: x is a reference to an empty array");
3220 $self->_set_error("setpixel: y is a reference to an empty array");
3224 # make both the same length, replicating the last element
3226 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3229 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3233 if ($color->isa('Imager::Color')) {
3234 for my $i (0..$#$x) {
3235 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3240 for my $i (0..$#$x) {
3241 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3249 if ($color->isa('Imager::Color')) {
3250 i_ppix($self->{IMG}, $x, $y, $color)
3254 i_ppixf($self->{IMG}, $x, $y, $color)
3265 my %opts = ( "type"=>'8bit', @_);
3267 $self->_valid_image("getpixel")
3270 unless (exists $opts{'x'} && exists $opts{'y'}) {
3271 $self->_set_error('getpixel: missing x or y parameter');
3277 my $type = $opts{'type'};
3278 if (ref $x || ref $y) {
3279 $x = ref $x ? $x : [ $x ];
3280 $y = ref $y ? $y : [ $y ];
3282 $self->_set_error("getpixel: x is a reference to an empty array");
3286 $self->_set_error("getpixel: y is a reference to an empty array");
3290 # make both the same length, replicating the last element
3292 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3295 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3299 if ($type eq '8bit') {
3300 for my $i (0..$#$x) {
3301 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3304 elsif ($type eq 'float' || $type eq 'double') {
3305 for my $i (0..$#$x) {
3306 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3310 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3313 return wantarray ? @result : \@result;
3316 if ($type eq '8bit') {
3317 return i_get_pixel($self->{IMG}, $x, $y);
3319 elsif ($type eq 'float' || $type eq 'double') {
3320 return i_gpixf($self->{IMG}, $x, $y);
3323 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3331 my %opts = ( type => '8bit', x=>0, @_);
3333 $self->_valid_image("getscanline")
3336 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3338 unless (defined $opts{'y'}) {
3339 $self->_set_error("missing y parameter");
3343 if ($opts{type} eq '8bit') {
3344 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3347 elsif ($opts{type} eq 'float') {
3348 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3351 elsif ($opts{type} eq 'index') {
3352 unless (i_img_type($self->{IMG})) {
3353 $self->_set_error("type => index only valid on paletted images");
3356 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3360 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3367 my %opts = ( x=>0, @_);
3369 $self->_valid_image("setscanline")
3372 unless (defined $opts{'y'}) {
3373 $self->_set_error("missing y parameter");
3378 if (ref $opts{pixels} && @{$opts{pixels}}) {
3379 # try to guess the type
3380 if ($opts{pixels}[0]->isa('Imager::Color')) {
3381 $opts{type} = '8bit';
3383 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3384 $opts{type} = 'float';
3387 $self->_set_error("missing type parameter and could not guess from pixels");
3393 $opts{type} = '8bit';
3397 if ($opts{type} eq '8bit') {
3398 if (ref $opts{pixels}) {
3399 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3402 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3405 elsif ($opts{type} eq 'float') {
3406 if (ref $opts{pixels}) {
3407 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3410 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3413 elsif ($opts{type} eq 'index') {
3414 if (ref $opts{pixels}) {
3415 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3418 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3422 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3429 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3431 $self->_valid_image("getsamples")
3434 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3436 unless (defined $opts{'y'}) {
3437 $self->_set_error("missing y parameter");
3441 if ($opts{target}) {
3442 my $target = $opts{target};
3443 my $offset = $opts{offset};
3444 if ($opts{type} eq '8bit') {
3445 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3446 $opts{y}, $opts{channels})
3448 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3449 return scalar(@samples);
3451 elsif ($opts{type} eq 'float') {
3452 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3453 $opts{y}, $opts{channels});
3454 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3455 return scalar(@samples);
3457 elsif ($opts{type} =~ /^(\d+)bit$/) {
3461 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3462 $opts{y}, $bits, $target,
3463 $offset, $opts{channels});
3464 unless (defined $count) {
3465 $self->_set_error(Imager->_error_as_msg);
3472 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3477 if ($opts{type} eq '8bit') {
3478 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3479 $opts{y}, $opts{channels});
3481 elsif ($opts{type} eq 'float') {
3482 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3483 $opts{y}, $opts{channels});
3485 elsif ($opts{type} =~ /^(\d+)bit$/) {
3489 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3490 $opts{y}, $bits, \@data, 0, $opts{channels})
3495 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3504 $self->_valid_image("setsamples")
3507 my %opts = ( x => 0, offset => 0 );
3509 # avoid duplicating the data parameter, it may be a large scalar
3511 while ($i < @_ -1) {
3512 if ($_[$i] eq 'data') {
3516 $opts{$_[$i]} = $_[$i+1];
3522 unless(defined $data_index) {
3523 $self->_set_error('setsamples: data parameter missing');
3526 unless (defined $_[$data_index]) {
3527 $self->_set_error('setsamples: data parameter not defined');
3531 my $type = $opts{type};
3532 defined $type or $type = '8bit';
3534 my $width = defined $opts{width} ? $opts{width}
3535 : $self->getwidth() - $opts{x};
3538 if ($type eq '8bit') {
3539 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3540 $_[$data_index], $opts{offset}, $width);
3542 elsif ($type eq 'float') {
3543 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3544 $_[$data_index], $opts{offset}, $width);
3546 elsif ($type =~ /^([0-9]+)bit$/) {
3549 unless (ref $_[$data_index]) {
3550 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3554 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3555 $opts{channels}, $_[$data_index], $opts{offset},
3559 $self->_set_error('setsamples: type parameter invalid');
3563 unless (defined $count) {
3564 $self->_set_error(Imager->_error_as_msg);
3571 # make an identity matrix of the given size
3575 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3576 for my $c (0 .. ($size-1)) {
3577 $matrix->[$c][$c] = 1;
3582 # general function to convert an image
3584 my ($self, %opts) = @_;
3587 $self->_valid_image("convert")
3590 unless (defined wantarray) {
3591 my @caller = caller;
3592 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3596 # the user can either specify a matrix or preset
3597 # the matrix overrides the preset
3598 if (!exists($opts{matrix})) {
3599 unless (exists($opts{preset})) {
3600 $self->{ERRSTR} = "convert() needs a matrix or preset";
3604 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3605 # convert to greyscale, keeping the alpha channel if any
3606 if ($self->getchannels == 3) {
3607 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3609 elsif ($self->getchannels == 4) {
3610 # preserve the alpha channel
3611 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3616 $matrix = _identity($self->getchannels);
3619 elsif ($opts{preset} eq 'noalpha') {
3620 # strip the alpha channel
3621 if ($self->getchannels == 2 or $self->getchannels == 4) {
3622 $matrix = _identity($self->getchannels);
3623 pop(@$matrix); # lose the alpha entry
3626 $matrix = _identity($self->getchannels);
3629 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3631 $matrix = [ [ 1 ] ];
3633 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3634 $matrix = [ [ 0, 1 ] ];
3636 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3637 $matrix = [ [ 0, 0, 1 ] ];
3639 elsif ($opts{preset} eq 'alpha') {
3640 if ($self->getchannels == 2 or $self->getchannels == 4) {
3641 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3644 # the alpha is just 1 <shrug>
3645 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3648 elsif ($opts{preset} eq 'rgb') {
3649 if ($self->getchannels == 1) {
3650 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3652 elsif ($self->getchannels == 2) {
3653 # preserve the alpha channel
3654 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3657 $matrix = _identity($self->getchannels);
3660 elsif ($opts{preset} eq 'addalpha') {
3661 if ($self->getchannels == 1) {
3662 $matrix = _identity(2);
3664 elsif ($self->getchannels == 3) {
3665 $matrix = _identity(4);
3668 $matrix = _identity($self->getchannels);
3672 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3678 $matrix = $opts{matrix};
3681 my $new = Imager->new;
3682 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3683 unless ($new->{IMG}) {
3684 # most likely a bad matrix
3685 i_push_error(0, "convert");
3686 $self->{ERRSTR} = _error_as_msg();
3692 # combine channels from multiple input images, a class method
3694 my ($class, %opts) = @_;
3696 my $src = delete $opts{src};
3698 $class->_set_error("src parameter missing");
3703 for my $img (@$src) {
3704 unless (eval { $img->isa("Imager") }) {
3705 $class->_set_error("src must contain image objects");
3708 unless ($img->_valid_image("combine")) {
3709 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3712 push @imgs, $img->{IMG};
3715 if (my $channels = delete $opts{channels}) {
3716 $result = i_combine(\@imgs, $channels);
3719 $result = i_combine(\@imgs);
3722 $class->_set_error($class->_error_as_msg);
3726 my $img = $class->new;
3727 $img->{IMG} = $result;
3733 # general function to map an image through lookup tables
3736 my ($self, %opts) = @_;
3737 my @chlist = qw( red green blue alpha );
3739 $self->_valid_image("map")
3742 if (!exists($opts{'maps'})) {
3743 # make maps from channel maps
3745 for $chnum (0..$#chlist) {
3746 if (exists $opts{$chlist[$chnum]}) {
3747 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3748 } elsif (exists $opts{'all'}) {
3749 $opts{'maps'}[$chnum] = $opts{'all'};
3753 if ($opts{'maps'} and $self->{IMG}) {
3754 i_map($self->{IMG}, $opts{'maps'} );
3760 my ($self, %opts) = @_;
3762 $self->_valid_image("difference")
3765 defined $opts{mindist} or $opts{mindist} = 0;
3767 defined $opts{other}
3768 or return $self->_set_error("No 'other' parameter supplied");
3769 unless ($opts{other}->_valid_image("difference")) {
3770 $self->_set_error($opts{other}->errstr . " (other image)");
3774 my $result = Imager->new;
3775 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3777 or return $self->_set_error($self->_error_as_msg());
3782 # destructive border - image is shrunk by one pixel all around
3785 my ($self,%opts)=@_;
3786 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3787 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3791 # Get the width of an image
3796 $self->_valid_image("getwidth")
3799 return i_img_get_width($self->{IMG});
3802 # Get the height of an image
3807 $self->_valid_image("getheight")
3810 return i_img_get_height($self->{IMG});
3813 # Get number of channels in an image
3818 $self->_valid_image("getchannels")
3821 return i_img_getchannels($self->{IMG});
3829 $self->_valid_image("getmask")
3832 return i_img_getmask($self->{IMG});
3841 $self->_valid_image("setmask")
3844 unless (defined $opts{mask}) {
3845 $self->_set_error("mask parameter required");
3849 i_img_setmask( $self->{IMG} , $opts{mask} );
3854 # Get number of colors in an image
3858 my %opts=('maxcolors'=>2**30,@_);
3860 $self->_valid_image("getcolorcount")
3863 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3864 return ($rc==-1? undef : $rc);
3867 # Returns a reference to a hash. The keys are colour named (packed) and the
3868 # values are the number of pixels in this colour.
3869 sub getcolorusagehash {
3872 $self->_valid_image("getcolorusagehash")
3875 my %opts = ( maxcolors => 2**30, @_ );
3876 my $max_colors = $opts{maxcolors};
3877 unless (defined $max_colors && $max_colors > 0) {
3878 $self->_set_error('maxcolors must be a positive integer');
3882 my $channels= $self->getchannels;
3883 # We don't want to look at the alpha channel, because some gifs using it
3884 # doesn't define it for every colour (but only for some)
3885 $channels -= 1 if $channels == 2 or $channels == 4;
3887 my $height = $self->getheight;
3888 for my $y (0 .. $height - 1) {
3889 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3890 while (length $colors) {
3891 $color_use{ substr($colors, 0, $channels, '') }++;
3893 keys %color_use > $max_colors
3899 # This will return a ordered array of the colour usage. Kind of the sorted
3900 # version of the values of the hash returned by getcolorusagehash.
3901 # You might want to add safety checks and change the names, etc...
3905 $self->_valid_image("getcolorusage")
3908 my %opts = ( maxcolors => 2**30, @_ );
3909 my $max_colors = $opts{maxcolors};
3910 unless (defined $max_colors && $max_colors > 0) {
3911 $self->_set_error('maxcolors must be a positive integer');
3915 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3918 # draw string to an image
3923 $self->_valid_image("string")
3926 my %input=('x'=>0, 'y'=>0, @_);
3927 defined($input{string}) or $input{string} = $input{text};
3929 unless(defined $input{string}) {
3930 $self->{ERRSTR}="missing required parameter 'string'";
3934 unless($input{font}) {
3935 $self->{ERRSTR}="missing required parameter 'font'";
3939 unless ($input{font}->draw(image=>$self, %input)) {
3951 $self->_valid_image("align_string")
3960 my %input=('x'=>0, 'y'=>0, @_);
3961 defined $input{string}
3962 or $input{string} = $input{text};
3964 unless(exists $input{string}) {
3965 $self->_set_error("missing required parameter 'string'");
3969 unless($input{font}) {
3970 $self->_set_error("missing required parameter 'font'");
3975 unless (@result = $input{font}->align(image=>$img, %input)) {
3979 return wantarray ? @result : $result[0];
3982 my @file_limit_names = qw/width height bytes/;
3984 sub set_file_limits {
3991 @values{@file_limit_names} = (0) x @file_limit_names;
3994 @values{@file_limit_names} = i_get_image_file_limits();
3997 for my $key (keys %values) {
3998 defined $opts{$key} and $values{$key} = $opts{$key};
4001 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4004 sub get_file_limits {
4005 i_get_image_file_limits();
4008 my @check_args = qw(width height channels sample_size);
4010 sub check_file_limits {
4020 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4021 $opts{sample_size} = length(pack("d", 0));
4024 for my $name (@check_args) {
4025 unless (defined $opts{$name}) {
4026 $class->_set_error("check_file_limits: $name must be defined");
4029 unless ($opts{$name} == int($opts{$name})) {
4030 $class->_set_error("check_file_limits: $name must be a positive integer");
4035 my $result = i_int_check_image_file_limits(@opts{@check_args});
4037 $class->_set_error($class->_error_as_msg());
4043 # Shortcuts that can be exported
4045 sub newcolor { Imager::Color->new(@_); }
4046 sub newfont { Imager::Font->new(@_); }
4048 require Imager::Color::Float;
4049 return Imager::Color::Float->new(@_);
4052 *NC=*newcolour=*newcolor;
4059 #### Utility routines
4062 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4066 my ($self, $msg) = @_;
4069 $self->{ERRSTR} = $msg;
4077 # Default guess for the type of an image from extension
4079 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
4083 ( map { $_ => $_ } @simple_types ),
4089 pnm => "pnm", # technically wrong, but historically it works in Imager
4102 sub def_guess_type {
4105 my ($ext) = $name =~ /\.([^.]+)$/
4108 my $type = $ext_types{$ext}
4115 return @combine_types;
4118 # get the minimum of a list
4122 for(@_) { if ($_<$mx) { $mx=$_; }}
4126 # get the maximum of a list
4130 for(@_) { if ($_>$mx) { $mx=$_; }}
4134 # string stuff for iptc headers
4138 $str = substr($str,3);
4139 $str =~ s/[\n\r]//g;
4146 # A little hack to parse iptc headers.
4151 my($caption,$photogr,$headln,$credit);
4153 my $str=$self->{IPTCRAW};
4158 @ar=split(/8BIM/,$str);
4163 @sar=split(/\034\002/);
4164 foreach $item (@sar) {
4165 if ($item =~ m/^x/) {
4166 $caption = _clean($item);
4169 if ($item =~ m/^P/) {
4170 $photogr = _clean($item);
4173 if ($item =~ m/^i/) {
4174 $headln = _clean($item);
4177 if ($item =~ m/^n/) {
4178 $credit = _clean($item);
4184 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4191 or die "Only C language supported";
4193 require Imager::ExtUtils;
4194 return Imager::ExtUtils->inline_config;
4197 # threads shouldn't try to close raw Imager objects
4198 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4201 # this serves two purposes:
4202 # - a class method to load the file support modules included with Imager
4203 # (or were included, once the library dependent modules are split out)
4204 # - something for Module::ScanDeps to analyze
4205 # https://rt.cpan.org/Ticket/Display.html?id=6566
4207 eval { require Imager::File::GIF };
4208 eval { require Imager::File::JPEG };
4209 eval { require Imager::File::PNG };
4210 eval { require Imager::File::SGI };
4211 eval { require Imager::File::TIFF };
4212 eval { require Imager::File::ICO };
4213 eval { require Imager::Font::W32 };
4214 eval { require Imager::Font::FT2 };
4215 eval { require Imager::Font::T1 };
4218 # backward compatibility for %formats
4219 package Imager::FORMATS;
4221 use constant IX_FORMATS => 0;
4222 use constant IX_LIST => 1;
4223 use constant IX_INDEX => 2;
4224 use constant IX_CLASSES => 3;
4227 my ($class, $formats, $classes) = @_;
4229 return bless [ $formats, [ ], 0, $classes ], $class;
4233 my ($self, $key) = @_;
4235 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4238 my $loaded = Imager::_load_file($file, \$error);
4243 if ($error =~ /^Can't locate /) {
4244 $error = "Can't locate $file";
4246 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4249 $self->[IX_FORMATS]{$key} = $value;
4255 my ($self, $key) = @_;
4257 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4259 $self->[IX_CLASSES]{$key} or return undef;
4261 return $self->_check($key);
4265 die "%Imager::formats is not user monifiable";
4269 die "%Imager::formats is not user monifiable";
4273 die "%Imager::formats is not user monifiable";
4277 my ($self, $key) = @_;
4279 if (exists $self->[IX_FORMATS]{$key}) {
4280 my $value = $self->[IX_FORMATS]{$key}
4285 $self->_check($key) or return 1==0;
4293 unless (@{$self->[IX_LIST]}) {
4295 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4296 keys %{$self->[IX_FORMATS]};
4298 for my $key (keys %{$self->[IX_CLASSES]}) {
4299 $self->[IX_FORMATS]{$key} and next;
4301 and push @{$self->[IX_LIST]}, $key;
4305 @{$self->[IX_LIST]} or return;
4306 $self->[IX_INDEX] = 1;
4307 return $self->[IX_LIST][0];
4313 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4316 return $self->[IX_LIST][$self->[IX_INDEX]++];
4322 return scalar @{$self->[IX_LIST]};
4327 # Below is the stub of documentation for your module. You better edit it!
4331 Imager - Perl extension for Generating 24 bit Images
4341 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4346 # see Imager::Files for information on the read() method
4347 my $img = Imager->new(file=>$file)
4348 or die Imager->errstr();
4350 $file =~ s/\.[^.]*$//;
4352 # Create smaller version
4353 # documented in Imager::Transformations
4354 my $thumb = $img->scale(scalefactor=>.3);
4356 # Autostretch individual channels
4357 $thumb->filter(type=>'autolevels');
4359 # try to save in one of these formats
4362 for $format ( qw( png gif jpeg tiff ppm ) ) {
4363 # Check if given format is supported
4364 if ($Imager::formats{$format}) {
4365 $file.="_low.$format";
4366 print "Storing image as: $file\n";
4367 # documented in Imager::Files
4368 $thumb->write(file=>$file) or
4376 Imager is a module for creating and altering images. It can read and
4377 write various image formats, draw primitive shapes like lines,and
4378 polygons, blend multiple images together in various ways, scale, crop,
4379 render text and more.
4381 =head2 Overview of documentation
4387 Imager - This document - Synopsis, Example, Table of Contents and
4392 L<Imager::Tutorial> - a brief introduction to Imager.
4396 L<Imager::Cookbook> - how to do various things with Imager.
4400 L<Imager::ImageTypes> - Basics of constructing image objects with
4401 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4402 8/16/double bits/channel, color maps, channel masks, image tags, color
4403 quantization. Also discusses basic image information methods.
4407 L<Imager::Files> - IO interaction, reading/writing images, format
4412 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4417 L<Imager::Color> - Color specification.
4421 L<Imager::Fill> - Fill pattern specification.
4425 L<Imager::Font> - General font rendering, bounding boxes and font
4430 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4431 blending, pasting, convert and map.
4435 L<Imager::Engines> - Programmable transformations through
4436 C<transform()>, C<transform2()> and C<matrix_transform()>.
4440 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4445 L<Imager::Expr> - Expressions for evaluation engine used by
4450 L<Imager::Matrix2d> - Helper class for affine transformations.
4454 L<Imager::Fountain> - Helper for making gradient profiles.
4458 L<Imager::API> - using Imager's C API
4462 L<Imager::APIRef> - API function reference
4466 L<Imager::Inline> - using Imager's C API from Inline::C
4470 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4474 L<Imager::Security> - brief security notes.
4478 L<Imager::Threads> - brief information on working with threads.
4482 =head2 Basic Overview
4484 An Image object is created with C<$img = Imager-E<gt>new()>.
4487 $img=Imager->new(); # create empty image
4488 $img->read(file=>'lena.png',type=>'png') or # read image from file
4489 die $img->errstr(); # give an explanation
4490 # if something failed
4492 or if you want to create an empty image:
4494 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4496 This example creates a completely black image of width 400 and height
4499 =head1 ERROR HANDLING
4501 In general a method will return false when it fails, if it does use
4502 the C<errstr()> method to find out why:
4508 Returns the last error message in that context.
4510 If the last error you received was from calling an object method, such
4511 as read, call errstr() as an object method to find out why:
4513 my $image = Imager->new;
4514 $image->read(file => 'somefile.gif')
4515 or die $image->errstr;
4517 If it was a class method then call errstr() as a class method:
4519 my @imgs = Imager->read_multi(file => 'somefile.gif')
4520 or die Imager->errstr;
4522 Note that in some cases object methods are implemented in terms of
4523 class methods so a failing object method may set both.
4527 The C<Imager-E<gt>new> method is described in detail in
4528 L<Imager::ImageTypes>.
4532 Where to find information on methods for Imager class objects.
4534 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4537 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4539 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4542 arc() - L<Imager::Draw/arc()> - draw a filled arc
4544 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4547 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4549 check_file_limits() - L<Imager::Files/check_file_limits()>
4551 circle() - L<Imager::Draw/circle()> - draw a filled circle
4553 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4556 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4557 colors in an image's palette (paletted images only)
4559 combine() - L<Imager::Transformations/combine()> - combine channels
4560 from one or more images.
4562 combines() - L<Imager::Draw/combines()> - return a list of the
4563 different combine type keywords
4565 compose() - L<Imager::Transformations/compose()> - compose one image
4568 convert() - L<Imager::Transformations/convert()> - transform the color
4571 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4574 crop() - L<Imager::Transformations/crop()> - extract part of an image
4576 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4577 used to guess the output file format based on the output file name
4579 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4581 difference() - L<Imager::Filters/difference()> - produce a difference
4582 images from two input images.
4584 errstr() - L</errstr()> - the error from the last failed operation.
4586 filter() - L<Imager::Filters/filter()> - image filtering
4588 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4589 palette, if it has one
4591 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4594 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4597 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4598 samples per pixel for an image
4600 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4601 different colors used by an image (works for direct color images)
4603 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4604 palette, if it has one
4606 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4608 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4610 get_file_limits() - L<Imager::Files/get_file_limits()>
4612 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4615 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4617 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4620 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4621 row or partial row of pixels.
4623 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4624 row or partial row of pixels.
4626 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4629 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4632 init() - L<Imager::ImageTypes/init()>
4634 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4635 image write functions should write the image in their bilevel (blank
4636 and white, no gray levels) format
4638 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4641 line() - L<Imager::Draw/line()> - draw an interval
4643 load_plugin() - L<Imager::Filters/load_plugin()>
4645 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4648 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4649 color palette from one or more input images.
4651 map() - L<Imager::Transformations/map()> - remap color
4654 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4656 matrix_transform() - L<Imager::Engines/matrix_transform()>
4658 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4660 NC() - L<Imager::Handy/NC()>
4662 NCF() - L<Imager::Handy/NCF()>
4664 new() - L<Imager::ImageTypes/new()>
4666 newcolor() - L<Imager::Handy/newcolor()>
4668 newcolour() - L<Imager::Handy/newcolour()>
4670 newfont() - L<Imager::Handy/newfont()>
4672 NF() - L<Imager::Handy/NF()>
4674 open() - L<Imager::Files/read()> - an alias for read()
4676 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4680 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4683 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4686 polygon() - L<Imager::Draw/polygon()>
4688 polyline() - L<Imager::Draw/polyline()>
4690 preload() - L<Imager::Files/preload()>
4692 read() - L<Imager::Files/read()> - read a single image from an image file
4694 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4697 read_types() - L<Imager::Files/read_types()> - list image types Imager
4700 register_filter() - L<Imager::Filters/register_filter()>
4702 register_reader() - L<Imager::Files/register_reader()>
4704 register_writer() - L<Imager::Files/register_writer()>
4706 rotate() - L<Imager::Transformations/rotate()>
4708 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4709 onto an image and use the alpha channel
4711 scale() - L<Imager::Transformations/scale()>
4713 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4715 scaleX() - L<Imager::Transformations/scaleX()>
4717 scaleY() - L<Imager::Transformations/scaleY()>
4719 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4722 set_file_limits() - L<Imager::Files/set_file_limits()>
4724 setmask() - L<Imager::ImageTypes/setmask()>
4726 setpixel() - L<Imager::Draw/setpixel()>
4728 setsamples() - L<Imager::Draw/setsamples()>
4730 setscanline() - L<Imager::Draw/setscanline()>
4732 settag() - L<Imager::ImageTypes/settag()>
4734 string() - L<Imager::Draw/string()> - draw text on an image
4736 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4738 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4740 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4742 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4744 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4745 double per sample image.
4747 transform() - L<Imager::Engines/"transform()">
4749 transform2() - L<Imager::Engines/"transform2()">
4751 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4753 unload_plugin() - L<Imager::Filters/unload_plugin()>
4755 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4758 write() - L<Imager::Files/write()> - write an image to a file
4760 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4763 write_types() - L<Imager::Files/read_types()> - list image types Imager
4766 =head1 CONCEPT INDEX
4768 animated GIF - L<Imager::Files/"Writing an animated GIF">
4770 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4771 L<Imager::ImageTypes/"Common Tags">.
4773 blend - alpha blending one image onto another
4774 L<Imager::Transformations/rubthrough()>
4776 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4778 boxes, drawing - L<Imager::Draw/box()>
4780 changes between image - L<Imager::Filters/"Image Difference">
4782 channels, combine into one image - L<Imager::Transformations/combine()>
4784 color - L<Imager::Color>
4786 color names - L<Imager::Color>, L<Imager::Color::Table>
4788 combine modes - L<Imager::Draw/"Combine Types">
4790 compare images - L<Imager::Filters/"Image Difference">
4792 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4794 convolution - L<Imager::Filters/conv>
4796 cropping - L<Imager::Transformations/crop()>
4798 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4800 C<diff> images - L<Imager::Filters/"Image Difference">
4802 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4803 L<Imager::Cookbook/"Image spatial resolution">
4805 drawing boxes - L<Imager::Draw/box()>
4807 drawing lines - L<Imager::Draw/line()>
4809 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4811 error message - L</"ERROR HANDLING">
4813 files, font - L<Imager::Font>
4815 files, image - L<Imager::Files>
4817 filling, types of fill - L<Imager::Fill>
4819 filling, boxes - L<Imager::Draw/box()>
4821 filling, flood fill - L<Imager::Draw/flood_fill()>
4823 flood fill - L<Imager::Draw/flood_fill()>
4825 fonts - L<Imager::Font>
4827 fonts, drawing with - L<Imager::Draw/string()>,
4828 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4830 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4832 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4834 fountain fill - L<Imager::Fill/"Fountain fills">,
4835 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4836 L<Imager::Filters/gradgen>
4838 GIF files - L<Imager::Files/"GIF">
4840 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4842 gradient fill - L<Imager::Fill/"Fountain fills">,
4843 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4844 L<Imager::Filters/gradgen>
4846 gray scale, convert image to - L<Imager::Transformations/convert()>
4848 gaussian blur - L<Imager::Filters/gaussian>
4850 hatch fills - L<Imager::Fill/"Hatched fills">
4852 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4854 invert image - L<Imager::Filters/hardinvert>,
4855 L<Imager::Filters/hardinvertall>
4857 JPEG - L<Imager::Files/"JPEG">
4859 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4861 lines, drawing - L<Imager::Draw/line()>
4863 matrix - L<Imager::Matrix2d>,
4864 L<Imager::Engines/"Matrix Transformations">,
4865 L<Imager::Font/transform()>
4867 metadata, image - L<Imager::ImageTypes/"Tags">, L<Image::ExifTool>
4869 mosaic - L<Imager::Filters/mosaic>
4871 noise, filter - L<Imager::Filters/noise>
4873 noise, rendered - L<Imager::Filters/turbnoise>,
4874 L<Imager::Filters/radnoise>
4876 paste - L<Imager::Transformations/paste()>,
4877 L<Imager::Transformations/rubthrough()>
4879 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4880 L<Imager::ImageTypes/new()>
4882 =for stopwords posterize
4884 posterize - L<Imager::Filters/postlevels>
4886 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4888 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4890 rectangles, drawing - L<Imager::Draw/box()>
4892 resizing an image - L<Imager::Transformations/scale()>,
4893 L<Imager::Transformations/crop()>
4895 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4897 saving an image - L<Imager::Files>
4899 scaling - L<Imager::Transformations/scale()>
4901 security - L<Imager::Security>
4903 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4905 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4907 size, image - L<Imager::ImageTypes/getwidth()>,
4908 L<Imager::ImageTypes/getheight()>
4910 size, text - L<Imager::Font/bounding_box()>
4912 tags, image metadata - L<Imager::ImageTypes/"Tags">
4914 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4915 L<Imager::Font::Wrap>
4917 text, wrapping text in an area - L<Imager::Font::Wrap>
4919 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4921 threads - L<Imager::Threads>
4923 tiles, color - L<Imager::Filters/mosaic>
4925 transparent images - L<Imager::ImageTypes>,
4926 L<Imager::Cookbook/"Transparent PNG">
4928 =for stopwords unsharp
4930 unsharp mask - L<Imager::Filters/unsharpmask>
4932 watermark - L<Imager::Filters/watermark>
4934 writing an image to a file - L<Imager::Files>
4938 The best place to get help with Imager is the mailing list.
4940 To subscribe send a message with C<subscribe> in the body to:
4942 imager-devel+request@molar.is
4948 L<http://www.molar.is/en/lists/imager-devel/>
4952 where you can also find the mailing list archive.
4954 You can report bugs by pointing your browser at:
4958 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4962 or by sending an email to:
4966 bug-Imager@rt.cpan.org
4970 Please remember to include the versions of Imager, perl, supporting
4971 libraries, and any relevant code. If you have specific images that
4972 cause the problems, please include those too.
4974 If you don't want to publish your email address on a mailing list you
4975 can use CPAN::Forum:
4977 http://www.cpanforum.com/dist/Imager
4979 You will need to register to post.
4981 =head1 CONTRIBUTING TO IMAGER
4987 If you like or dislike Imager, you can add a public review of Imager
4990 http://cpanratings.perl.org/dist/Imager
4992 =for stopwords Bitcard
4994 This requires a Bitcard account (http://www.bitcard.org).
4996 You can also send email to the maintainer below.
4998 If you send me a bug report via email, it will be copied to Request
5003 I accept patches, preferably against the master branch in git. Please
5004 include an explanation of the reason for why the patch is needed or
5007 Your patch should include regression tests where possible, otherwise
5008 it will be delayed until I get a chance to write them.
5010 To browse Imager's git repository:
5012 http://git.imager.perl.org/imager.git
5016 https://github.com/tonycoz/imager
5020 git clone git://git.imager.perl.org/imager.git
5024 git clone git://github.com/tonycoz/imager.git
5028 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
5030 Arnar M. Hrafnkelsson is the original author of Imager.
5032 Many others have contributed to Imager, please see the C<README> for a
5037 Imager is licensed under the same terms as perl itself.
5040 makeblendedfont Fontforge
5042 A test font, generated by the Debian packaged Fontforge,
5043 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
5044 copyrighted by Adobe. See F<adobe.txt> in the source for license
5049 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
5050 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
5051 L<Imager::Font>(3), L<Imager::Transformations>(3),
5052 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
5053 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
5055 L<http://imager.perl.org/>
5057 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
5059 Other perl imaging modules include:
5061 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3),
5062 L<Prima::Image>, L<IPA>.
5064 For manipulating image metadata see L<Image::ExifTool>.
5066 If you're trying to use Imager for array processing, you should
5067 probably using L<PDL>.