4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
113 # registered file readers
116 # registered file writers
119 # modules we attempted to autoload
120 my %attempted_to_load;
122 # errors from loading files
123 my %file_load_errors;
125 # what happened when we tried to load
126 my %reader_load_errors;
127 my %writer_load_errors;
129 # library keys that are image file formats
130 my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
132 # image pixel combine types
134 qw/none normal multiply dissolve add subtract diff lighten darken
135 hue saturation value color/;
137 @combine_types{@combine_types} = 0 .. $#combine_types;
138 $combine_types{mult} = $combine_types{multiply};
139 $combine_types{'sub'} = $combine_types{subtract};
140 $combine_types{sat} = $combine_types{saturation};
142 # this will be used to store global defaults at some point
147 my $ex_version = eval $Exporter::VERSION;
148 if ($ex_version < 5.57) {
153 XSLoader::load(Imager => $VERSION);
159 png => "Imager::File::PNG",
160 gif => "Imager::File::GIF",
161 tiff => "Imager::File::TIFF",
162 jpeg => "Imager::File::JPEG",
163 w32 => "Imager::Font::W32",
164 ft2 => "Imager::Font::FT2",
165 t1 => "Imager::Font::T1",
168 tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
171 for(i_list_formats()) { $formats_low{$_}++; }
173 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
177 # the members of the subhashes under %filters are:
178 # callseq - a list of the parameters to the underlying filter in the
179 # order they are passed
180 # callsub - a code ref that takes a named parameter list and calls the
182 # defaults - a hash of default values
183 # names - defines names for value of given parameters so if the names
184 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
185 # foo parameter, the filter will receive 1 for the foo
188 callseq => ['image','intensity'],
189 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
193 callseq => ['image', 'amount', 'subtype'],
194 defaults => { amount=>3,subtype=>0 },
195 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
198 $filters{hardinvert} ={
199 callseq => ['image'],
201 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
204 $filters{hardinvertall} =
206 callseq => ['image'],
208 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
211 $filters{autolevels} ={
212 callseq => ['image','lsat','usat','skew'],
213 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
214 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
217 $filters{turbnoise} ={
218 callseq => ['image'],
219 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
220 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
223 $filters{radnoise} ={
224 callseq => ['image'],
225 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
226 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
231 callseq => ['image', 'coef'],
236 i_conv($hsh{image},$hsh{coef})
237 or die Imager->_error_as_msg() . "\n";
243 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
244 defaults => { dist => 0 },
248 my @colors = @{$hsh{colors}};
251 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
255 $filters{nearest_color} =
257 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
262 # make sure the segments are specified with colors
264 for my $color (@{$hsh{colors}}) {
265 my $new_color = _color($color)
266 or die $Imager::ERRSTR."\n";
267 push @colors, $new_color;
270 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
272 or die Imager->_error_as_msg() . "\n";
275 $filters{gaussian} = {
276 callseq => [ 'image', 'stddev' ],
278 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
282 callseq => [ qw(image size) ],
283 defaults => { size => 20 },
284 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
288 callseq => [ qw(image bump elevation lightx lighty st) ],
289 defaults => { elevation=>0, st=> 2 },
292 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
293 $hsh{lightx}, $hsh{lighty}, $hsh{st});
296 $filters{bumpmap_complex} =
298 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
315 for my $cname (qw/Ia Il Is/) {
316 my $old = $hsh{$cname};
317 my $new_color = _color($old)
318 or die $Imager::ERRSTR, "\n";
319 $hsh{$cname} = $new_color;
321 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
322 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
323 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
327 $filters{postlevels} =
329 callseq => [ qw(image levels) ],
330 defaults => { levels => 10 },
331 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
333 $filters{watermark} =
335 callseq => [ qw(image wmark tx ty pixdiff) ],
336 defaults => { pixdiff=>10, tx=>0, ty=>0 },
340 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
346 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
348 ftype => { linear => 0,
354 repeat => { none => 0,
369 multiply => 2, mult => 2,
372 subtract => 5, 'sub' => 5,
382 defaults => { ftype => 0, repeat => 0, combine => 0,
383 super_sample => 0, ssample_param => 4,
396 # make sure the segments are specified with colors
398 for my $segment (@{$hsh{segments}}) {
399 my @new_segment = @$segment;
401 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
402 push @segments, \@new_segment;
405 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
406 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
407 $hsh{ssample_param}, \@segments)
408 or die Imager->_error_as_msg() . "\n";
411 $filters{unsharpmask} =
413 callseq => [ qw(image stddev scale) ],
414 defaults => { stddev=>2.0, scale=>1.0 },
418 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
422 $FORMATGUESS=\&def_guess_type;
432 # NOTE: this might be moved to an import override later on
437 if ($_[$i] eq '-log-stderr') {
445 goto &Exporter::import;
449 Imager->open_log(log => $_[0], level => $_[1]);
454 my %parms=(loglevel=>1,@_);
456 if (exists $parms{'warn_obsolete'}) {
457 $warn_obsolete = $parms{'warn_obsolete'};
461 Imager->open_log(log => $parms{log}, level => $parms{loglevel})
465 if (exists $parms{'t1log'}) {
467 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
468 Imager->_set_error(Imager->_error_as_msg);
482 my (%opts) = ( loglevel => 1, @_ );
484 $is_logging = i_init_log($opts{log}, $opts{loglevel});
485 unless ($is_logging) {
486 Imager->_set_error(Imager->_error_as_msg());
490 Imager->log("Imager $VERSION starting\n", 1);
496 i_init_log(undef, -1);
501 my ($class, $message, $level) = @_;
503 defined $level or $level = 1;
505 i_log_entry($message, $level);
515 print "shutdown code\n";
516 # for(keys %instances) { $instances{$_}->DESTROY(); }
517 malloc_state(); # how do decide if this should be used? -- store something from the import
518 print "Imager exiting\n";
522 # Load a filter plugin
527 my ($DSO_handle,$str)=DSO_open($filename);
528 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
529 my %funcs=DSO_funclist($DSO_handle);
530 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
532 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
534 $DSOs{$filename}=[$DSO_handle,\%funcs];
537 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
538 $DEBUG && print "eval string:\n",$evstr,"\n";
550 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
551 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
552 for(keys %{$funcref}) {
554 $DEBUG && print "unloading: $_\n";
556 my $rc=DSO_close($DSO_handle);
557 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
561 # take the results of i_error() and make a message out of it
563 return join(": ", map $_->[0], i_errors());
566 # this function tries to DWIM for color parameters
567 # color objects are used as is
568 # simple scalars are simply treated as single parameters to Imager::Color->new
569 # hashrefs are treated as named argument lists to Imager::Color->new
570 # arrayrefs are treated as list arguments to Imager::Color->new iff any
572 # other arrayrefs are treated as list arguments to Imager::Color::Float
576 # perl 5.6.0 seems to do weird things to $arg if we don't make an
577 # explicitly stringified copy
578 # I vaguely remember a bug on this on p5p, but couldn't find it
579 # through bugs.perl.org (I had trouble getting it to find any bugs)
580 my $copy = $arg . "";
584 if (UNIVERSAL::isa($arg, "Imager::Color")
585 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
589 if ($copy =~ /^HASH\(/) {
590 $result = Imager::Color->new(%$arg);
592 elsif ($copy =~ /^ARRAY\(/) {
593 $result = Imager::Color->new(@$arg);
596 $Imager::ERRSTR = "Not a color";
601 # assume Imager::Color::new knows how to handle it
602 $result = Imager::Color->new($arg);
609 my ($self, $combine, $default) = @_;
611 if (!defined $combine && ref $self) {
612 $combine = $self->{combine};
614 defined $combine or $combine = $defaults{combine};
615 defined $combine or $combine = $default;
617 if (exists $combine_types{$combine}) {
618 $combine = $combine_types{$combine};
625 my ($self, $method) = @_;
627 $self->{IMG} and return 1;
629 my $msg = 'empty input image';
630 $msg = "$method: $msg" if $method;
631 $self->_set_error($msg);
636 # returns first defined parameter
639 return $_ if defined $_;
645 # Methods to be called on objects.
648 # Create a new Imager object takes very few parameters.
649 # usually you call this method and then call open from
650 # the resulting object
657 $self->{IMG}=undef; # Just to indicate what exists
658 $self->{ERRSTR}=undef; #
659 $self->{DEBUG}=$DEBUG;
660 $self->{DEBUG} and print "Initialized Imager\n";
661 if (defined $hsh{xsize} || defined $hsh{ysize}) {
662 unless ($self->img_set(%hsh)) {
663 $Imager::ERRSTR = $self->{ERRSTR};
667 elsif (defined $hsh{file} ||
670 defined $hsh{callback} ||
671 defined $hsh{readcb} ||
672 defined $hsh{data}) {
673 # allow $img = Imager->new(file => $filename)
676 # type is already used as a parameter to new(), rename it for the
678 if ($hsh{filetype}) {
679 $extras{type} = $hsh{filetype};
681 unless ($self->read(%hsh, %extras)) {
682 $Imager::ERRSTR = $self->{ERRSTR};
690 # Copy an entire image with no changes
691 # - if an image has magic the copy of it will not be magical
695 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
697 unless (defined wantarray) {
699 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
703 my $newcopy=Imager->new();
704 $newcopy->{IMG} = i_copy($self->{IMG});
713 unless ($self->{IMG}) {
714 $self->_set_error('empty input image');
717 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
718 my $src = $input{img} || $input{src};
720 $self->_set_error("no source image");
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
781 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
783 unless (defined wantarray) {
785 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
791 my ($w, $h, $l, $r, $b, $t) =
792 @hsh{qw(width height left right bottom top)};
794 # work through the various possibilities
799 elsif (!defined $r) {
800 $r = $self->getwidth;
812 $l = int(0.5+($self->getwidth()-$w)/2);
817 $r = $self->getwidth;
823 elsif (!defined $b) {
824 $b = $self->getheight;
836 $t=int(0.5+($self->getheight()-$h)/2);
841 $b = $self->getheight;
844 ($l,$r)=($r,$l) if $l>$r;
845 ($t,$b)=($b,$t) if $t>$b;
848 $r > $self->getwidth and $r = $self->getwidth;
850 $b > $self->getheight and $b = $self->getheight;
852 if ($l == $r || $t == $b) {
853 $self->_set_error("resulting image would have no content");
856 if( $r < $l or $b < $t ) {
857 $self->_set_error("attempting to crop outside of the image");
860 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
862 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
867 my ($self, %opts) = @_;
869 $self->{IMG} or return $self->_set_error("Not a valid image");
871 my $x = $opts{xsize} || $self->getwidth;
872 my $y = $opts{ysize} || $self->getheight;
873 my $channels = $opts{channels} || $self->getchannels;
875 my $out = Imager->new;
876 if ($channels == $self->getchannels) {
877 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
880 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
882 unless ($out->{IMG}) {
883 $self->{ERRSTR} = $self->_error_as_msg;
890 # Sets an image to a certain size and channel number
891 # if there was previously data in the image it is discarded
896 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
898 if (defined($self->{IMG})) {
899 # let IIM_DESTROY destroy it, it's possible this image is
900 # referenced from a virtual image (like masked)
901 #i_img_destroy($self->{IMG});
905 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
906 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
907 $hsh{maxcolors} || 256);
909 elsif ($hsh{bits} eq 'double') {
910 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
912 elsif ($hsh{bits} == 16) {
913 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
916 $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
920 unless ($self->{IMG}) {
921 $self->{ERRSTR} = Imager->_error_as_msg();
928 # created a masked version of the current image
932 $self or return undef;
933 my %opts = (left => 0,
935 right => $self->getwidth,
936 bottom => $self->getheight,
938 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
940 my $result = Imager->new;
941 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
942 $opts{top}, $opts{right} - $opts{left},
943 $opts{bottom} - $opts{top});
944 unless ($result->{IMG}) {
945 $self->_set_error(Imager->_error_as_msg);
949 # keep references to the mask and base images so they don't
951 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
956 # convert an RGB image into a paletted image
960 if (@_ != 1 && !ref $_[0]) {
967 unless (defined wantarray) {
969 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
976 my $result = Imager->new;
977 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
978 $self->_set_error(Imager->_error_as_msg);
986 my ($class, $quant, @images) = @_;
989 Imager->_set_error("make_palette: supply at least one image");
993 for my $img (@images) {
994 unless ($img->{IMG}) {
995 Imager->_set_error("make_palette: image $index is empty");
1001 return i_img_make_palette($quant, map $_->{IMG}, @images);
1004 # convert a paletted (or any image) to an 8-bit/channel RGB image
1008 unless (defined wantarray) {
1009 my @caller = caller;
1010 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1017 my $result = Imager->new;
1018 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1019 $self->_set_error(Imager->_error_as_msg());
1026 # convert a paletted (or any image) to a 16-bit/channel RGB image
1030 unless (defined wantarray) {
1031 my @caller = caller;
1032 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1039 my $result = Imager->new;
1040 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1041 $self->_set_error(Imager->_error_as_msg());
1048 # convert a paletted (or any image) to an double/channel RGB image
1052 unless (defined wantarray) {
1053 my @caller = caller;
1054 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1061 my $result = Imager->new;
1062 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1063 $self->_set_error(Imager->_error_as_msg());
1072 my %opts = (colors=>[], @_);
1074 unless ($self->{IMG}) {
1075 $self->_set_error("empty input image");
1079 my @colors = @{$opts{colors}}
1082 for my $color (@colors) {
1083 $color = _color($color);
1085 $self->_set_error($Imager::ERRSTR);
1090 return i_addcolors($self->{IMG}, @colors);
1095 my %opts = (start=>0, colors=>[], @_);
1097 unless ($self->{IMG}) {
1098 $self->_set_error("empty input image");
1102 my @colors = @{$opts{colors}}
1105 for my $color (@colors) {
1106 $color = _color($color);
1108 $self->_set_error($Imager::ERRSTR);
1113 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1119 if (!exists $opts{start} && !exists $opts{count}) {
1122 $opts{count} = $self->colorcount;
1124 elsif (!exists $opts{count}) {
1127 elsif (!exists $opts{start}) {
1132 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1136 i_colorcount($_[0]{IMG});
1140 i_maxcolors($_[0]{IMG});
1146 $opts{color} or return undef;
1148 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1153 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1154 if ($bits && $bits == length(pack("d", 1)) * 8) {
1163 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1169 $self->{IMG} and i_img_virtual($self->{IMG});
1175 $self->{IMG} or return;
1177 return i_img_is_monochrome($self->{IMG});
1181 my ($self, %opts) = @_;
1183 $self->{IMG} or return;
1185 if (defined $opts{name}) {
1189 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1190 push @result, (i_tags_get($self->{IMG}, $found))[1];
1193 return wantarray ? @result : $result[0];
1195 elsif (defined $opts{code}) {
1199 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1200 push @result, (i_tags_get($self->{IMG}, $found))[1];
1207 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1210 return i_tags_count($self->{IMG});
1219 return -1 unless $self->{IMG};
1221 if (defined $opts{value}) {
1222 if ($opts{value} =~ /^\d+$/) {
1224 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1227 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1230 elsif (defined $opts{data}) {
1231 # force addition as a string
1232 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1235 $self->{ERRSTR} = "No value supplied";
1239 elsif ($opts{code}) {
1240 if (defined $opts{value}) {
1241 if ($opts{value} =~ /^\d+$/) {
1243 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1246 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1249 elsif (defined $opts{data}) {
1250 # force addition as a string
1251 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1254 $self->{ERRSTR} = "No value supplied";
1267 return 0 unless $self->{IMG};
1269 if (defined $opts{'index'}) {
1270 return i_tags_delete($self->{IMG}, $opts{'index'});
1272 elsif (defined $opts{name}) {
1273 return i_tags_delbyname($self->{IMG}, $opts{name});
1275 elsif (defined $opts{code}) {
1276 return i_tags_delbycode($self->{IMG}, $opts{code});
1279 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1285 my ($self, %opts) = @_;
1288 $self->deltag(name=>$opts{name});
1289 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1291 elsif (defined $opts{code}) {
1292 $self->deltag(code=>$opts{code});
1293 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1301 sub _get_reader_io {
1302 my ($self, $input) = @_;
1305 return $input->{io}, undef;
1307 elsif ($input->{fd}) {
1308 return io_new_fd($input->{fd});
1310 elsif ($input->{fh}) {
1311 my $fd = fileno($input->{fh});
1312 unless (defined $fd) {
1313 $self->_set_error("Handle in fh option not opened");
1316 return io_new_fd($fd);
1318 elsif ($input->{file}) {
1319 my $file = IO::File->new($input->{file}, "r");
1321 $self->_set_error("Could not open $input->{file}: $!");
1325 return (io_new_fd(fileno($file)), $file);
1327 elsif ($input->{data}) {
1328 return io_new_buffer($input->{data});
1330 elsif ($input->{callback} || $input->{readcb}) {
1331 if (!$input->{seekcb}) {
1332 $self->_set_error("Need a seekcb parameter");
1334 if ($input->{maxbuffer}) {
1335 return io_new_cb($input->{writecb},
1336 $input->{callback} || $input->{readcb},
1337 $input->{seekcb}, $input->{closecb},
1338 $input->{maxbuffer});
1341 return io_new_cb($input->{writecb},
1342 $input->{callback} || $input->{readcb},
1343 $input->{seekcb}, $input->{closecb});
1347 $self->_set_error("file/fd/fh/data/callback parameter missing");
1352 sub _get_writer_io {
1353 my ($self, $input) = @_;
1355 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1362 elsif ($input->{fd}) {
1363 $io = io_new_fd($input->{fd});
1365 elsif ($input->{fh}) {
1366 my $fd = fileno($input->{fh});
1367 unless (defined $fd) {
1368 $self->_set_error("Handle in fh option not opened");
1372 my $oldfh = select($input->{fh});
1373 # flush anything that's buffered, and make sure anything else is flushed
1376 $io = io_new_fd($fd);
1378 elsif ($input->{file}) {
1379 my $fh = new IO::File($input->{file},"w+");
1381 $self->_set_error("Could not open file $input->{file}: $!");
1384 binmode($fh) or die;
1385 $io = io_new_fd(fileno($fh));
1388 elsif ($input->{data}) {
1389 $io = io_new_bufchain();
1391 elsif ($input->{callback} || $input->{writecb}) {
1392 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1395 $io = io_new_cb($input->{callback} || $input->{writecb},
1397 $input->{seekcb}, $input->{closecb});
1400 $self->_set_error("file/fd/fh/data/callback parameter missing");
1404 unless ($buffered) {
1405 $io->set_buffered(0);
1408 return ($io, @extras);
1411 # Read an image from file
1417 if (defined($self->{IMG})) {
1418 # let IIM_DESTROY do the destruction, since the image may be
1419 # referenced from elsewhere
1420 #i_img_destroy($self->{IMG});
1421 undef($self->{IMG});
1424 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1426 my $type = $input{'type'};
1428 $type = i_test_format_probe($IO, -1);
1431 if ($input{file} && !$type) {
1433 $type = $FORMATGUESS->($input{file});
1437 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1438 $input{file} and $msg .= " or file name";
1439 $self->_set_error($msg);
1443 _reader_autoload($type);
1445 if ($readers{$type} && $readers{$type}{single}) {
1446 return $readers{$type}{single}->($self, $IO, %input);
1449 unless ($formats_low{$type}) {
1450 my $read_types = join ', ', sort Imager->read_types();
1451 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1455 my $allow_incomplete = $input{allow_incomplete};
1456 defined $allow_incomplete or $allow_incomplete = 0;
1458 if ( $type eq 'pnm' ) {
1459 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1460 if ( !defined($self->{IMG}) ) {
1461 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1464 $self->{DEBUG} && print "loading a pnm file\n";
1468 if ( $type eq 'bmp' ) {
1469 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1470 if ( !defined($self->{IMG}) ) {
1471 $self->{ERRSTR}=$self->_error_as_msg();
1474 $self->{DEBUG} && print "loading a bmp file\n";
1477 if ( $type eq 'tga' ) {
1478 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1479 if ( !defined($self->{IMG}) ) {
1480 $self->{ERRSTR}=$self->_error_as_msg();
1483 $self->{DEBUG} && print "loading a tga file\n";
1486 if ( $type eq 'raw' ) {
1487 unless ( $input{xsize} && $input{ysize} ) {
1488 $self->_set_error('missing xsize or ysize parameter for raw');
1492 my $interleave = _first($input{raw_interleave}, $input{interleave});
1493 unless (defined $interleave) {
1494 my @caller = caller;
1495 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1498 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1499 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1501 $self->{IMG} = i_readraw_wiol( $IO,
1507 if ( !defined($self->{IMG}) ) {
1508 $self->{ERRSTR}=$self->_error_as_msg();
1511 $self->{DEBUG} && print "loading a raw file\n";
1517 sub register_reader {
1518 my ($class, %opts) = @_;
1521 or die "register_reader called with no type parameter\n";
1523 my $type = $opts{type};
1525 defined $opts{single} || defined $opts{multiple}
1526 or die "register_reader called with no single or multiple parameter\n";
1528 $readers{$type} = { };
1529 if ($opts{single}) {
1530 $readers{$type}{single} = $opts{single};
1532 if ($opts{multiple}) {
1533 $readers{$type}{multiple} = $opts{multiple};
1539 sub register_writer {
1540 my ($class, %opts) = @_;
1543 or die "register_writer called with no type parameter\n";
1545 my $type = $opts{type};
1547 defined $opts{single} || defined $opts{multiple}
1548 or die "register_writer called with no single or multiple parameter\n";
1550 $writers{$type} = { };
1551 if ($opts{single}) {
1552 $writers{$type}{single} = $opts{single};
1554 if ($opts{multiple}) {
1555 $writers{$type}{multiple} = $opts{multiple};
1566 grep($file_formats{$_}, keys %formats),
1567 qw(ico sgi), # formats not handled directly, but supplied with Imager
1578 grep($file_formats{$_}, keys %formats),
1579 qw(ico sgi), # formats not handled directly, but supplied with Imager
1586 my ($file, $error) = @_;
1588 if ($attempted_to_load{$file}) {
1589 if ($file_load_errors{$file}) {
1590 $$error = $file_load_errors{$file};
1598 local $SIG{__DIE__};
1600 ++$attempted_to_load{$file};
1608 my $work = $@ || "Unknown error";
1610 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1611 $work =~ s/\n/\\n/g;
1612 $work =~ s/\s*\.?\z/ loading $file/;
1613 $file_load_errors{$file} = $work;
1620 # probes for an Imager::File::whatever module
1621 sub _reader_autoload {
1624 return if $formats_low{$type} || $readers{$type};
1626 return unless $type =~ /^\w+$/;
1628 my $file = "Imager/File/\U$type\E.pm";
1631 my $loaded = _load_file($file, \$error);
1632 if (!$loaded && $error =~ /^Can't locate /) {
1633 my $filer = "Imager/File/\U$type\EReader.pm";
1634 $loaded = _load_file($filer, \$error);
1635 if ($error =~ /^Can't locate /) {
1636 $error = "Can't locate $file or $filer";
1640 $reader_load_errors{$type} = $error;
1644 # probes for an Imager::File::whatever module
1645 sub _writer_autoload {
1648 return if $formats_low{$type} || $writers{$type};
1650 return unless $type =~ /^\w+$/;
1652 my $file = "Imager/File/\U$type\E.pm";
1655 my $loaded = _load_file($file, \$error);
1656 if (!$loaded && $error =~ /^Can't locate /) {
1657 my $filew = "Imager/File/\U$type\EWriter.pm";
1658 $loaded = _load_file($filew, \$error);
1659 if ($error =~ /^Can't locate /) {
1660 $error = "Can't locate $file or $filew";
1664 $writer_load_errors{$type} = $error;
1668 sub _fix_gif_positions {
1669 my ($opts, $opt, $msg, @imgs) = @_;
1671 my $positions = $opts->{'gif_positions'};
1673 for my $pos (@$positions) {
1674 my ($x, $y) = @$pos;
1675 my $img = $imgs[$index++];
1676 $img->settag(name=>'gif_left', value=>$x);
1677 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1679 $$msg .= "replaced with the gif_left and gif_top tags";
1684 gif_each_palette=>'gif_local_map',
1685 interlace => 'gif_interlace',
1686 gif_delays => 'gif_delay',
1687 gif_positions => \&_fix_gif_positions,
1688 gif_loop_count => 'gif_loop',
1691 # options that should be converted to colors
1692 my %color_opts = map { $_ => 1 } qw/i_background/;
1695 my ($self, $opts, $prefix, @imgs) = @_;
1697 for my $opt (keys %$opts) {
1699 if ($obsolete_opts{$opt}) {
1700 my $new = $obsolete_opts{$opt};
1701 my $msg = "Obsolete option $opt ";
1703 $new->($opts, $opt, \$msg, @imgs);
1706 $msg .= "replaced with the $new tag ";
1709 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1710 warn $msg if $warn_obsolete && $^W;
1712 next unless $tagname =~ /^\Q$prefix/;
1713 my $value = $opts->{$opt};
1714 if ($color_opts{$opt}) {
1715 $value = _color($value);
1717 $self->_set_error($Imager::ERRSTR);
1722 if (UNIVERSAL::isa($value, "Imager::Color")) {
1723 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1724 for my $img (@imgs) {
1725 $img->settag(name=>$tagname, value=>$tag);
1728 elsif (ref($value) eq 'ARRAY') {
1729 for my $i (0..$#$value) {
1730 my $val = $value->[$i];
1732 if (UNIVERSAL::isa($val, "Imager::Color")) {
1733 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1735 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1738 $self->_set_error("Unknown reference type " . ref($value) .
1739 " supplied in array for $opt");
1745 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1750 $self->_set_error("Unknown reference type " . ref($value) .
1751 " supplied for $opt");
1756 # set it as a tag for every image
1757 for my $img (@imgs) {
1758 $img->settag(name=>$tagname, value=>$value);
1766 # Write an image to file
1769 my %input=(jpegquality=>75,
1779 $self->_set_opts(\%input, "i_", $self)
1782 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1784 my $type = $input{'type'};
1785 if (!$type and $input{file}) {
1786 $type = $FORMATGUESS->($input{file});
1789 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1793 _writer_autoload($type);
1796 if ($writers{$type} && $writers{$type}{single}) {
1797 ($IO, $fh) = $self->_get_writer_io(\%input)
1800 $writers{$type}{single}->($self, $IO, %input, type => $type)
1804 if (!$formats_low{$type}) {
1805 my $write_types = join ', ', sort Imager->write_types();
1806 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
1810 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
1813 if ( $type eq 'pnm' ) {
1814 $self->_set_opts(\%input, "pnm_", $self)
1816 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1817 $self->{ERRSTR} = $self->_error_as_msg();
1820 $self->{DEBUG} && print "writing a pnm file\n";
1822 elsif ( $type eq 'raw' ) {
1823 $self->_set_opts(\%input, "raw_", $self)
1825 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1826 $self->{ERRSTR} = $self->_error_as_msg();
1829 $self->{DEBUG} && print "writing a raw file\n";
1831 elsif ( $type eq 'bmp' ) {
1832 $self->_set_opts(\%input, "bmp_", $self)
1834 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1835 $self->{ERRSTR} = $self->_error_as_msg;
1838 $self->{DEBUG} && print "writing a bmp file\n";
1840 elsif ( $type eq 'tga' ) {
1841 $self->_set_opts(\%input, "tga_", $self)
1844 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1845 $self->{ERRSTR}=$self->_error_as_msg();
1848 $self->{DEBUG} && print "writing a tga file\n";
1852 if (exists $input{'data'}) {
1853 my $data = io_slurp($IO);
1855 $self->{ERRSTR}='Could not slurp from buffer';
1858 ${$input{data}} = $data;
1864 my ($class, $opts, @images) = @_;
1866 my $type = $opts->{type};
1868 if (!$type && $opts->{'file'}) {
1869 $type = $FORMATGUESS->($opts->{'file'});
1872 $class->_set_error('type parameter missing and not possible to guess from extension');
1875 # translate to ImgRaw
1876 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1877 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1880 $class->_set_opts($opts, "i_", @images)
1882 my @work = map $_->{IMG}, @images;
1884 _writer_autoload($type);
1887 if ($writers{$type} && $writers{$type}{multiple}) {
1888 ($IO, $file) = $class->_get_writer_io($opts, $type)
1891 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1895 if (!$formats{$type}) {
1896 my $write_types = join ', ', sort Imager->write_types();
1897 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
1901 ($IO, $file) = $class->_get_writer_io($opts, $type)
1904 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
1908 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
1913 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1919 if (exists $opts->{'data'}) {
1920 my $data = io_slurp($IO);
1922 Imager->_set_error('Could not slurp from buffer');
1925 ${$opts->{data}} = $data;
1930 # read multiple images from a file
1932 my ($class, %opts) = @_;
1934 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1937 my $type = $opts{'type'};
1939 $type = i_test_format_probe($IO, -1);
1942 if ($opts{file} && !$type) {
1944 $type = $FORMATGUESS->($opts{file});
1948 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1949 $opts{file} and $msg .= " or file name";
1950 Imager->_set_error($msg);
1954 _reader_autoload($type);
1956 if ($readers{$type} && $readers{$type}{multiple}) {
1957 return $readers{$type}{multiple}->($IO, %opts);
1960 unless ($formats{$type}) {
1961 my $read_types = join ', ', sort Imager->read_types();
1962 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
1967 if ($type eq 'pnm') {
1968 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
1971 my $img = Imager->new;
1972 if ($img->read(%opts, io => $IO, type => $type)) {
1975 Imager->_set_error($img->errstr);
1980 $ERRSTR = _error_as_msg();
1984 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1988 # Destroy an Imager object
1992 # delete $instances{$self};
1993 if (defined($self->{IMG})) {
1994 # the following is now handled by the XS DESTROY method for
1995 # Imager::ImgRaw object
1996 # Re-enabling this will break virtual images
1997 # tested for in t/t020masked.t
1998 # i_img_destroy($self->{IMG});
1999 undef($self->{IMG});
2001 # print "Destroy Called on an empty image!\n"; # why did I put this here??
2005 # Perform an inplace filter of an image
2006 # that is the image will be overwritten with the data
2012 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2014 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
2016 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
2017 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
2020 if ($filters{$input{'type'}}{names}) {
2021 my $names = $filters{$input{'type'}}{names};
2022 for my $name (keys %$names) {
2023 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2024 $input{$name} = $names->{$name}{$input{$name}};
2028 if (defined($filters{$input{'type'}}{defaults})) {
2029 %hsh=( image => $self->{IMG},
2031 %{$filters{$input{'type'}}{defaults}},
2034 %hsh=( image => $self->{IMG},
2039 my @cs=@{$filters{$input{'type'}}{callseq}};
2042 if (!defined($hsh{$_})) {
2043 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
2048 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2049 &{$filters{$input{'type'}}{callsub}}(%hsh);
2052 chomp($self->{ERRSTR} = $@);
2058 $self->{DEBUG} && print "callseq is: @cs\n";
2059 $self->{DEBUG} && print "matching callseq is: @b\n";
2064 sub register_filter {
2066 my %hsh = ( defaults => {}, @_ );
2069 or die "register_filter() with no type\n";
2070 defined $hsh{callsub}
2071 or die "register_filter() with no callsub\n";
2072 defined $hsh{callseq}
2073 or die "register_filter() with no callseq\n";
2075 exists $filters{$hsh{type}}
2078 $filters{$hsh{type}} = \%hsh;
2083 sub scale_calculate {
2086 my %opts = ('type'=>'max', @_);
2088 # none of these should be references
2089 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2090 if (defined $opts{$name} && ref $opts{$name}) {
2091 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2096 my ($x_scale, $y_scale);
2097 my $width = $opts{width};
2098 my $height = $opts{height};
2100 defined $width or $width = $self->getwidth;
2101 defined $height or $height = $self->getheight;
2104 unless (defined $width && defined $height) {
2105 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2110 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
2111 $x_scale = $opts{'xscalefactor'};
2112 $y_scale = $opts{'yscalefactor'};
2114 elsif ($opts{'xscalefactor'}) {
2115 $x_scale = $opts{'xscalefactor'};
2116 $y_scale = $opts{'scalefactor'} || $x_scale;
2118 elsif ($opts{'yscalefactor'}) {
2119 $y_scale = $opts{'yscalefactor'};
2120 $x_scale = $opts{'scalefactor'} || $y_scale;
2123 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2126 # work out the scaling
2127 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
2128 my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2129 $opts{ypixels} / $height );
2130 if ($opts{'type'} eq 'min') {
2131 $x_scale = $y_scale = _min($xpix,$ypix);
2133 elsif ($opts{'type'} eq 'max') {
2134 $x_scale = $y_scale = _max($xpix,$ypix);
2136 elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2141 $self->_set_error('invalid value for type parameter');
2144 } elsif ($opts{xpixels}) {
2145 $x_scale = $y_scale = $opts{xpixels} / $width;
2147 elsif ($opts{ypixels}) {
2148 $x_scale = $y_scale = $opts{ypixels}/$height;
2150 elsif ($opts{constrain} && ref $opts{constrain}
2151 && $opts{constrain}->can('constrain')) {
2152 # we've been passed an Image::Math::Constrain object or something
2153 # that looks like one
2155 (undef, undef, $scalefactor)
2156 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2157 unless ($scalefactor) {
2158 $self->_set_error('constrain method failed on constrain parameter');
2161 $x_scale = $y_scale = $scalefactor;
2164 my $new_width = int($x_scale * $width + 0.5);
2165 $new_width > 0 or $new_width = 1;
2166 my $new_height = int($y_scale * $height + 0.5);
2167 $new_height > 0 or $new_height = 1;
2169 return ($x_scale, $y_scale, $new_width, $new_height);
2173 # Scale an image to requested size and return the scaled version
2177 my %opts = (qtype=>'normal' ,@_);
2178 my $img = Imager->new();
2179 my $tmp = Imager->new();
2181 unless (defined wantarray) {
2182 my @caller = caller;
2183 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2187 unless ($self->{IMG}) {
2188 $self->_set_error('empty input image');
2192 my ($x_scale, $y_scale, $new_width, $new_height) =
2193 $self->scale_calculate(%opts)
2196 if ($opts{qtype} eq 'normal') {
2197 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2198 if ( !defined($tmp->{IMG}) ) {
2199 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2202 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2203 if ( !defined($img->{IMG}) ) {
2204 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2210 elsif ($opts{'qtype'} eq 'preview') {
2211 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2212 if ( !defined($img->{IMG}) ) {
2213 $self->{ERRSTR}='unable to scale image';
2218 elsif ($opts{'qtype'} eq 'mixing') {
2219 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2220 unless ($img->{IMG}) {
2221 $self->_set_error(Imager->_error_as_msg);
2227 $self->_set_error('invalid value for qtype parameter');
2232 # Scales only along the X axis
2236 my %opts = ( scalefactor=>0.5, @_ );
2238 unless (defined wantarray) {
2239 my @caller = caller;
2240 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2244 unless ($self->{IMG}) {
2245 $self->{ERRSTR} = 'empty input image';
2249 my $img = Imager->new();
2251 my $scalefactor = $opts{scalefactor};
2253 if ($opts{pixels}) {
2254 $scalefactor = $opts{pixels} / $self->getwidth();
2257 unless ($self->{IMG}) {
2258 $self->{ERRSTR}='empty input image';
2262 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2264 if ( !defined($img->{IMG}) ) {
2265 $self->{ERRSTR} = 'unable to scale image';
2272 # Scales only along the Y axis
2276 my %opts = ( scalefactor => 0.5, @_ );
2278 unless (defined wantarray) {
2279 my @caller = caller;
2280 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2284 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2286 my $img = Imager->new();
2288 my $scalefactor = $opts{scalefactor};
2290 if ($opts{pixels}) {
2291 $scalefactor = $opts{pixels} / $self->getheight();
2294 unless ($self->{IMG}) {
2295 $self->{ERRSTR} = 'empty input image';
2298 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2300 if ( !defined($img->{IMG}) ) {
2301 $self->{ERRSTR} = 'unable to scale image';
2308 # Transform returns a spatial transformation of the input image
2309 # this moves pixels to a new location in the returned image.
2310 # NOTE - should make a utility function to check transforms for
2315 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2317 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2319 # print Dumper(\%opts);
2322 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2324 eval ("use Affix::Infix2Postfix;");
2327 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2330 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2331 {op=>'-',trans=>'Sub'},
2332 {op=>'*',trans=>'Mult'},
2333 {op=>'/',trans=>'Div'},
2334 {op=>'-','type'=>'unary',trans=>'u-'},
2336 {op=>'func','type'=>'unary'}],
2337 'grouping'=>[qw( \( \) )],
2338 'func'=>[qw( sin cos )],
2343 @xt=$I2P->translate($opts{'xexpr'});
2344 @yt=$I2P->translate($opts{'yexpr'});
2346 $numre=$I2P->{'numre'};
2349 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2350 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2351 @{$opts{'parm'}}=@pt;
2354 # print Dumper(\%opts);
2356 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2357 $self->{ERRSTR}='transform: no xopcodes given.';
2361 @op=@{$opts{'xopcodes'}};
2363 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2364 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2367 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2373 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2374 $self->{ERRSTR}='transform: no yopcodes given.';
2378 @op=@{$opts{'yopcodes'}};
2380 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2381 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2384 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2389 if ( !exists $opts{'parm'}) {
2390 $self->{ERRSTR}='transform: no parameter arg given.';
2394 # print Dumper(\@ropx);
2395 # print Dumper(\@ropy);
2396 # print Dumper(\@ropy);
2398 my $img = Imager->new();
2399 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2400 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2406 my ($opts, @imgs) = @_;
2408 require "Imager/Expr.pm";
2410 $opts->{variables} = [ qw(x y) ];
2411 my ($width, $height) = @{$opts}{qw(width height)};
2413 $width ||= $imgs[0]->getwidth();
2414 $height ||= $imgs[0]->getheight();
2416 for my $img (@imgs) {
2417 $opts->{constants}{"w$img_num"} = $img->getwidth();
2418 $opts->{constants}{"h$img_num"} = $img->getheight();
2419 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2420 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2425 $opts->{constants}{w} = $width;
2426 $opts->{constants}{cx} = $width/2;
2429 $Imager::ERRSTR = "No width supplied";
2433 $opts->{constants}{h} = $height;
2434 $opts->{constants}{cy} = $height/2;
2437 $Imager::ERRSTR = "No height supplied";
2440 my $code = Imager::Expr->new($opts);
2442 $Imager::ERRSTR = Imager::Expr::error();
2445 my $channels = $opts->{channels} || 3;
2446 unless ($channels >= 1 && $channels <= 4) {
2447 return Imager->_set_error("channels must be an integer between 1 and 4");
2450 my $img = Imager->new();
2451 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2452 $channels, $code->code(),
2453 $code->nregs(), $code->cregs(),
2454 [ map { $_->{IMG} } @imgs ]);
2455 if (!defined $img->{IMG}) {
2456 $Imager::ERRSTR = Imager->_error_as_msg();
2467 unless ($self->{IMG}) {
2468 $self->{ERRSTR}='empty input image';
2471 unless ($opts{src} && $opts{src}->{IMG}) {
2472 $self->{ERRSTR}='empty input image for src';
2476 %opts = (src_minx => 0,
2478 src_maxx => $opts{src}->getwidth(),
2479 src_maxy => $opts{src}->getheight(),
2483 defined $tx or $tx = $opts{left};
2484 defined $tx or $tx = 0;
2487 defined $ty or $ty = $opts{top};
2488 defined $ty or $ty = 0;
2490 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2491 $opts{src_minx}, $opts{src_miny},
2492 $opts{src_maxx}, $opts{src_maxy})) {
2493 $self->_set_error($self->_error_as_msg());
2510 unless ($self->{IMG}) {
2511 $self->_set_error("compose: empty input image");
2515 unless ($opts{src}) {
2516 $self->_set_error("compose: src parameter missing");
2520 unless ($opts{src}{IMG}) {
2521 $self->_set_error("compose: src parameter empty image");
2524 my $src = $opts{src};
2526 my $left = $opts{left};
2527 defined $left or $left = $opts{tx};
2528 defined $left or $left = 0;
2530 my $top = $opts{top};
2531 defined $top or $top = $opts{ty};
2532 defined $top or $top = 0;
2534 my $src_left = $opts{src_left};
2535 defined $src_left or $src_left = $opts{src_minx};
2536 defined $src_left or $src_left = 0;
2538 my $src_top = $opts{src_top};
2539 defined $src_top or $src_top = $opts{src_miny};
2540 defined $src_top or $src_top = 0;
2542 my $width = $opts{width};
2543 if (!defined $width && defined $opts{src_maxx}) {
2544 $width = $opts{src_maxx} - $src_left;
2546 defined $width or $width = $src->getwidth() - $src_left;
2548 my $height = $opts{height};
2549 if (!defined $height && defined $opts{src_maxy}) {
2550 $height = $opts{src_maxy} - $src_top;
2552 defined $height or $height = $src->getheight() - $src_top;
2554 my $combine = $self->_combine($opts{combine}, 'normal');
2557 unless ($opts{mask}{IMG}) {
2558 $self->_set_error("compose: mask parameter empty image");
2562 my $mask_left = $opts{mask_left};
2563 defined $mask_left or $mask_left = $opts{mask_minx};
2564 defined $mask_left or $mask_left = 0;
2566 my $mask_top = $opts{mask_top};
2567 defined $mask_top or $mask_top = $opts{mask_miny};
2568 defined $mask_top or $mask_top = 0;
2570 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2571 $left, $top, $src_left, $src_top,
2572 $mask_left, $mask_top, $width, $height,
2573 $combine, $opts{opacity})) {
2574 $self->_set_error(Imager->_error_as_msg);
2579 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2580 $width, $height, $combine, $opts{opacity})) {
2581 $self->_set_error(Imager->_error_as_msg);
2592 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2594 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2595 $dir = $xlate{$opts{'dir'}};
2596 return $self if i_flipxy($self->{IMG}, $dir);
2604 unless (defined wantarray) {
2605 my @caller = caller;
2606 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2610 if (defined $opts{right}) {
2611 my $degrees = $opts{right};
2613 $degrees += 360 * int(((-$degrees)+360)/360);
2615 $degrees = $degrees % 360;
2616 if ($degrees == 0) {
2617 return $self->copy();
2619 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2620 my $result = Imager->new();
2621 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2625 $self->{ERRSTR} = $self->_error_as_msg();
2630 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2634 elsif (defined $opts{radians} || defined $opts{degrees}) {
2635 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2637 my $back = $opts{back};
2638 my $result = Imager->new;
2640 $back = _color($back);
2642 $self->_set_error(Imager->errstr);
2646 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2649 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2651 if ($result->{IMG}) {
2655 $self->{ERRSTR} = $self->_error_as_msg();
2660 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2665 sub matrix_transform {
2669 unless (defined wantarray) {
2670 my @caller = caller;
2671 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2675 if ($opts{matrix}) {
2676 my $xsize = $opts{xsize} || $self->getwidth;
2677 my $ysize = $opts{ysize} || $self->getheight;
2679 my $result = Imager->new;
2681 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2682 $opts{matrix}, $opts{back})
2686 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2694 $self->{ERRSTR} = "matrix parameter required";
2700 *yatf = \&matrix_transform;
2702 # These two are supported for legacy code only
2705 return Imager::Color->new(@_);
2709 return Imager::Color::set(@_);
2712 # Draws a box between the specified corner points.
2715 my $raw = $self->{IMG};
2718 $self->{ERRSTR}='empty input image';
2724 my ($xmin, $ymin, $xmax, $ymax);
2725 if (exists $opts{'box'}) {
2726 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2727 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2728 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2729 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2732 defined($xmin = $opts{xmin}) or $xmin = 0;
2733 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2734 defined($ymin = $opts{ymin}) or $ymin = 0;
2735 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2738 if ($opts{filled}) {
2739 my $color = $opts{'color'};
2741 if (defined $color) {
2742 unless (_is_color_object($color)) {
2743 $color = _color($color);
2745 $self->{ERRSTR} = $Imager::ERRSTR;
2751 $color = i_color_new(255,255,255,255);
2754 if ($color->isa("Imager::Color")) {
2755 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
2758 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
2761 elsif ($opts{fill}) {
2762 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2763 # assume it's a hash ref
2764 require 'Imager/Fill.pm';
2765 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2766 $self->{ERRSTR} = $Imager::ERRSTR;
2770 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
2773 my $color = $opts{'color'};
2774 if (defined $color) {
2775 unless (_is_color_object($color)) {
2776 $color = _color($color);
2778 $self->{ERRSTR} = $Imager::ERRSTR;
2784 $color = i_color_new(255, 255, 255, 255);
2787 $self->{ERRSTR} = $Imager::ERRSTR;
2790 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
2798 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2799 my $dflcl= [ 255, 255, 255, 255];
2804 'r'=>_min($self->getwidth(),$self->getheight())/3,
2805 'x'=>$self->getwidth()/2,
2806 'y'=>$self->getheight()/2,
2813 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2814 # assume it's a hash ref
2815 require 'Imager/Fill.pm';
2816 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2817 $self->{ERRSTR} = $Imager::ERRSTR;
2821 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2822 $opts{'d2'}, $opts{fill}{fill});
2824 elsif ($opts{filled}) {
2825 my $color = _color($opts{'color'});
2827 $self->{ERRSTR} = $Imager::ERRSTR;
2830 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2831 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2835 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2836 $opts{'d1'}, $opts{'d2'}, $color);
2840 my $color = _color($opts{'color'});
2841 if ($opts{d2} - $opts{d1} >= 360) {
2842 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
2845 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
2851 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2852 # assume it's a hash ref
2853 require 'Imager/Fill.pm';
2854 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2855 $self->{ERRSTR} = $Imager::ERRSTR;
2859 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2860 $opts{'d2'}, $opts{fill}{fill});
2863 my $color = _color($opts{'color'});
2865 $self->{ERRSTR} = $Imager::ERRSTR;
2868 if ($opts{filled}) {
2869 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2870 $opts{'d1'}, $opts{'d2'}, $color);
2873 if ($opts{d1} == 0 && $opts{d2} == 361) {
2874 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
2877 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
2883 $self->_set_error($self->_error_as_msg);
2890 # Draws a line from one point to the other
2891 # the endpoint is set if the endp parameter is set which it is by default.
2892 # to turn of the endpoint being set use endp=>0 when calling line.
2896 my $dflcl=i_color_new(0,0,0,0);
2897 my %opts=(color=>$dflcl,
2900 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2902 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2903 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2905 my $color = _color($opts{'color'});
2907 $self->{ERRSTR} = $Imager::ERRSTR;
2911 $opts{antialias} = $opts{aa} if defined $opts{aa};
2912 if ($opts{antialias}) {
2913 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2914 $color, $opts{endp});
2916 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2917 $color, $opts{endp});
2922 # Draws a line between an ordered set of points - It more or less just transforms this
2923 # into a list of lines.
2927 my ($pt,$ls,@points);
2928 my $dflcl=i_color_new(0,0,0,0);
2929 my %opts=(color=>$dflcl,@_);
2931 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2933 if (exists($opts{points})) { @points=@{$opts{points}}; }
2934 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2935 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2938 # print Dumper(\@points);
2940 my $color = _color($opts{'color'});
2942 $self->{ERRSTR} = $Imager::ERRSTR;
2945 $opts{antialias} = $opts{aa} if defined $opts{aa};
2946 if ($opts{antialias}) {
2949 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2956 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2966 my ($pt,$ls,@points);
2967 my $dflcl = i_color_new(0,0,0,0);
2968 my %opts = (color=>$dflcl, @_);
2970 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2972 if (exists($opts{points})) {
2973 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2974 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2977 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2978 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2981 if ($opts{'fill'}) {
2982 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2983 # assume it's a hash ref
2984 require 'Imager/Fill.pm';
2985 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2986 $self->{ERRSTR} = $Imager::ERRSTR;
2990 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2991 $opts{'fill'}{'fill'});
2994 my $color = _color($opts{'color'});
2996 $self->{ERRSTR} = $Imager::ERRSTR;
2999 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3006 # this the multipoint bezier curve
3007 # this is here more for testing that actual usage since
3008 # this is not a good algorithm. Usually the curve would be
3009 # broken into smaller segments and each done individually.
3013 my ($pt,$ls,@points);
3014 my $dflcl=i_color_new(0,0,0,0);
3015 my %opts=(color=>$dflcl,@_);
3017 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3019 if (exists $opts{points}) {
3020 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
3021 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
3024 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
3025 $self->{ERRSTR}='Missing or invalid points.';
3029 my $color = _color($opts{'color'});
3031 $self->{ERRSTR} = $Imager::ERRSTR;
3034 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3040 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3043 unless (exists $opts{'x'} && exists $opts{'y'}) {
3044 $self->{ERRSTR} = "missing seed x and y parameters";
3048 if ($opts{border}) {
3049 my $border = _color($opts{border});
3051 $self->_set_error($Imager::ERRSTR);
3055 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3056 # assume it's a hash ref
3057 require Imager::Fill;
3058 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3059 $self->{ERRSTR} = $Imager::ERRSTR;
3063 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3064 $opts{fill}{fill}, $border);
3067 my $color = _color($opts{'color'});
3069 $self->{ERRSTR} = $Imager::ERRSTR;
3072 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3079 $self->{ERRSTR} = $self->_error_as_msg();
3085 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3086 # assume it's a hash ref
3087 require 'Imager/Fill.pm';
3088 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
3089 $self->{ERRSTR} = $Imager::ERRSTR;
3093 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3096 my $color = _color($opts{'color'});
3098 $self->{ERRSTR} = $Imager::ERRSTR;
3101 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3107 $self->{ERRSTR} = $self->_error_as_msg();
3114 my ($self, %opts) = @_;
3116 $self->_valid_image("setpixel")
3119 my $color = $opts{color};
3120 unless (defined $color) {
3121 $color = $self->{fg};
3122 defined $color or $color = NC(255, 255, 255);
3125 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3126 unless ($color = _color($color, 'setpixel')) {
3127 $self->_set_error("setpixel: " . Imager->errstr);
3132 unless (exists $opts{'x'} && exists $opts{'y'}) {
3133 $self->_set_error('setpixel: missing x or y parameter');
3139 if (ref $x || ref $y) {
3140 $x = ref $x ? $x : [ $x ];
3141 $y = ref $y ? $y : [ $y ];
3143 $self->_set_error("setpixel: x is a reference to an empty array");
3147 $self->_set_error("setpixel: y is a reference to an empty array");
3151 # make both the same length, replicating the last element
3153 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3156 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3160 if ($color->isa('Imager::Color')) {
3161 for my $i (0..$#$x) {
3162 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3167 for my $i (0..$#$x) {
3168 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3176 if ($color->isa('Imager::Color')) {
3177 i_ppix($self->{IMG}, $x, $y, $color)
3181 i_ppixf($self->{IMG}, $x, $y, $color)
3192 my %opts = ( "type"=>'8bit', @_);
3194 $self->_valid_image("getpixel")
3197 unless (exists $opts{'x'} && exists $opts{'y'}) {
3198 $self->_set_error('getpixel: missing x or y parameter');
3204 my $type = $opts{'type'};
3205 if (ref $x || ref $y) {
3206 $x = ref $x ? $x : [ $x ];
3207 $y = ref $y ? $y : [ $y ];
3209 $self->_set_error("getpixel: x is a reference to an empty array");
3213 $self->_set_error("getpixel: y is a reference to an empty array");
3217 # make both the same length, replicating the last element
3219 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3222 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3226 if ($type eq '8bit') {
3227 for my $i (0..$#$x) {
3228 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3231 elsif ($type eq 'float' || $type eq 'double') {
3232 for my $i (0..$#$x) {
3233 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3237 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3240 return wantarray ? @result : \@result;
3243 if ($type eq '8bit') {
3244 return i_get_pixel($self->{IMG}, $x, $y);
3246 elsif ($type eq 'float' || $type eq 'double') {
3247 return i_gpixf($self->{IMG}, $x, $y);
3250 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3258 my %opts = ( type => '8bit', x=>0, @_);
3260 $self->_valid_image or return;
3262 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3264 unless (defined $opts{'y'}) {
3265 $self->_set_error("missing y parameter");
3269 if ($opts{type} eq '8bit') {
3270 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3273 elsif ($opts{type} eq 'float') {
3274 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3277 elsif ($opts{type} eq 'index') {
3278 unless (i_img_type($self->{IMG})) {
3279 $self->_set_error("type => index only valid on paletted images");
3282 return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3286 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3293 my %opts = ( x=>0, @_);
3295 $self->_valid_image or return;
3297 unless (defined $opts{'y'}) {
3298 $self->_set_error("missing y parameter");
3303 if (ref $opts{pixels} && @{$opts{pixels}}) {
3304 # try to guess the type
3305 if ($opts{pixels}[0]->isa('Imager::Color')) {
3306 $opts{type} = '8bit';
3308 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3309 $opts{type} = 'float';
3312 $self->_set_error("missing type parameter and could not guess from pixels");
3318 $opts{type} = '8bit';
3322 if ($opts{type} eq '8bit') {
3323 if (ref $opts{pixels}) {
3324 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3327 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3330 elsif ($opts{type} eq 'float') {
3331 if (ref $opts{pixels}) {
3332 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3335 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3338 elsif ($opts{type} eq 'index') {
3339 if (ref $opts{pixels}) {
3340 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
3343 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3347 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3354 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3356 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3358 unless (defined $opts{'y'}) {
3359 $self->_set_error("missing y parameter");
3363 if ($opts{target}) {
3364 my $target = $opts{target};
3365 my $offset = $opts{offset};
3366 if ($opts{type} eq '8bit') {
3367 my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3368 $opts{y}, $opts{channels})
3370 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3371 return scalar(@samples);
3373 elsif ($opts{type} eq 'float') {
3374 my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3375 $opts{y}, $opts{channels});
3376 @{$target}[$offset .. $offset + @samples - 1] = @samples;
3377 return scalar(@samples);
3379 elsif ($opts{type} =~ /^(\d+)bit$/) {
3383 my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3384 $opts{y}, $bits, $target,
3385 $offset, $opts{channels});
3386 unless (defined $count) {
3387 $self->_set_error(Imager->_error_as_msg);
3394 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3399 if ($opts{type} eq '8bit') {
3400 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3401 $opts{y}, $opts{channels});
3403 elsif ($opts{type} eq 'float') {
3404 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3405 $opts{y}, $opts{channels});
3407 elsif ($opts{type} =~ /^(\d+)bit$/) {
3411 i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3412 $opts{y}, $bits, \@data, 0, $opts{channels})
3417 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3425 my %opts = ( x => 0, offset => 0, @_ );
3427 unless ($self->{IMG}) {
3428 $self->_set_error('setsamples: empty input image');
3432 my $data = $opts{data};
3433 unless(defined $data) {
3434 $self->_set_error('setsamples: data parameter missing');
3438 my $type = $opts{type};
3439 defined $type or $type = '8bit';
3441 my $width = defined $opts{width} ? $opts{width}
3442 : $self->getwidth() - $opts{x};
3445 if ($type eq '8bit') {
3446 $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3447 $data, $opts{offset}, $width);
3449 elsif ($type eq 'float') {
3450 $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3451 $data, $opts{offset}, $width);
3453 elsif ($type =~ /^([0-9]+)bit$/) {
3456 unless (ref $data) {
3457 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3461 $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3462 $opts{channels}, $data, $opts{offset},
3466 $self->_set_error('setsamples: type parameter invalid');
3470 unless (defined $count) {
3471 $self->_set_error(Imager->_error_as_msg);
3478 # make an identity matrix of the given size
3482 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
3483 for my $c (0 .. ($size-1)) {
3484 $matrix->[$c][$c] = 1;
3489 # general function to convert an image
3491 my ($self, %opts) = @_;
3494 unless (defined wantarray) {
3495 my @caller = caller;
3496 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3500 # the user can either specify a matrix or preset
3501 # the matrix overrides the preset
3502 if (!exists($opts{matrix})) {
3503 unless (exists($opts{preset})) {
3504 $self->{ERRSTR} = "convert() needs a matrix or preset";
3508 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
3509 # convert to greyscale, keeping the alpha channel if any
3510 if ($self->getchannels == 3) {
3511 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3513 elsif ($self->getchannels == 4) {
3514 # preserve the alpha channel
3515 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3520 $matrix = _identity($self->getchannels);
3523 elsif ($opts{preset} eq 'noalpha') {
3524 # strip the alpha channel
3525 if ($self->getchannels == 2 or $self->getchannels == 4) {
3526 $matrix = _identity($self->getchannels);
3527 pop(@$matrix); # lose the alpha entry
3530 $matrix = _identity($self->getchannels);
3533 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3535 $matrix = [ [ 1 ] ];
3537 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3538 $matrix = [ [ 0, 1 ] ];
3540 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3541 $matrix = [ [ 0, 0, 1 ] ];
3543 elsif ($opts{preset} eq 'alpha') {
3544 if ($self->getchannels == 2 or $self->getchannels == 4) {
3545 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3548 # the alpha is just 1 <shrug>
3549 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3552 elsif ($opts{preset} eq 'rgb') {
3553 if ($self->getchannels == 1) {
3554 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3556 elsif ($self->getchannels == 2) {
3557 # preserve the alpha channel
3558 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3561 $matrix = _identity($self->getchannels);
3564 elsif ($opts{preset} eq 'addalpha') {
3565 if ($self->getchannels == 1) {
3566 $matrix = _identity(2);
3568 elsif ($self->getchannels == 3) {
3569 $matrix = _identity(4);
3572 $matrix = _identity($self->getchannels);
3576 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3582 $matrix = $opts{matrix};
3585 my $new = Imager->new;
3586 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3587 unless ($new->{IMG}) {
3588 # most likely a bad matrix
3589 $self->{ERRSTR} = _error_as_msg();
3595 # combine channels from multiple input images, a class method
3597 my ($class, %opts) = @_;
3599 my $src = delete $opts{src};
3601 $class->_set_error("src parameter missing");
3606 for my $img (@$src) {
3607 unless (eval { $img->isa("Imager") }) {
3608 $class->_set_error("src must contain image objects");
3611 unless ($img->{IMG}) {
3612 $class->_set_error("empty input image");
3615 push @imgs, $img->{IMG};
3618 if (my $channels = delete $opts{channels}) {
3619 $result = i_combine(\@imgs, $channels);
3622 $result = i_combine(\@imgs);
3625 $class->_set_error($class->_error_as_msg);
3629 my $img = $class->new;
3630 $img->{IMG} = $result;
3636 # general function to map an image through lookup tables
3639 my ($self, %opts) = @_;
3640 my @chlist = qw( red green blue alpha );
3642 if (!exists($opts{'maps'})) {
3643 # make maps from channel maps
3645 for $chnum (0..$#chlist) {
3646 if (exists $opts{$chlist[$chnum]}) {
3647 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3648 } elsif (exists $opts{'all'}) {
3649 $opts{'maps'}[$chnum] = $opts{'all'};
3653 if ($opts{'maps'} and $self->{IMG}) {
3654 i_map($self->{IMG}, $opts{'maps'} );
3660 my ($self, %opts) = @_;
3662 defined $opts{mindist} or $opts{mindist} = 0;
3664 defined $opts{other}
3665 or return $self->_set_error("No 'other' parameter supplied");
3666 defined $opts{other}{IMG}
3667 or return $self->_set_error("No image data in 'other' image");
3670 or return $self->_set_error("No image data");
3672 my $result = Imager->new;
3673 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3675 or return $self->_set_error($self->_error_as_msg());
3680 # destructive border - image is shrunk by one pixel all around
3683 my ($self,%opts)=@_;
3684 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3685 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3689 # Get the width of an image
3694 if (my $raw = $self->{IMG}) {
3695 return i_img_get_width($raw);
3698 $self->{ERRSTR} = 'image is empty'; return undef;
3702 # Get the height of an image
3707 if (my $raw = $self->{IMG}) {
3708 return i_img_get_height($raw);
3711 $self->{ERRSTR} = 'image is empty'; return undef;
3715 # Get number of channels in an image
3719 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3720 return i_img_getchannels($self->{IMG});
3727 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3728 return i_img_getmask($self->{IMG});
3736 if (!defined($self->{IMG})) {
3737 $self->{ERRSTR} = 'image is empty';
3740 unless (defined $opts{mask}) {
3741 $self->_set_error("mask parameter required");
3744 i_img_setmask( $self->{IMG} , $opts{mask} );
3749 # Get number of colors in an image
3753 my %opts=('maxcolors'=>2**30,@_);
3754 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3755 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3756 return ($rc==-1? undef : $rc);
3759 # Returns a reference to a hash. The keys are colour named (packed) and the
3760 # values are the number of pixels in this colour.
3761 sub getcolorusagehash {
3764 my %opts = ( maxcolors => 2**30, @_ );
3765 my $max_colors = $opts{maxcolors};
3766 unless (defined $max_colors && $max_colors > 0) {
3767 $self->_set_error('maxcolors must be a positive integer');
3771 unless (defined $self->{IMG}) {
3772 $self->_set_error('empty input image');
3776 my $channels= $self->getchannels;
3777 # We don't want to look at the alpha channel, because some gifs using it
3778 # doesn't define it for every colour (but only for some)
3779 $channels -= 1 if $channels == 2 or $channels == 4;
3781 my $height = $self->getheight;
3782 for my $y (0 .. $height - 1) {
3783 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
3784 while (length $colors) {
3785 $color_use{ substr($colors, 0, $channels, '') }++;
3787 keys %color_use > $max_colors
3793 # This will return a ordered array of the colour usage. Kind of the sorted
3794 # version of the values of the hash returned by getcolorusagehash.
3795 # You might want to add safety checks and change the names, etc...
3799 my %opts = ( maxcolors => 2**30, @_ );
3800 my $max_colors = $opts{maxcolors};
3801 unless (defined $max_colors && $max_colors > 0) {
3802 $self->_set_error('maxcolors must be a positive integer');
3806 unless (defined $self->{IMG}) {
3807 $self->_set_error('empty input image');
3811 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
3814 # draw string to an image
3818 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3820 my %input=('x'=>0, 'y'=>0, @_);
3821 defined($input{string}) or $input{string} = $input{text};
3823 unless(defined $input{string}) {
3824 $self->{ERRSTR}="missing required parameter 'string'";
3828 unless($input{font}) {
3829 $self->{ERRSTR}="missing required parameter 'font'";
3833 unless ($input{font}->draw(image=>$self, %input)) {
3845 unless ($self->{IMG}) {
3846 $self->{ERRSTR}='empty input image';
3855 my %input=('x'=>0, 'y'=>0, @_);
3856 defined $input{string}
3857 or $input{string} = $input{text};
3859 unless(exists $input{string}) {
3860 $self->_set_error("missing required parameter 'string'");
3864 unless($input{font}) {
3865 $self->_set_error("missing required parameter 'font'");
3870 unless (@result = $input{font}->align(image=>$img, %input)) {
3874 return wantarray ? @result : $result[0];
3877 my @file_limit_names = qw/width height bytes/;
3879 sub set_file_limits {
3886 @values{@file_limit_names} = (0) x @file_limit_names;
3889 @values{@file_limit_names} = i_get_image_file_limits();
3892 for my $key (keys %values) {
3893 defined $opts{$key} and $values{$key} = $opts{$key};
3896 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3899 sub get_file_limits {
3900 i_get_image_file_limits();
3903 my @check_args = qw(width height channels sample_size);
3905 sub check_file_limits {
3915 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
3916 $opts{sample_size} = length(pack("d", 0));
3919 for my $name (@check_args) {
3920 unless (defined $opts{$name}) {
3921 $class->_set_error("check_file_limits: $name must be defined");
3924 unless ($opts{$name} == int($opts{$name})) {
3925 $class->_set_error("check_file_limits: $name must be a positive integer");
3930 my $result = i_int_check_image_file_limits(@opts{@check_args});
3932 $class->_set_error($class->_error_as_msg());
3938 # Shortcuts that can be exported
3940 sub newcolor { Imager::Color->new(@_); }
3941 sub newfont { Imager::Font->new(@_); }
3943 require Imager::Color::Float;
3944 return Imager::Color::Float->new(@_);
3947 *NC=*newcolour=*newcolor;
3954 #### Utility routines
3957 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3961 my ($self, $msg) = @_;
3964 $self->{ERRSTR} = $msg;
3972 # Default guess for the type of an image from extension
3974 my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
3978 ( map { $_ => $_ } @simple_types ),
3984 pnm => "pnm", # technically wrong, but historically it works in Imager
3997 sub def_guess_type {
4000 my ($ext) = $name =~ /\.([^.]+)$/
4003 my $type = $ext_types{$ext}
4010 return @combine_types;
4013 # get the minimum of a list
4017 for(@_) { if ($_<$mx) { $mx=$_; }}
4021 # get the maximum of a list
4025 for(@_) { if ($_>$mx) { $mx=$_; }}
4029 # string stuff for iptc headers
4033 $str = substr($str,3);
4034 $str =~ s/[\n\r]//g;
4041 # A little hack to parse iptc headers.
4046 my($caption,$photogr,$headln,$credit);
4048 my $str=$self->{IPTCRAW};
4053 @ar=split(/8BIM/,$str);
4058 @sar=split(/\034\002/);
4059 foreach $item (@sar) {
4060 if ($item =~ m/^x/) {
4061 $caption = _clean($item);
4064 if ($item =~ m/^P/) {
4065 $photogr = _clean($item);
4068 if ($item =~ m/^i/) {
4069 $headln = _clean($item);
4072 if ($item =~ m/^n/) {
4073 $credit = _clean($item);
4079 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4086 or die "Only C language supported";
4088 require Imager::ExtUtils;
4089 return Imager::ExtUtils->inline_config;
4092 # threads shouldn't try to close raw Imager objects
4093 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4096 # this serves two purposes:
4097 # - a class method to load the file support modules included with Imager
4098 # (or were included, once the library dependent modules are split out)
4099 # - something for Module::ScanDeps to analyze
4100 # https://rt.cpan.org/Ticket/Display.html?id=6566
4102 eval { require Imager::File::GIF };
4103 eval { require Imager::File::JPEG };
4104 eval { require Imager::File::PNG };
4105 eval { require Imager::File::SGI };
4106 eval { require Imager::File::TIFF };
4107 eval { require Imager::File::ICO };
4108 eval { require Imager::Font::W32 };
4109 eval { require Imager::Font::FT2 };
4110 eval { require Imager::Font::T1 };
4113 # backward compatibility for %formats
4114 package Imager::FORMATS;
4116 use constant IX_FORMATS => 0;
4117 use constant IX_LIST => 1;
4118 use constant IX_INDEX => 2;
4119 use constant IX_CLASSES => 3;
4122 my ($class, $formats, $classes) = @_;
4124 return bless [ $formats, [ ], 0, $classes ], $class;
4128 my ($self, $key) = @_;
4130 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4133 my $loaded = Imager::_load_file($file, \$error);
4138 if ($error =~ /^Can't locate /) {
4139 $error = "Can't locate $file";
4141 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4144 $self->[IX_FORMATS]{$key} = $value;
4150 my ($self, $key) = @_;
4152 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4154 $self->[IX_CLASSES]{$key} or return undef;
4156 return $self->_check($key);
4160 die "%Imager::formats is not user monifiable";
4164 die "%Imager::formats is not user monifiable";
4168 die "%Imager::formats is not user monifiable";
4172 my ($self, $key) = @_;
4174 if (exists $self->[IX_FORMATS]{$key}) {
4175 my $value = $self->[IX_FORMATS]{$key}
4180 $self->_check($key) or return 1==0;
4188 unless (@{$self->[IX_LIST]}) {
4190 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4191 keys %{$self->[IX_FORMATS]};
4193 for my $key (keys %{$self->[IX_CLASSES]}) {
4194 $self->[IX_FORMATS]{$key} and next;
4196 and push @{$self->[IX_LIST]}, $key;
4200 @{$self->[IX_LIST]} or return;
4201 $self->[IX_INDEX] = 1;
4202 return $self->[IX_LIST][0];
4208 $self->[IX_INDEX] < @{$self->[IX_LIST]}
4211 return $self->[IX_LIST][$self->[IX_INDEX]++];
4217 return scalar @{$self->[IX_LIST]};
4222 # Below is the stub of documentation for your module. You better edit it!
4226 Imager - Perl extension for Generating 24 bit Images
4236 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
4241 # see Imager::Files for information on the read() method
4242 my $img = Imager->new(file=>$file)
4243 or die Imager->errstr();
4245 $file =~ s/\.[^.]*$//;
4247 # Create smaller version
4248 # documented in Imager::Transformations
4249 my $thumb = $img->scale(scalefactor=>.3);
4251 # Autostretch individual channels
4252 $thumb->filter(type=>'autolevels');
4254 # try to save in one of these formats
4257 for $format ( qw( png gif jpeg tiff ppm ) ) {
4258 # Check if given format is supported
4259 if ($Imager::formats{$format}) {
4260 $file.="_low.$format";
4261 print "Storing image as: $file\n";
4262 # documented in Imager::Files
4263 $thumb->write(file=>$file) or
4271 Imager is a module for creating and altering images. It can read and
4272 write various image formats, draw primitive shapes like lines,and
4273 polygons, blend multiple images together in various ways, scale, crop,
4274 render text and more.
4276 =head2 Overview of documentation
4282 Imager - This document - Synopsis, Example, Table of Contents and
4287 L<Imager::Tutorial> - a brief introduction to Imager.
4291 L<Imager::Cookbook> - how to do various things with Imager.
4295 L<Imager::ImageTypes> - Basics of constructing image objects with
4296 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
4297 8/16/double bits/channel, color maps, channel masks, image tags, color
4298 quantization. Also discusses basic image information methods.
4302 L<Imager::Files> - IO interaction, reading/writing images, format
4307 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
4312 L<Imager::Color> - Color specification.
4316 L<Imager::Fill> - Fill pattern specification.
4320 L<Imager::Font> - General font rendering, bounding boxes and font
4325 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
4326 blending, pasting, convert and map.
4330 L<Imager::Engines> - Programmable transformations through
4331 C<transform()>, C<transform2()> and C<matrix_transform()>.
4335 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
4340 L<Imager::Expr> - Expressions for evaluation engine used by
4345 L<Imager::Matrix2d> - Helper class for affine transformations.
4349 L<Imager::Fountain> - Helper for making gradient profiles.
4353 L<Imager::API> - using Imager's C API
4357 L<Imager::APIRef> - API function reference
4361 L<Imager::Inline> - using Imager's C API from Inline::C
4365 L<Imager::ExtUtils> - tools to get access to Imager's C API.
4369 L<Imager::Security> - brief security notes.
4373 =head2 Basic Overview
4375 An Image object is created with C<$img = Imager-E<gt>new()>.
4378 $img=Imager->new(); # create empty image
4379 $img->read(file=>'lena.png',type=>'png') or # read image from file
4380 die $img->errstr(); # give an explanation
4381 # if something failed
4383 or if you want to create an empty image:
4385 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
4387 This example creates a completely black image of width 400 and height
4390 =head1 ERROR HANDLING
4392 In general a method will return false when it fails, if it does use
4393 the C<errstr()> method to find out why:
4399 Returns the last error message in that context.
4401 If the last error you received was from calling an object method, such
4402 as read, call errstr() as an object method to find out why:
4404 my $image = Imager->new;
4405 $image->read(file => 'somefile.gif')
4406 or die $image->errstr;
4408 If it was a class method then call errstr() as a class method:
4410 my @imgs = Imager->read_multi(file => 'somefile.gif')
4411 or die Imager->errstr;
4413 Note that in some cases object methods are implemented in terms of
4414 class methods so a failing object method may set both.
4418 The C<Imager-E<gt>new> method is described in detail in
4419 L<Imager::ImageTypes>.
4423 Where to find information on methods for Imager class objects.
4425 addcolors() - L<Imager::ImageTypes/addcolors()> - add colors to a
4428 addtag() - L<Imager::ImageTypes/addtag()> - add image tags
4430 align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
4433 arc() - L<Imager::Draw/arc()> - draw a filled arc
4435 bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
4438 box() - L<Imager::Draw/box()> - draw a filled or outline box.
4440 check_file_limits() - L<Imager::Files/check_file_limits()>
4442 circle() - L<Imager::Draw/circle()> - draw a filled circle
4444 close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
4447 colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
4448 colors in an image's palette (paletted images only)
4450 combine() - L<Imager::Transformations/combine()> - combine channels
4451 from one or more images.
4453 combines() - L<Imager::Draw/combines()> - return a list of the
4454 different combine type keywords
4456 compose() - L<Imager::Transformations/compose()> - compose one image
4459 convert() - L<Imager::Transformations/convert()> - transform the color
4462 copy() - L<Imager::Transformations/copy()> - make a duplicate of an
4465 crop() - L<Imager::Transformations/crop()> - extract part of an image
4467 def_guess_type() - L<Imager::Files/def_guess_type()> - default function
4468 used to guess the output file format based on the output file name
4470 deltag() - L<Imager::ImageTypes/deltag()> - delete image tags
4472 difference() - L<Imager::Filters/difference()> - produce a difference
4473 images from two input images.
4475 errstr() - L</errstr()> - the error from the last failed operation.
4477 filter() - L<Imager::Filters/filter()> - image filtering
4479 findcolor() - L<Imager::ImageTypes/findcolor()> - search the image
4480 palette, if it has one
4482 flip() - L<Imager::Transformations/flip()> - flip an image, vertically,
4485 flood_fill() - L<Imager::Draw/flood_fill()> - fill an enclosed or same
4488 getchannels() - L<Imager::ImageTypes/getchannels()> - the number of
4489 samples per pixel for an image
4491 getcolorcount() - L<Imager::ImageTypes/getcolorcount()> - the number of
4492 different colors used by an image (works for direct color images)
4494 getcolors() - L<Imager::ImageTypes/getcolors()> - get colors from the image
4495 palette, if it has one
4497 getcolorusage() - L<Imager::ImageTypes/getcolorusage()>
4499 getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
4501 get_file_limits() - L<Imager::Files/get_file_limits()>
4503 getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
4506 getmask() - L<Imager::ImageTypes/getmask()> - write mask for the image
4508 getpixel() - L<Imager::Draw/getpixel()> - retrieve one or more pixel
4511 getsamples() - L<Imager::Draw/getsamples()> - retrieve samples from a
4512 row or partial row of pixels.
4514 getscanline() - L<Imager::Draw/getscanline()> - retrieve colors for a
4515 row or partial row of pixels.
4517 getwidth() - L<Imager::ImageTypes/getwidth()> - width of the image in
4520 img_set() - L<Imager::ImageTypes/img_set()> - re-use an Imager object
4523 init() - L<Imager::ImageTypes/init()>
4525 is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
4526 image write functions should write the image in their bilevel (blank
4527 and white, no gray levels) format
4529 is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
4532 line() - L<Imager::Draw/line()> - draw an interval
4534 load_plugin() - L<Imager::Filters/load_plugin()>
4536 log() - L<Imager::ImageTypes/log()> - send a message to the debugging
4539 make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
4540 color palette from one or more input images.
4542 map() - L<Imager::Transformations/map()> - remap color
4545 masked() - L<Imager::ImageTypes/masked()> - make a masked image
4547 matrix_transform() - L<Imager::Engines/matrix_transform()>
4549 maxcolors() - L<Imager::ImageTypes/maxcolors()>
4551 NC() - L<Imager::Handy/NC()>
4553 NCF() - L<Imager::Handy/NCF()>
4555 new() - L<Imager::ImageTypes/new()>
4557 newcolor() - L<Imager::Handy/newcolor()>
4559 newcolour() - L<Imager::Handy/newcolour()>
4561 newfont() - L<Imager::Handy/newfont()>
4563 NF() - L<Imager::Handy/NF()>
4565 open() - L<Imager::Files/read()> - an alias for read()
4567 open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
4571 parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
4574 paste() - L<Imager::Transformations/paste()> - draw an image onto an
4577 polygon() - L<Imager::Draw/polygon()>
4579 polyline() - L<Imager::Draw/polyline()>
4581 preload() - L<Imager::Files/preload()>
4583 read() - L<Imager::Files/read()> - read a single image from an image file
4585 read_multi() - L<Imager::Files/read_multi()> - read multiple images from an image
4588 read_types() - L<Imager::Files/read_types()> - list image types Imager
4591 register_filter() - L<Imager::Filters/register_filter()>
4593 register_reader() - L<Imager::Files/register_reader()>
4595 register_writer() - L<Imager::Files/register_writer()>
4597 rotate() - L<Imager::Transformations/rotate()>
4599 rubthrough() - L<Imager::Transformations/rubthrough()> - draw an image
4600 onto an image and use the alpha channel
4602 scale() - L<Imager::Transformations/scale()>
4604 scale_calculate() - L<Imager::Transformations/scale_calculate()>
4606 scaleX() - L<Imager::Transformations/scaleX()>
4608 scaleY() - L<Imager::Transformations/scaleY()>
4610 setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
4613 set_file_limits() - L<Imager::Files/set_file_limits()>
4615 setmask() - L<Imager::ImageTypes/setmask()>
4617 setpixel() - L<Imager::Draw/setpixel()>
4619 setsamples() - L<Imager::Draw/setsamples()>
4621 setscanline() - L<Imager::Draw/setscanline()>
4623 settag() - L<Imager::ImageTypes/settag()>
4625 string() - L<Imager::Draw/string()> - draw text on an image
4627 tags() - L<Imager::ImageTypes/tags()> - fetch image tags
4629 to_paletted() - L<Imager::ImageTypes/to_paletted()>
4631 to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
4633 to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
4635 to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
4636 double per sample image.
4638 transform() - L<Imager::Engines/"transform()">
4640 transform2() - L<Imager::Engines/"transform2()">
4642 type() - L<Imager::ImageTypes/type()> - type of image (direct vs paletted)
4644 unload_plugin() - L<Imager::Filters/unload_plugin()>
4646 virtual() - L<Imager::ImageTypes/virtual()> - whether the image has it's own
4649 write() - L<Imager::Files/write()> - write an image to a file
4651 write_multi() - L<Imager::Files/write_multi()> - write multiple image to an image
4654 write_types() - L<Imager::Files/read_types()> - list image types Imager
4657 =head1 CONCEPT INDEX
4659 animated GIF - L<Imager::Files/"Writing an animated GIF">
4661 aspect ratio - C<i_xres>, C<i_yres>, C<i_aspect_only> in
4662 L<Imager::ImageTypes/"Common Tags">.
4664 blend - alpha blending one image onto another
4665 L<Imager::Transformations/rubthrough()>
4667 blur - L<Imager::Filters/gaussian>, L<Imager::Filters/conv>
4669 boxes, drawing - L<Imager::Draw/box()>
4671 changes between image - L<Imager::Filters/"Image Difference">
4673 channels, combine into one image - L<Imager::Transformations/combine()>
4675 color - L<Imager::Color>
4677 color names - L<Imager::Color>, L<Imager::Color::Table>
4679 combine modes - L<Imager::Draw/"Combine Types">
4681 compare images - L<Imager::Filters/"Image Difference">
4683 contrast - L<Imager::Filters/contrast>, L<Imager::Filters/autolevels>
4685 convolution - L<Imager::Filters/conv>
4687 cropping - L<Imager::Transformations/crop()>
4689 CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4691 C<diff> images - L<Imager::Filters/"Image Difference">
4693 dpi - C<i_xres>, C<i_yres> in L<Imager::ImageTypes/"Common Tags">,
4694 L<Imager::Cookbook/"Image spatial resolution">
4696 drawing boxes - L<Imager::Draw/box()>
4698 drawing lines - L<Imager::Draw/line()>
4700 drawing text - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>
4702 error message - L</"ERROR HANDLING">
4704 files, font - L<Imager::Font>
4706 files, image - L<Imager::Files>
4708 filling, types of fill - L<Imager::Fill>
4710 filling, boxes - L<Imager::Draw/box()>
4712 filling, flood fill - L<Imager::Draw/flood_fill()>
4714 flood fill - L<Imager::Draw/flood_fill()>
4716 fonts - L<Imager::Font>
4718 fonts, drawing with - L<Imager::Draw/string()>,
4719 L<Imager::Draw/align_string()>, L<Imager::Font::Wrap>
4721 fonts, metrics - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4723 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
4725 fountain fill - L<Imager::Fill/"Fountain fills">,
4726 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4727 L<Imager::Filters/gradgen>
4729 GIF files - L<Imager::Files/"GIF">
4731 GIF files, animated - L<Imager::Files/"Writing an animated GIF">
4733 gradient fill - L<Imager::Fill/"Fountain fills">,
4734 L<Imager::Filters/fountain>, L<Imager::Fountain>,
4735 L<Imager::Filters/gradgen>
4737 gray scale, convert image to - L<Imager::Transformations/convert()>
4739 gaussian blur - L<Imager::Filters/gaussian>
4741 hatch fills - L<Imager::Fill/"Hatched fills">
4743 ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
4745 invert image - L<Imager::Filters/hardinvert>,
4746 L<Imager::Filters/hardinvertall>
4748 JPEG - L<Imager::Files/"JPEG">
4750 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
4752 lines, drawing - L<Imager::Draw/line()>
4754 matrix - L<Imager::Matrix2d>,
4755 L<Imager::Engines/"Matrix Transformations">,
4756 L<Imager::Font/transform()>
4758 metadata, image - L<Imager::ImageTypes/"Tags">
4760 mosaic - L<Imager::Filters/mosaic>
4762 noise, filter - L<Imager::Filters/noise>
4764 noise, rendered - L<Imager::Filters/turbnoise>,
4765 L<Imager::Filters/radnoise>
4767 paste - L<Imager::Transformations/paste()>,
4768 L<Imager::Transformations/rubthrough()>
4770 pseudo-color image - L<Imager::ImageTypes/to_paletted()>,
4771 L<Imager::ImageTypes/new()>
4773 =for stopwords posterize
4775 posterize - L<Imager::Filters/postlevels>
4777 PNG files - L<Imager::Files>, L<Imager::Files/"PNG">
4779 PNM - L<Imager::Files/"PNM (Portable aNy Map)">
4781 rectangles, drawing - L<Imager::Draw/box()>
4783 resizing an image - L<Imager::Transformations/scale()>,
4784 L<Imager::Transformations/crop()>
4786 RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
4788 saving an image - L<Imager::Files>
4790 scaling - L<Imager::Transformations/scale()>
4792 security - L<Imager::Security>
4794 SGI files - L<Imager::Files/"SGI (RGB, BW)">
4796 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
4798 size, image - L<Imager::ImageTypes/getwidth()>,
4799 L<Imager::ImageTypes/getheight()>
4801 size, text - L<Imager::Font/bounding_box()>
4803 tags, image metadata - L<Imager::ImageTypes/"Tags">
4805 text, drawing - L<Imager::Draw/string()>, L<Imager::Draw/align_string()>,
4806 L<Imager::Font::Wrap>
4808 text, wrapping text in an area - L<Imager::Font::Wrap>
4810 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
4812 tiles, color - L<Imager::Filters/mosaic>
4814 transparent images - L<Imager::ImageTypes>,
4815 L<Imager::Cookbook/"Transparent PNG">
4817 =for stopwords unsharp
4819 unsharp mask - L<Imager::Filters/unsharpmask>
4821 watermark - L<Imager::Filters/watermark>
4823 writing an image to a file - L<Imager::Files>
4827 Imager doesn't support perl threads.
4829 Imager has limited code to prevent double frees if you create images,
4830 colors etc, and then create a thread, but has no code to prevent two
4831 threads entering Imager's error handling code, and none is likely to
4836 The best place to get help with Imager is the mailing list.
4838 To subscribe send a message with C<subscribe> in the body to:
4840 imager-devel+request@molar.is
4846 L<http://www.molar.is/en/lists/imager-devel/>
4850 where you can also find the mailing list archive.
4852 You can report bugs by pointing your browser at:
4856 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
4860 or by sending an email to:
4864 bug-Imager@rt.cpan.org
4868 Please remember to include the versions of Imager, perl, supporting
4869 libraries, and any relevant code. If you have specific images that
4870 cause the problems, please include those too.
4872 If you don't want to publish your email address on a mailing list you
4873 can use CPAN::Forum:
4875 http://www.cpanforum.com/dist/Imager
4877 You will need to register to post.
4879 =head1 CONTRIBUTING TO IMAGER
4885 If you like or dislike Imager, you can add a public review of Imager
4888 http://cpanratings.perl.org/dist/Imager
4890 =for stopwords Bitcard
4892 This requires a Bitcard account (http://www.bitcard.org).
4894 You can also send email to the maintainer below.
4896 If you send me a bug report via email, it will be copied to Request
4901 I accept patches, preferably against the master branch in git. Please
4902 include an explanation of the reason for why the patch is needed or
4905 Your patch should include regression tests where possible, otherwise
4906 it will be delayed until I get a chance to write them.
4908 To browse Imager's git repository:
4910 http://git.imager.perl.org/imager.git
4914 https://github.com/tonycoz/imager
4918 git clone git://git.imager.perl.org/imager.git
4922 git clone git://github.com/tonycoz/imager.git
4926 Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
4928 Arnar M. Hrafnkelsson is the original author of Imager.
4930 Many others have contributed to Imager, please see the C<README> for a
4935 Imager is licensed under the same terms as perl itself.
4938 makeblendedfont Fontforge
4940 A test font, generated by the Debian packaged Fontforge,
4941 F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
4942 copyrighted by Adobe. See F<adobe.txt> in the source for license
4947 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
4948 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
4949 L<Imager::Font>(3), L<Imager::Transformations>(3),
4950 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
4951 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
4953 L<http://imager.perl.org/>
4955 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
4957 Other perl imaging modules include:
4959 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3),
4960 L<Prima::Image>, L<IPA>.
4962 If you're trying to use Imager for array processing, you should
4963 probably using L<PDL>.