4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR $fontstate %OPCODES $I2P $FORMATGUESS $warn_obsolete);
82 i_writetiff_wiol_faxable
152 XSLoader::load(Imager => $VERSION);
156 push @ISA, 'DynaLoader';
157 bootstrap Imager $VERSION;
162 i_init_fonts(); # Initialize font engines
163 Imager::Font::__init();
164 for(i_list_formats()) { $formats{$_}++; }
166 if ($formats{'t1'}) {
170 if (!$formats{'t1'} and !$formats{'tt'}
171 && !$formats{'ft2'} && !$formats{'w32'}) {
172 $fontstate='no font support';
175 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
179 # the members of the subhashes under %filters are:
180 # callseq - a list of the parameters to the underlying filter in the
181 # order they are passed
182 # callsub - a code ref that takes a named parameter list and calls the
184 # defaults - a hash of default values
185 # names - defines names for value of given parameters so if the names
186 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
187 # foo parameter, the filter will receive 1 for the foo
190 callseq => ['image','intensity'],
191 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
195 callseq => ['image', 'amount', 'subtype'],
196 defaults => { amount=>3,subtype=>0 },
197 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
200 $filters{hardinvert} ={
201 callseq => ['image'],
203 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
206 $filters{autolevels} ={
207 callseq => ['image','lsat','usat','skew'],
208 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
209 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
212 $filters{turbnoise} ={
213 callseq => ['image'],
214 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
215 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
218 $filters{radnoise} ={
219 callseq => ['image'],
220 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
221 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
225 callseq => ['image', 'coef'],
227 callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
232 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
233 defaults => { dist => 0 },
237 my @colors = @{$hsh{colors}};
240 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
244 $filters{nearest_color} =
246 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
251 # make sure the segments are specified with colors
253 for my $color (@{$hsh{colors}}) {
254 my $new_color = _color($color)
255 or die $Imager::ERRSTR."\n";
256 push @colors, $new_color;
259 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
261 or die Imager->_error_as_msg() . "\n";
264 $filters{gaussian} = {
265 callseq => [ 'image', 'stddev' ],
267 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
271 callseq => [ qw(image size) ],
272 defaults => { size => 20 },
273 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
277 callseq => [ qw(image bump elevation lightx lighty st) ],
278 defaults => { elevation=>0, st=> 2 },
281 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
282 $hsh{lightx}, $hsh{lighty}, $hsh{st});
285 $filters{bumpmap_complex} =
287 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
298 Ia => Imager::Color->new(rgb=>[0,0,0]),
299 Il => Imager::Color->new(rgb=>[255,255,255]),
300 Is => Imager::Color->new(rgb=>[255,255,255]),
304 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
305 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
306 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
310 $filters{postlevels} =
312 callseq => [ qw(image levels) ],
313 defaults => { levels => 10 },
314 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
316 $filters{watermark} =
318 callseq => [ qw(image wmark tx ty pixdiff) ],
319 defaults => { pixdiff=>10, tx=>0, ty=>0 },
323 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
329 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
331 ftype => { linear => 0,
337 repeat => { none => 0,
352 multiply => 2, mult => 2,
355 subtract => 5, 'sub' => 5,
365 defaults => { ftype => 0, repeat => 0, combine => 0,
366 super_sample => 0, ssample_param => 4,
369 Imager::Color->new(0,0,0),
370 Imager::Color->new(255, 255, 255),
379 # make sure the segments are specified with colors
381 for my $segment (@{$hsh{segments}}) {
382 my @new_segment = @$segment;
384 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
385 push @segments, \@new_segment;
388 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
389 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
390 $hsh{ssample_param}, \@segments)
391 or die Imager->_error_as_msg() . "\n";
394 $filters{unsharpmask} =
396 callseq => [ qw(image stddev scale) ],
397 defaults => { stddev=>2.0, scale=>1.0 },
401 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
405 $FORMATGUESS=\&def_guess_type;
415 # NOTE: this might be moved to an import override later on
419 # (look through @_ for special tags, process, and remove them);
421 # print Dumper($pack);
426 i_init_log($_[0],$_[1]);
427 i_log_entry("Imager $VERSION starting\n", 1);
432 my %parms=(loglevel=>1,@_);
434 init_log($parms{'log'},$parms{'loglevel'});
437 if (exists $parms{'warn_obsolete'}) {
438 $warn_obsolete = $parms{'warn_obsolete'};
441 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
442 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
446 if (exists $parms{'t1log'}) {
447 i_init_fonts($parms{'t1log'});
453 print "shutdown code\n";
454 # for(keys %instances) { $instances{$_}->DESTROY(); }
455 malloc_state(); # how do decide if this should be used? -- store something from the import
456 print "Imager exiting\n";
460 # Load a filter plugin
465 my ($DSO_handle,$str)=DSO_open($filename);
466 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
467 my %funcs=DSO_funclist($DSO_handle);
468 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
470 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
472 $DSOs{$filename}=[$DSO_handle,\%funcs];
475 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
476 $DEBUG && print "eval string:\n",$evstr,"\n";
488 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
489 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
490 for(keys %{$funcref}) {
492 $DEBUG && print "unloading: $_\n";
494 my $rc=DSO_close($DSO_handle);
495 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
499 # take the results of i_error() and make a message out of it
501 return join(": ", map $_->[0], i_errors());
504 # this function tries to DWIM for color parameters
505 # color objects are used as is
506 # simple scalars are simply treated as single parameters to Imager::Color->new
507 # hashrefs are treated as named argument lists to Imager::Color->new
508 # arrayrefs are treated as list arguments to Imager::Color->new iff any
510 # other arrayrefs are treated as list arguments to Imager::Color::Float
514 # perl 5.6.0 seems to do weird things to $arg if we don't make an
515 # explicitly stringified copy
516 # I vaguely remember a bug on this on p5p, but couldn't find it
517 # through bugs.perl.org (I had trouble getting it to find any bugs)
518 my $copy = $arg . "";
522 if (UNIVERSAL::isa($arg, "Imager::Color")
523 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
527 if ($copy =~ /^HASH\(/) {
528 $result = Imager::Color->new(%$arg);
530 elsif ($copy =~ /^ARRAY\(/) {
531 if (grep $_ > 1, @$arg) {
532 $result = Imager::Color->new(@$arg);
535 $result = Imager::Color::Float->new(@$arg);
539 $Imager::ERRSTR = "Not a color";
544 # assume Imager::Color::new knows how to handle it
545 $result = Imager::Color->new($arg);
553 # Methods to be called on objects.
556 # Create a new Imager object takes very few parameters.
557 # usually you call this method and then call open from
558 # the resulting object
565 $self->{IMG}=undef; # Just to indicate what exists
566 $self->{ERRSTR}=undef; #
567 $self->{DEBUG}=$DEBUG;
568 $self->{DEBUG} && print "Initialized Imager\n";
569 if (defined $hsh{xsize} && defined $hsh{ysize}) {
570 unless ($self->img_set(%hsh)) {
571 $Imager::ERRSTR = $self->{ERRSTR};
578 # Copy an entire image with no changes
579 # - if an image has magic the copy of it will not be magical
583 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
585 unless (defined wantarray) {
587 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
591 my $newcopy=Imager->new();
592 $newcopy->{IMG} = i_copy($self->{IMG});
601 unless ($self->{IMG}) {
602 $self->_set_error('empty input image');
605 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
606 my $src = $input{img} || $input{src};
608 $self->_set_error("no source image");
611 $input{left}=0 if $input{left} <= 0;
612 $input{top}=0 if $input{top} <= 0;
614 my($r,$b)=i_img_info($src->{IMG});
615 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
616 my ($src_right, $src_bottom);
617 if ($input{src_coords}) {
618 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
621 if (defined $input{src_maxx}) {
622 $src_right = $input{src_maxx};
624 elsif (defined $input{width}) {
625 if ($input{width} <= 0) {
626 $self->_set_error("paste: width must me positive");
629 $src_right = $src_left + $input{width};
634 if (defined $input{src_maxx}) {
635 $src_bottom = $input{src_maxy};
637 elsif (defined $input{height}) {
638 if ($input{height} < 0) {
639 $self->_set_error("paste: height must be positive");
642 $src_bottom = $src_top + $input{height};
649 $src_right > $r and $src_right = $r;
650 $src_bottom > $r and $src_bottom = $b;
652 if ($src_right <= $src_left
653 || $src_bottom < $src_top) {
654 $self->_set_error("nothing to paste");
658 i_copyto($self->{IMG}, $src->{IMG},
659 $src_left, $src_top, $src_right, $src_bottom,
660 $input{left}, $input{top});
662 return $self; # What should go here??
665 # Crop an image - i.e. return a new image that is smaller
669 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
671 unless (defined wantarray) {
673 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
679 my ($w, $h, $l, $r, $b, $t) =
680 @hsh{qw(width height left right bottom top)};
682 # work through the various possibilities
687 elsif (!defined $r) {
688 $r = $self->getwidth;
700 $l = int(0.5+($self->getwidth()-$w)/2);
705 $r = $self->getwidth;
711 elsif (!defined $b) {
712 $b = $self->getheight;
724 $t=int(0.5+($self->getheight()-$h)/2);
729 $b = $self->getheight;
732 ($l,$r)=($r,$l) if $l>$r;
733 ($t,$b)=($b,$t) if $t>$b;
736 $r > $self->getwidth and $r = $self->getwidth;
738 $b > $self->getheight and $b = $self->getheight;
740 if ($l == $r || $t == $b) {
741 $self->_set_error("resulting image would have no content");
745 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
747 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
752 my ($self, %opts) = @_;
754 $self->{IMG} or return $self->_set_error("Not a valid image");
756 my $x = $opts{xsize} || $self->getwidth;
757 my $y = $opts{ysize} || $self->getheight;
758 my $channels = $opts{channels} || $self->getchannels;
760 my $out = Imager->new;
761 if ($channels == $self->getchannels) {
762 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
765 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
767 unless ($out->{IMG}) {
768 $self->{ERRSTR} = $self->_error_as_msg;
775 # Sets an image to a certain size and channel number
776 # if there was previously data in the image it is discarded
781 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
783 if (defined($self->{IMG})) {
784 # let IIM_DESTROY destroy it, it's possible this image is
785 # referenced from a virtual image (like masked)
786 #i_img_destroy($self->{IMG});
790 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
791 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
792 $hsh{maxcolors} || 256);
794 elsif ($hsh{bits} eq 'double') {
795 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
797 elsif ($hsh{bits} == 16) {
798 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
801 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
805 unless ($self->{IMG}) {
806 $self->{ERRSTR} = Imager->_error_as_msg();
813 # created a masked version of the current image
817 $self or return undef;
818 my %opts = (left => 0,
820 right => $self->getwidth,
821 bottom => $self->getheight,
823 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
825 my $result = Imager->new;
826 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
827 $opts{top}, $opts{right} - $opts{left},
828 $opts{bottom} - $opts{top});
829 # keep references to the mask and base images so they don't
831 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
836 # convert an RGB image into a paletted image
840 if (@_ != 1 && !ref $_[0]) {
847 unless (defined wantarray) {
849 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
853 my $result = Imager->new;
854 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
856 #print "Type ", i_img_type($result->{IMG}), "\n";
858 if ($result->{IMG}) {
862 $self->{ERRSTR} = $self->_error_as_msg;
867 # convert a paletted (or any image) to an 8-bit/channel RGB images
872 unless (defined wantarray) {
874 warn "to_rgb8() called in void context - to_rgb8() returns the cropped image at $caller[1] line $caller[2]\n";
879 $result = Imager->new;
880 $result->{IMG} = i_img_to_rgb($self->{IMG})
889 my %opts = (colors=>[], @_);
891 @{$opts{colors}} or return undef;
893 $self->{IMG} and i_addcolors($self->{IMG}, @{$opts{colors}});
898 my %opts = (start=>0, colors=>[], @_);
899 @{$opts{colors}} or return undef;
901 $self->{IMG} and i_setcolors($self->{IMG}, $opts{start}, @{$opts{colors}});
907 if (!exists $opts{start} && !exists $opts{count}) {
910 $opts{count} = $self->colorcount;
912 elsif (!exists $opts{count}) {
915 elsif (!exists $opts{start}) {
920 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
924 i_colorcount($_[0]{IMG});
928 i_maxcolors($_[0]{IMG});
934 $opts{color} or return undef;
936 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
941 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
942 if ($bits && $bits == length(pack("d", 1)) * 8) {
951 return i_img_type($self->{IMG}) ? "paletted" : "direct";
957 $self->{IMG} and i_img_virtual($self->{IMG});
961 my ($self, %opts) = @_;
963 $self->{IMG} or return;
965 if (defined $opts{name}) {
969 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
970 push @result, (i_tags_get($self->{IMG}, $found))[1];
973 return wantarray ? @result : $result[0];
975 elsif (defined $opts{code}) {
979 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
980 push @result, (i_tags_get($self->{IMG}, $found))[1];
987 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
990 return i_tags_count($self->{IMG});
999 return -1 unless $self->{IMG};
1001 if (defined $opts{value}) {
1002 if ($opts{value} =~ /^\d+$/) {
1004 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1007 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1010 elsif (defined $opts{data}) {
1011 # force addition as a string
1012 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1015 $self->{ERRSTR} = "No value supplied";
1019 elsif ($opts{code}) {
1020 if (defined $opts{value}) {
1021 if ($opts{value} =~ /^\d+$/) {
1023 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1026 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1029 elsif (defined $opts{data}) {
1030 # force addition as a string
1031 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1034 $self->{ERRSTR} = "No value supplied";
1047 return 0 unless $self->{IMG};
1049 if (defined $opts{'index'}) {
1050 return i_tags_delete($self->{IMG}, $opts{'index'});
1052 elsif (defined $opts{name}) {
1053 return i_tags_delbyname($self->{IMG}, $opts{name});
1055 elsif (defined $opts{code}) {
1056 return i_tags_delbycode($self->{IMG}, $opts{code});
1059 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1065 my ($self, %opts) = @_;
1068 $self->deltag(name=>$opts{name});
1069 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1071 elsif (defined $opts{code}) {
1072 $self->deltag(code=>$opts{code});
1073 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1081 sub _get_reader_io {
1082 my ($self, $input) = @_;
1085 return $input->{io}, undef;
1087 elsif ($input->{fd}) {
1088 return io_new_fd($input->{fd});
1090 elsif ($input->{fh}) {
1091 my $fd = fileno($input->{fh});
1093 $self->_set_error("Handle in fh option not opened");
1096 return io_new_fd($fd);
1098 elsif ($input->{file}) {
1099 my $file = IO::File->new($input->{file}, "r");
1101 $self->_set_error("Could not open $input->{file}: $!");
1105 return (io_new_fd(fileno($file)), $file);
1107 elsif ($input->{data}) {
1108 return io_new_buffer($input->{data});
1110 elsif ($input->{callback} || $input->{readcb}) {
1111 if (!$input->{seekcb}) {
1112 $self->_set_error("Need a seekcb parameter");
1114 if ($input->{maxbuffer}) {
1115 return io_new_cb($input->{writecb},
1116 $input->{callback} || $input->{readcb},
1117 $input->{seekcb}, $input->{closecb},
1118 $input->{maxbuffer});
1121 return io_new_cb($input->{writecb},
1122 $input->{callback} || $input->{readcb},
1123 $input->{seekcb}, $input->{closecb});
1127 $self->_set_error("file/fd/fh/data/callback parameter missing");
1132 sub _get_writer_io {
1133 my ($self, $input, $type) = @_;
1136 return io_new_fd($input->{fd});
1138 elsif ($input->{fh}) {
1139 my $fd = fileno($input->{fh});
1141 $self->_set_error("Handle in fh option not opened");
1145 my $oldfh = select($input->{fh});
1146 # flush anything that's buffered, and make sure anything else is flushed
1149 return io_new_fd($fd);
1151 elsif ($input->{file}) {
1152 my $fh = new IO::File($input->{file},"w+");
1154 $self->_set_error("Could not open file $input->{file}: $!");
1157 binmode($fh) or die;
1158 return (io_new_fd(fileno($fh)), $fh);
1160 elsif ($input->{data}) {
1161 return io_new_bufchain();
1163 elsif ($input->{callback} || $input->{writecb}) {
1164 if ($input->{maxbuffer}) {
1165 return io_new_cb($input->{callback} || $input->{writecb},
1167 $input->{seekcb}, $input->{closecb},
1168 $input->{maxbuffer});
1171 return io_new_cb($input->{callback} || $input->{writecb},
1173 $input->{seekcb}, $input->{closecb});
1177 $self->_set_error("file/fd/fh/data/callback parameter missing");
1182 # Read an image from file
1188 if (defined($self->{IMG})) {
1189 # let IIM_DESTROY do the destruction, since the image may be
1190 # referenced from elsewhere
1191 #i_img_destroy($self->{IMG});
1192 undef($self->{IMG});
1195 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1197 unless ($input{'type'}) {
1198 $input{'type'} = i_test_format_probe($IO, -1);
1201 unless ($input{'type'}) {
1202 $self->_set_error('type parameter missing and not possible to guess from extension');
1206 unless ($formats{$input{'type'}}) {
1207 $self->_set_error("format '$input{'type'}' not supported");
1212 if ( $input{'type'} eq 'jpeg' ) {
1213 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1214 if ( !defined($self->{IMG}) ) {
1215 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1217 $self->{DEBUG} && print "loading a jpeg file\n";
1221 if ( $input{'type'} eq 'tiff' ) {
1222 my $page = $input{'page'};
1223 defined $page or $page = 0;
1224 # Fixme, check if that length parameter is ever needed
1225 $self->{IMG}=i_readtiff_wiol( $IO, -1, $page );
1226 if ( !defined($self->{IMG}) ) {
1227 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1229 $self->{DEBUG} && print "loading a tiff file\n";
1233 if ( $input{'type'} eq 'pnm' ) {
1234 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1235 if ( !defined($self->{IMG}) ) {
1236 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1239 $self->{DEBUG} && print "loading a pnm file\n";
1243 if ( $input{'type'} eq 'png' ) {
1244 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1245 if ( !defined($self->{IMG}) ) {
1246 $self->{ERRSTR} = $self->_error_as_msg();
1249 $self->{DEBUG} && print "loading a png file\n";
1252 if ( $input{'type'} eq 'bmp' ) {
1253 $self->{IMG}=i_readbmp_wiol( $IO );
1254 if ( !defined($self->{IMG}) ) {
1255 $self->{ERRSTR}=$self->_error_as_msg();
1258 $self->{DEBUG} && print "loading a bmp file\n";
1261 if ( $input{'type'} eq 'gif' ) {
1262 if ($input{colors} && !ref($input{colors})) {
1263 # must be a reference to a scalar that accepts the colour map
1264 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1267 if ($input{'gif_consolidate'}) {
1268 if ($input{colors}) {
1270 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1272 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1276 $self->{IMG} =i_readgif_wiol( $IO );
1280 my $page = $input{'page'};
1281 defined $page or $page = 0;
1282 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1283 if ($input{colors}) {
1284 ${ $input{colors} } =
1285 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1289 if ( !defined($self->{IMG}) ) {
1290 $self->{ERRSTR}=$self->_error_as_msg();
1293 $self->{DEBUG} && print "loading a gif file\n";
1296 if ( $input{'type'} eq 'tga' ) {
1297 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1298 if ( !defined($self->{IMG}) ) {
1299 $self->{ERRSTR}=$self->_error_as_msg();
1302 $self->{DEBUG} && print "loading a tga file\n";
1305 if ( $input{'type'} eq 'rgb' ) {
1306 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1307 if ( !defined($self->{IMG}) ) {
1308 $self->{ERRSTR}=$self->_error_as_msg();
1311 $self->{DEBUG} && print "loading a tga file\n";
1315 if ( $input{'type'} eq 'raw' ) {
1316 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1318 if ( !($params{xsize} && $params{ysize}) ) {
1319 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1323 $self->{IMG} = i_readraw_wiol( $IO,
1326 $params{datachannels},
1327 $params{storechannels},
1328 $params{interleave});
1329 if ( !defined($self->{IMG}) ) {
1330 $self->{ERRSTR}=$self->_error_as_msg();
1333 $self->{DEBUG} && print "loading a raw file\n";
1339 sub _fix_gif_positions {
1340 my ($opts, $opt, $msg, @imgs) = @_;
1342 my $positions = $opts->{'gif_positions'};
1344 for my $pos (@$positions) {
1345 my ($x, $y) = @$pos;
1346 my $img = $imgs[$index++];
1347 $img->settag(name=>'gif_left', value=>$x);
1348 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1350 $$msg .= "replaced with the gif_left and gif_top tags";
1355 gif_each_palette=>'gif_local_map',
1356 interlace => 'gif_interlace',
1357 gif_delays => 'gif_delay',
1358 gif_positions => \&_fix_gif_positions,
1359 gif_loop_count => 'gif_loop',
1363 my ($self, $opts, $prefix, @imgs) = @_;
1365 for my $opt (keys %$opts) {
1367 if ($obsolete_opts{$opt}) {
1368 my $new = $obsolete_opts{$opt};
1369 my $msg = "Obsolete option $opt ";
1371 $new->($opts, $opt, \$msg, @imgs);
1374 $msg .= "replaced with the $new tag ";
1377 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1378 warn $msg if $warn_obsolete && $^W;
1380 next unless $tagname =~ /^\Q$prefix/;
1381 my $value = $opts->{$opt};
1383 if (UNIVERSAL::isa($value, "Imager::Color")) {
1384 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1385 for my $img (@imgs) {
1386 $img->settag(name=>$tagname, value=>$tag);
1389 elsif (ref($value) eq 'ARRAY') {
1390 for my $i (0..$#$value) {
1391 my $val = $value->[$i];
1393 if (UNIVERSAL::isa($val, "Imager::Color")) {
1394 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1396 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1399 $self->_set_error("Unknown reference type " . ref($value) .
1400 " supplied in array for $opt");
1406 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1411 $self->_set_error("Unknown reference type " . ref($value) .
1412 " supplied for $opt");
1417 # set it as a tag for every image
1418 for my $img (@imgs) {
1419 $img->settag(name=>$tagname, value=>$value);
1427 # Write an image to file
1430 my %input=(jpegquality=>75,
1440 $self->_set_opts(\%input, "i_", $self)
1443 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1445 if (!$input{'type'} and $input{file}) {
1446 $input{'type'}=$FORMATGUESS->($input{file});
1448 if (!$input{'type'}) {
1449 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1453 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1455 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1458 if ($input{'type'} eq 'tiff') {
1459 $self->_set_opts(\%input, "tiff_", $self)
1461 $self->_set_opts(\%input, "exif_", $self)
1464 if (defined $input{class} && $input{class} eq 'fax') {
1465 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1466 $self->{ERRSTR} = $self->_error_as_msg();
1470 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1471 $self->{ERRSTR} = $self->_error_as_msg();
1475 } elsif ( $input{'type'} eq 'pnm' ) {
1476 $self->_set_opts(\%input, "pnm_", $self)
1478 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1479 $self->{ERRSTR} = $self->_error_as_msg();
1482 $self->{DEBUG} && print "writing a pnm file\n";
1483 } elsif ( $input{'type'} eq 'raw' ) {
1484 $self->_set_opts(\%input, "raw_", $self)
1486 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1487 $self->{ERRSTR} = $self->_error_as_msg();
1490 $self->{DEBUG} && print "writing a raw file\n";
1491 } elsif ( $input{'type'} eq 'png' ) {
1492 $self->_set_opts(\%input, "png_", $self)
1494 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1495 $self->{ERRSTR}='unable to write png image';
1498 $self->{DEBUG} && print "writing a png file\n";
1499 } elsif ( $input{'type'} eq 'jpeg' ) {
1500 $self->_set_opts(\%input, "jpeg_", $self)
1502 $self->_set_opts(\%input, "exif_", $self)
1504 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1505 $self->{ERRSTR} = $self->_error_as_msg();
1508 $self->{DEBUG} && print "writing a jpeg file\n";
1509 } elsif ( $input{'type'} eq 'bmp' ) {
1510 $self->_set_opts(\%input, "bmp_", $self)
1512 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1513 $self->{ERRSTR}='unable to write bmp image';
1516 $self->{DEBUG} && print "writing a bmp file\n";
1517 } elsif ( $input{'type'} eq 'tga' ) {
1518 $self->_set_opts(\%input, "tga_", $self)
1521 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1522 $self->{ERRSTR}=$self->_error_as_msg();
1525 $self->{DEBUG} && print "writing a tga file\n";
1526 } elsif ( $input{'type'} eq 'gif' ) {
1527 $self->_set_opts(\%input, "gif_", $self)
1529 # compatibility with the old interfaces
1530 if ($input{gifquant} eq 'lm') {
1531 $input{make_colors} = 'addi';
1532 $input{translate} = 'perturb';
1533 $input{perturb} = $input{lmdither};
1534 } elsif ($input{gifquant} eq 'gen') {
1535 # just pass options through
1537 $input{make_colors} = 'webmap'; # ignored
1538 $input{translate} = 'giflib';
1540 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1541 $self->{ERRSTR} = $self->_error_as_msg;
1546 if (exists $input{'data'}) {
1547 my $data = io_slurp($IO);
1549 $self->{ERRSTR}='Could not slurp from buffer';
1552 ${$input{data}} = $data;
1558 my ($class, $opts, @images) = @_;
1560 if (!$opts->{'type'} && $opts->{'file'}) {
1561 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1563 unless ($opts->{'type'}) {
1564 $class->_set_error('type parameter missing and not possible to guess from extension');
1567 # translate to ImgRaw
1568 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1569 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1572 $class->_set_opts($opts, "i_", @images)
1574 my @work = map $_->{IMG}, @images;
1575 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1577 if ($opts->{'type'} eq 'gif') {
1578 $class->_set_opts($opts, "gif_", @images)
1580 my $gif_delays = $opts->{gif_delays};
1581 local $opts->{gif_delays} = $gif_delays;
1582 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1583 # assume the caller wants the same delay for each frame
1584 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1586 my $res = i_writegif_wiol($IO, $opts, @work);
1587 $res or $class->_set_error($class->_error_as_msg());
1590 elsif ($opts->{'type'} eq 'tiff') {
1591 $class->_set_opts($opts, "tiff_", @images)
1593 $class->_set_opts($opts, "exif_", @images)
1596 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1597 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1598 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1601 $res = i_writetiff_multi_wiol($IO, @work);
1603 $res or $class->_set_error($class->_error_as_msg());
1607 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1612 # read multiple images from a file
1614 my ($class, %opts) = @_;
1616 if ($opts{file} && !exists $opts{'type'}) {
1618 my $type = $FORMATGUESS->($opts{file});
1619 $opts{'type'} = $type;
1621 unless ($opts{'type'}) {
1622 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1626 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1628 if ($opts{'type'} eq 'gif') {
1630 @imgs = i_readgif_multi_wiol($IO);
1633 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1637 $ERRSTR = _error_as_msg();
1641 elsif ($opts{'type'} eq 'tiff') {
1642 my @imgs = i_readtiff_multi_wiol($IO, -1);
1645 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1649 $ERRSTR = _error_as_msg();
1654 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1658 # Destroy an Imager object
1662 # delete $instances{$self};
1663 if (defined($self->{IMG})) {
1664 # the following is now handled by the XS DESTROY method for
1665 # Imager::ImgRaw object
1666 # Re-enabling this will break virtual images
1667 # tested for in t/t020masked.t
1668 # i_img_destroy($self->{IMG});
1669 undef($self->{IMG});
1671 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1675 # Perform an inplace filter of an image
1676 # that is the image will be overwritten with the data
1682 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1684 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1686 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1687 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1690 if ($filters{$input{'type'}}{names}) {
1691 my $names = $filters{$input{'type'}}{names};
1692 for my $name (keys %$names) {
1693 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1694 $input{$name} = $names->{$name}{$input{$name}};
1698 if (defined($filters{$input{'type'}}{defaults})) {
1699 %hsh=( image => $self->{IMG},
1701 %{$filters{$input{'type'}}{defaults}},
1704 %hsh=( image => $self->{IMG},
1709 my @cs=@{$filters{$input{'type'}}{callseq}};
1712 if (!defined($hsh{$_})) {
1713 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1718 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1719 &{$filters{$input{'type'}}{callsub}}(%hsh);
1722 chomp($self->{ERRSTR} = $@);
1728 $self->{DEBUG} && print "callseq is: @cs\n";
1729 $self->{DEBUG} && print "matching callseq is: @b\n";
1734 sub register_filter {
1736 my %hsh = ( defaults => {}, @_ );
1739 or die "register_filter() with no type\n";
1740 defined $hsh{callsub}
1741 or die "register_filter() with no callsub\n";
1742 defined $hsh{callseq}
1743 or die "register_filter() with no callseq\n";
1745 exists $filters{$hsh{type}}
1748 $filters{$hsh{type}} = \%hsh;
1753 # Scale an image to requested size and return the scaled version
1757 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1758 my $img = Imager->new();
1759 my $tmp = Imager->new();
1761 my $scalefactor = $opts{scalefactor};
1763 unless (defined wantarray) {
1764 my @caller = caller;
1765 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1769 unless ($self->{IMG}) {
1770 $self->_set_error('empty input image');
1774 # work out the scaling
1775 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1776 my ($xpix, $ypix)=( $opts{xpixels} / $self->getwidth() ,
1777 $opts{ypixels} / $self->getheight() );
1778 if ($opts{'type'} eq 'min') {
1779 $scalefactor = _min($xpix,$ypix);
1781 elsif ($opts{'type'} eq 'max') {
1782 $scalefactor = _max($xpix,$ypix);
1785 $self->_set_error('invalid value for type parameter');
1788 } elsif ($opts{xpixels}) {
1789 $scalefactor = $opts{xpixels} / $self->getwidth();
1791 elsif ($opts{ypixels}) {
1792 $scalefactor = $opts{ypixels}/$self->getheight();
1794 elsif ($opts{constrain} && ref $opts{constrain}
1795 && $opts{constrain}->can('constrain')) {
1796 # we've been passed an Image::Math::Constrain object or something
1797 # that looks like one
1798 (undef, undef, $scalefactor)
1799 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
1800 unless ($scalefactor) {
1801 $self->_set_error('constrain method failed on constrain parameter');
1806 if ($opts{qtype} eq 'normal') {
1807 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
1808 if ( !defined($tmp->{IMG}) ) {
1809 $self->{ERRSTR} = 'unable to scale image';
1812 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $scalefactor, 1);
1813 if ( !defined($img->{IMG}) ) {
1814 $self->{ERRSTR}='unable to scale image';
1820 elsif ($opts{'qtype'} eq 'preview') {
1821 $img->{IMG} = i_scale_nn($self->{IMG}, $scalefactor, $scalefactor);
1822 if ( !defined($img->{IMG}) ) {
1823 $self->{ERRSTR}='unable to scale image';
1829 $self->_set_error('invalid value for qtype parameter');
1834 # Scales only along the X axis
1838 my %opts = ( scalefactor=>0.5, @_ );
1840 unless (defined wantarray) {
1841 my @caller = caller;
1842 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1846 unless ($self->{IMG}) {
1847 $self->{ERRSTR} = 'empty input image';
1851 my $img = Imager->new();
1853 my $scalefactor = $opts{scalefactor};
1855 if ($opts{pixels}) {
1856 $scalefactor = $opts{pixels} / $self->getwidth();
1859 unless ($self->{IMG}) {
1860 $self->{ERRSTR}='empty input image';
1864 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
1866 if ( !defined($img->{IMG}) ) {
1867 $self->{ERRSTR} = 'unable to scale image';
1874 # Scales only along the Y axis
1878 my %opts = ( scalefactor => 0.5, @_ );
1880 unless (defined wantarray) {
1881 my @caller = caller;
1882 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1886 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1888 my $img = Imager->new();
1890 my $scalefactor = $opts{scalefactor};
1892 if ($opts{pixels}) {
1893 $scalefactor = $opts{pixels} / $self->getheight();
1896 unless ($self->{IMG}) {
1897 $self->{ERRSTR} = 'empty input image';
1900 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
1902 if ( !defined($img->{IMG}) ) {
1903 $self->{ERRSTR} = 'unable to scale image';
1910 # Transform returns a spatial transformation of the input image
1911 # this moves pixels to a new location in the returned image.
1912 # NOTE - should make a utility function to check transforms for
1917 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1919 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1921 # print Dumper(\%opts);
1924 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1926 eval ("use Affix::Infix2Postfix;");
1929 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1932 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1933 {op=>'-',trans=>'Sub'},
1934 {op=>'*',trans=>'Mult'},
1935 {op=>'/',trans=>'Div'},
1936 {op=>'-','type'=>'unary',trans=>'u-'},
1938 {op=>'func','type'=>'unary'}],
1939 'grouping'=>[qw( \( \) )],
1940 'func'=>[qw( sin cos )],
1945 @xt=$I2P->translate($opts{'xexpr'});
1946 @yt=$I2P->translate($opts{'yexpr'});
1948 $numre=$I2P->{'numre'};
1951 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1952 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1953 @{$opts{'parm'}}=@pt;
1956 # print Dumper(\%opts);
1958 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1959 $self->{ERRSTR}='transform: no xopcodes given.';
1963 @op=@{$opts{'xopcodes'}};
1965 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1966 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1969 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1975 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1976 $self->{ERRSTR}='transform: no yopcodes given.';
1980 @op=@{$opts{'yopcodes'}};
1982 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1983 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1986 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1991 if ( !exists $opts{'parm'}) {
1992 $self->{ERRSTR}='transform: no parameter arg given.';
1996 # print Dumper(\@ropx);
1997 # print Dumper(\@ropy);
1998 # print Dumper(\@ropy);
2000 my $img = Imager->new();
2001 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2002 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2008 my ($opts, @imgs) = @_;
2010 require "Imager/Expr.pm";
2012 $opts->{variables} = [ qw(x y) ];
2013 my ($width, $height) = @{$opts}{qw(width height)};
2015 $width ||= $imgs[0]->getwidth();
2016 $height ||= $imgs[0]->getheight();
2018 for my $img (@imgs) {
2019 $opts->{constants}{"w$img_num"} = $img->getwidth();
2020 $opts->{constants}{"h$img_num"} = $img->getheight();
2021 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2022 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2027 $opts->{constants}{w} = $width;
2028 $opts->{constants}{cx} = $width/2;
2031 $Imager::ERRSTR = "No width supplied";
2035 $opts->{constants}{h} = $height;
2036 $opts->{constants}{cy} = $height/2;
2039 $Imager::ERRSTR = "No height supplied";
2042 my $code = Imager::Expr->new($opts);
2044 $Imager::ERRSTR = Imager::Expr::error();
2047 my $channels = $opts->{channels} || 3;
2048 unless ($channels >= 1 && $channels <= 4) {
2049 return Imager->_set_error("channels must be an integer between 1 and 4");
2052 my $img = Imager->new();
2053 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2054 $channels, $code->code(),
2055 $code->nregs(), $code->cregs(),
2056 [ map { $_->{IMG} } @imgs ]);
2057 if (!defined $img->{IMG}) {
2058 $Imager::ERRSTR = Imager->_error_as_msg();
2067 my %opts=(tx => 0,ty => 0, @_);
2069 unless ($self->{IMG}) {
2070 $self->{ERRSTR}='empty input image';
2073 unless ($opts{src} && $opts{src}->{IMG}) {
2074 $self->{ERRSTR}='empty input image for src';
2078 %opts = (src_minx => 0,
2080 src_maxx => $opts{src}->getwidth(),
2081 src_maxy => $opts{src}->getheight(),
2084 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
2085 $opts{src_minx}, $opts{src_miny},
2086 $opts{src_maxx}, $opts{src_maxy})) {
2087 $self->_set_error($self->_error_as_msg());
2097 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2099 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2100 $dir = $xlate{$opts{'dir'}};
2101 return $self if i_flipxy($self->{IMG}, $dir);
2109 unless (defined wantarray) {
2110 my @caller = caller;
2111 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2115 if (defined $opts{right}) {
2116 my $degrees = $opts{right};
2118 $degrees += 360 * int(((-$degrees)+360)/360);
2120 $degrees = $degrees % 360;
2121 if ($degrees == 0) {
2122 return $self->copy();
2124 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2125 my $result = Imager->new();
2126 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2130 $self->{ERRSTR} = $self->_error_as_msg();
2135 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2139 elsif (defined $opts{radians} || defined $opts{degrees}) {
2140 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2142 my $back = $opts{back};
2143 my $result = Imager->new;
2145 $back = _color($back);
2147 $self->_set_error(Imager->errstr);
2151 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2154 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2156 if ($result->{IMG}) {
2160 $self->{ERRSTR} = $self->_error_as_msg();
2165 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2170 sub matrix_transform {
2174 unless (defined wantarray) {
2175 my @caller = caller;
2176 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2180 if ($opts{matrix}) {
2181 my $xsize = $opts{xsize} || $self->getwidth;
2182 my $ysize = $opts{ysize} || $self->getheight;
2184 my $result = Imager->new;
2186 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2187 $opts{matrix}, $opts{back})
2191 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2199 $self->{ERRSTR} = "matrix parameter required";
2205 *yatf = \&matrix_transform;
2207 # These two are supported for legacy code only
2210 return Imager::Color->new(@_);
2214 return Imager::Color::set(@_);
2217 # Draws a box between the specified corner points.
2220 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2221 my $dflcl=i_color_new(255,255,255,255);
2222 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2224 if (exists $opts{'box'}) {
2225 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2226 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2227 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2228 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2231 if ($opts{filled}) {
2232 my $color = _color($opts{'color'});
2234 $self->{ERRSTR} = $Imager::ERRSTR;
2237 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2238 $opts{ymax}, $color);
2240 elsif ($opts{fill}) {
2241 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2242 # assume it's a hash ref
2243 require 'Imager/Fill.pm';
2244 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2245 $self->{ERRSTR} = $Imager::ERRSTR;
2249 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2250 $opts{ymax},$opts{fill}{fill});
2253 my $color = _color($opts{'color'});
2255 $self->{ERRSTR} = $Imager::ERRSTR;
2258 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2266 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2267 my $dflcl=i_color_new(255,255,255,255);
2268 my %opts=(color=>$dflcl,
2269 'r'=>_min($self->getwidth(),$self->getheight())/3,
2270 'x'=>$self->getwidth()/2,
2271 'y'=>$self->getheight()/2,
2272 'd1'=>0, 'd2'=>361, @_);
2275 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2276 # assume it's a hash ref
2277 require 'Imager/Fill.pm';
2278 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2279 $self->{ERRSTR} = $Imager::ERRSTR;
2283 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2284 $opts{'d2'}, $opts{fill}{fill});
2287 my $color = _color($opts{'color'});
2289 $self->{ERRSTR} = $Imager::ERRSTR;
2292 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2293 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2297 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2298 $opts{'d1'}, $opts{'d2'}, $color);
2304 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2305 # assume it's a hash ref
2306 require 'Imager/Fill.pm';
2307 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2308 $self->{ERRSTR} = $Imager::ERRSTR;
2312 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2313 $opts{'d2'}, $opts{fill}{fill});
2316 my $color = _color($opts{'color'});
2318 $self->{ERRSTR} = $Imager::ERRSTR;
2321 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2322 $opts{'d1'}, $opts{'d2'}, $color);
2329 # Draws a line from one point to the other
2330 # the endpoint is set if the endp parameter is set which it is by default.
2331 # to turn of the endpoint being set use endp=>0 when calling line.
2335 my $dflcl=i_color_new(0,0,0,0);
2336 my %opts=(color=>$dflcl,
2339 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2341 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2342 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2344 my $color = _color($opts{'color'});
2346 $self->{ERRSTR} = $Imager::ERRSTR;
2350 $opts{antialias} = $opts{aa} if defined $opts{aa};
2351 if ($opts{antialias}) {
2352 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2353 $color, $opts{endp});
2355 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2356 $color, $opts{endp});
2361 # Draws a line between an ordered set of points - It more or less just transforms this
2362 # into a list of lines.
2366 my ($pt,$ls,@points);
2367 my $dflcl=i_color_new(0,0,0,0);
2368 my %opts=(color=>$dflcl,@_);
2370 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2372 if (exists($opts{points})) { @points=@{$opts{points}}; }
2373 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2374 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2377 # print Dumper(\@points);
2379 my $color = _color($opts{'color'});
2381 $self->{ERRSTR} = $Imager::ERRSTR;
2384 $opts{antialias} = $opts{aa} if defined $opts{aa};
2385 if ($opts{antialias}) {
2388 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2395 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2405 my ($pt,$ls,@points);
2406 my $dflcl = i_color_new(0,0,0,0);
2407 my %opts = (color=>$dflcl, @_);
2409 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2411 if (exists($opts{points})) {
2412 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2413 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2416 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2417 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2420 if ($opts{'fill'}) {
2421 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2422 # assume it's a hash ref
2423 require 'Imager/Fill.pm';
2424 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2425 $self->{ERRSTR} = $Imager::ERRSTR;
2429 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2430 $opts{'fill'}{'fill'});
2433 my $color = _color($opts{'color'});
2435 $self->{ERRSTR} = $Imager::ERRSTR;
2438 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2445 # this the multipoint bezier curve
2446 # this is here more for testing that actual usage since
2447 # this is not a good algorithm. Usually the curve would be
2448 # broken into smaller segments and each done individually.
2452 my ($pt,$ls,@points);
2453 my $dflcl=i_color_new(0,0,0,0);
2454 my %opts=(color=>$dflcl,@_);
2456 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2458 if (exists $opts{points}) {
2459 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2460 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2463 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2464 $self->{ERRSTR}='Missing or invalid points.';
2468 my $color = _color($opts{'color'});
2470 $self->{ERRSTR} = $Imager::ERRSTR;
2473 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2479 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2482 unless (exists $opts{'x'} && exists $opts{'y'}) {
2483 $self->{ERRSTR} = "missing seed x and y parameters";
2488 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2489 # assume it's a hash ref
2490 require 'Imager/Fill.pm';
2491 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2492 $self->{ERRSTR} = $Imager::ERRSTR;
2496 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2499 my $color = _color($opts{'color'});
2501 $self->{ERRSTR} = $Imager::ERRSTR;
2504 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2506 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2512 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2514 unless (exists $opts{'x'} && exists $opts{'y'}) {
2515 $self->{ERRSTR} = 'missing x and y parameters';
2521 my $color = _color($opts{color})
2523 if (ref $x && ref $y) {
2524 unless (@$x == @$y) {
2525 $self->{ERRSTR} = 'length of x and y mismatch';
2528 if ($color->isa('Imager::Color')) {
2529 for my $i (0..$#{$opts{'x'}}) {
2530 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2534 for my $i (0..$#{$opts{'x'}}) {
2535 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2540 if ($color->isa('Imager::Color')) {
2541 i_ppix($self->{IMG}, $x, $y, $color);
2544 i_ppixf($self->{IMG}, $x, $y, $color);
2554 my %opts = ( "type"=>'8bit', @_);
2556 unless (exists $opts{'x'} && exists $opts{'y'}) {
2557 $self->{ERRSTR} = 'missing x and y parameters';
2563 if (ref $x && ref $y) {
2564 unless (@$x == @$y) {
2565 $self->{ERRSTR} = 'length of x and y mismatch';
2569 if ($opts{"type"} eq '8bit') {
2570 for my $i (0..$#{$opts{'x'}}) {
2571 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2575 for my $i (0..$#{$opts{'x'}}) {
2576 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2579 return wantarray ? @result : \@result;
2582 if ($opts{"type"} eq '8bit') {
2583 return i_get_pixel($self->{IMG}, $x, $y);
2586 return i_gpixf($self->{IMG}, $x, $y);
2595 my %opts = ( type => '8bit', x=>0, @_);
2597 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2599 unless (defined $opts{'y'}) {
2600 $self->_set_error("missing y parameter");
2604 if ($opts{type} eq '8bit') {
2605 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2608 elsif ($opts{type} eq 'float') {
2609 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2613 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2620 my %opts = ( x=>0, @_);
2622 unless (defined $opts{'y'}) {
2623 $self->_set_error("missing y parameter");
2628 if (ref $opts{pixels} && @{$opts{pixels}}) {
2629 # try to guess the type
2630 if ($opts{pixels}[0]->isa('Imager::Color')) {
2631 $opts{type} = '8bit';
2633 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2634 $opts{type} = 'float';
2637 $self->_set_error("missing type parameter and could not guess from pixels");
2643 $opts{type} = '8bit';
2647 if ($opts{type} eq '8bit') {
2648 if (ref $opts{pixels}) {
2649 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2652 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2655 elsif ($opts{type} eq 'float') {
2656 if (ref $opts{pixels}) {
2657 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2660 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2664 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2671 my %opts = ( type => '8bit', x=>0, @_);
2673 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2675 unless (defined $opts{'y'}) {
2676 $self->_set_error("missing y parameter");
2680 unless ($opts{channels}) {
2681 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2684 if ($opts{type} eq '8bit') {
2685 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2686 $opts{y}, @{$opts{channels}});
2688 elsif ($opts{type} eq 'float') {
2689 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2690 $opts{y}, @{$opts{channels}});
2693 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2698 # make an identity matrix of the given size
2702 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2703 for my $c (0 .. ($size-1)) {
2704 $matrix->[$c][$c] = 1;
2709 # general function to convert an image
2711 my ($self, %opts) = @_;
2714 unless (defined wantarray) {
2715 my @caller = caller;
2716 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2720 # the user can either specify a matrix or preset
2721 # the matrix overrides the preset
2722 if (!exists($opts{matrix})) {
2723 unless (exists($opts{preset})) {
2724 $self->{ERRSTR} = "convert() needs a matrix or preset";
2728 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2729 # convert to greyscale, keeping the alpha channel if any
2730 if ($self->getchannels == 3) {
2731 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2733 elsif ($self->getchannels == 4) {
2734 # preserve the alpha channel
2735 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2740 $matrix = _identity($self->getchannels);
2743 elsif ($opts{preset} eq 'noalpha') {
2744 # strip the alpha channel
2745 if ($self->getchannels == 2 or $self->getchannels == 4) {
2746 $matrix = _identity($self->getchannels);
2747 pop(@$matrix); # lose the alpha entry
2750 $matrix = _identity($self->getchannels);
2753 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2755 $matrix = [ [ 1 ] ];
2757 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2758 $matrix = [ [ 0, 1 ] ];
2760 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2761 $matrix = [ [ 0, 0, 1 ] ];
2763 elsif ($opts{preset} eq 'alpha') {
2764 if ($self->getchannels == 2 or $self->getchannels == 4) {
2765 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2768 # the alpha is just 1 <shrug>
2769 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2772 elsif ($opts{preset} eq 'rgb') {
2773 if ($self->getchannels == 1) {
2774 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2776 elsif ($self->getchannels == 2) {
2777 # preserve the alpha channel
2778 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2781 $matrix = _identity($self->getchannels);
2784 elsif ($opts{preset} eq 'addalpha') {
2785 if ($self->getchannels == 1) {
2786 $matrix = _identity(2);
2788 elsif ($self->getchannels == 3) {
2789 $matrix = _identity(4);
2792 $matrix = _identity($self->getchannels);
2796 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2802 $matrix = $opts{matrix};
2805 my $new = Imager->new();
2806 $new->{IMG} = i_img_new();
2807 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2808 # most likely a bad matrix
2809 $self->{ERRSTR} = _error_as_msg();
2816 # general function to map an image through lookup tables
2819 my ($self, %opts) = @_;
2820 my @chlist = qw( red green blue alpha );
2822 if (!exists($opts{'maps'})) {
2823 # make maps from channel maps
2825 for $chnum (0..$#chlist) {
2826 if (exists $opts{$chlist[$chnum]}) {
2827 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2828 } elsif (exists $opts{'all'}) {
2829 $opts{'maps'}[$chnum] = $opts{'all'};
2833 if ($opts{'maps'} and $self->{IMG}) {
2834 i_map($self->{IMG}, $opts{'maps'} );
2840 my ($self, %opts) = @_;
2842 defined $opts{mindist} or $opts{mindist} = 0;
2844 defined $opts{other}
2845 or return $self->_set_error("No 'other' parameter supplied");
2846 defined $opts{other}{IMG}
2847 or return $self->_set_error("No image data in 'other' image");
2850 or return $self->_set_error("No image data");
2852 my $result = Imager->new;
2853 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2855 or return $self->_set_error($self->_error_as_msg());
2860 # destructive border - image is shrunk by one pixel all around
2863 my ($self,%opts)=@_;
2864 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2865 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2869 # Get the width of an image
2873 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2874 return (i_img_info($self->{IMG}))[0];
2877 # Get the height of an image
2881 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2882 return (i_img_info($self->{IMG}))[1];
2885 # Get number of channels in an image
2889 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2890 return i_img_getchannels($self->{IMG});
2897 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2898 return i_img_getmask($self->{IMG});
2906 if (!defined($self->{IMG})) {
2907 $self->{ERRSTR} = 'image is empty';
2910 unless (defined $opts{mask}) {
2911 $self->_set_error("mask parameter required");
2914 i_img_setmask( $self->{IMG} , $opts{mask} );
2919 # Get number of colors in an image
2923 my %opts=('maxcolors'=>2**30,@_);
2924 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2925 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2926 return ($rc==-1? undef : $rc);
2929 # draw string to an image
2933 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2935 my %input=('x'=>0, 'y'=>0, @_);
2936 $input{string}||=$input{text};
2938 unless(defined $input{string}) {
2939 $self->{ERRSTR}="missing required parameter 'string'";
2943 unless($input{font}) {
2944 $self->{ERRSTR}="missing required parameter 'font'";
2948 unless ($input{font}->draw(image=>$self, %input)) {
2960 unless ($self->{IMG}) {
2961 $self->{ERRSTR}='empty input image';
2970 my %input=('x'=>0, 'y'=>0, @_);
2971 $input{string}||=$input{text};
2973 unless(exists $input{string}) {
2974 $self->_set_error("missing required parameter 'string'");
2978 unless($input{font}) {
2979 $self->_set_error("missing required parameter 'font'");
2984 unless (@result = $input{font}->align(image=>$img, %input)) {
2988 return wantarray ? @result : $result[0];
2991 my @file_limit_names = qw/width height bytes/;
2993 sub set_file_limits {
3000 @values{@file_limit_names} = (0) x @file_limit_names;
3003 @values{@file_limit_names} = i_get_image_file_limits();
3006 for my $key (keys %values) {
3007 defined $opts{$key} and $values{$key} = $opts{$key};
3010 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3013 sub get_file_limits {
3014 i_get_image_file_limits();
3017 # Shortcuts that can be exported
3019 sub newcolor { Imager::Color->new(@_); }
3020 sub newfont { Imager::Font->new(@_); }
3022 *NC=*newcolour=*newcolor;
3029 #### Utility routines
3032 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3036 my ($self, $msg) = @_;
3039 $self->{ERRSTR} = $msg;
3047 # Default guess for the type of an image from extension
3049 sub def_guess_type {
3052 $ext=($name =~ m/\.([^\.]+)$/)[0];
3053 return 'tiff' if ($ext =~ m/^tiff?$/);
3054 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3055 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3056 return 'png' if ($ext eq "png");
3057 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3058 return 'tga' if ($ext eq "tga");
3059 return 'rgb' if ($ext eq "rgb");
3060 return 'gif' if ($ext eq "gif");
3061 return 'raw' if ($ext eq "raw");
3065 # get the minimum of a list
3069 for(@_) { if ($_<$mx) { $mx=$_; }}
3073 # get the maximum of a list
3077 for(@_) { if ($_>$mx) { $mx=$_; }}
3081 # string stuff for iptc headers
3085 $str = substr($str,3);
3086 $str =~ s/[\n\r]//g;
3093 # A little hack to parse iptc headers.
3098 my($caption,$photogr,$headln,$credit);
3100 my $str=$self->{IPTCRAW};
3105 @ar=split(/8BIM/,$str);
3110 @sar=split(/\034\002/);
3111 foreach $item (@sar) {
3112 if ($item =~ m/^x/) {
3113 $caption = _clean($item);
3116 if ($item =~ m/^P/) {
3117 $photogr = _clean($item);
3120 if ($item =~ m/^i/) {
3121 $headln = _clean($item);
3124 if ($item =~ m/^n/) {
3125 $credit = _clean($item);
3131 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3138 or die "Only C language supported";
3140 require Imager::ExtUtils;
3141 return Imager::ExtUtils->inline_config;
3146 # Below is the stub of documentation for your module. You better edit it!
3150 Imager - Perl extension for Generating 24 bit Images
3160 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3165 my $img = Imager->new();
3166 # see Imager::Files for information on the read() method
3167 $img->read(file=>$file) or die $img->errstr();
3169 $file =~ s/\.[^.]*$//;
3171 # Create smaller version
3172 # documented in Imager::Transformations
3173 my $thumb = $img->scale(scalefactor=>.3);
3175 # Autostretch individual channels
3176 $thumb->filter(type=>'autolevels');
3178 # try to save in one of these formats
3181 for $format ( qw( png gif jpg tiff ppm ) ) {
3182 # Check if given format is supported
3183 if ($Imager::formats{$format}) {
3184 $file.="_low.$format";
3185 print "Storing image as: $file\n";
3186 # documented in Imager::Files
3187 $thumb->write(file=>$file) or
3195 Imager is a module for creating and altering images. It can read and
3196 write various image formats, draw primitive shapes like lines,and
3197 polygons, blend multiple images together in various ways, scale, crop,
3198 render text and more.
3200 =head2 Overview of documentation
3206 Imager - This document - Synopsis Example, Table of Contents and
3211 L<Imager::Tutorial> - a brief introduction to Imager.
3215 L<Imager::Cookbook> - how to do various things with Imager.
3219 L<Imager::ImageTypes> - Basics of constructing image objects with
3220 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3221 8/16/double bits/channel, color maps, channel masks, image tags, color
3222 quantization. Also discusses basic image information methods.
3226 L<Imager::Files> - IO interaction, reading/writing images, format
3231 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3236 L<Imager::Color> - Color specification.
3240 L<Imager::Fill> - Fill pattern specification.
3244 L<Imager::Font> - General font rendering, bounding boxes and font
3249 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3250 blending, pasting, convert and map.
3254 L<Imager::Engines> - Programmable transformations through
3255 C<transform()>, C<transform2()> and C<matrix_transform()>.
3259 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3264 L<Imager::Expr> - Expressions for evaluation engine used by
3269 L<Imager::Matrix2d> - Helper class for affine transformations.
3273 L<Imager::Fountain> - Helper for making gradient profiles.
3277 L<Imager::API> - using Imager's C API
3281 L<Imager::APIRef> - API function reference
3285 L<Imager::Inline> - using Imager's C API from Inline::C
3289 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3293 =head2 Basic Overview
3295 An Image object is created with C<$img = Imager-E<gt>new()>.
3298 $img=Imager->new(); # create empty image
3299 $img->read(file=>'lena.png',type=>'png') or # read image from file
3300 die $img->errstr(); # give an explanation
3301 # if something failed
3303 or if you want to create an empty image:
3305 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3307 This example creates a completely black image of width 400 and height
3310 When an operation fails which can be directly associated with an image
3311 the error message is stored can be retrieved with
3312 C<$img-E<gt>errstr()>.
3314 In cases where no image object is associated with an operation
3315 C<$Imager::ERRSTR> is used to report errors not directly associated
3316 with an image object. You can also call C<Imager->errstr> to get this
3319 The C<Imager-E<gt>new> method is described in detail in
3320 L<Imager::ImageTypes>.
3324 Where to find information on methods for Imager class objects.
3326 addcolors() - L<Imager::ImageTypes/addcolors>
3328 addtag() - L<Imager::ImageTypes/addtag> - add image tags
3330 arc() - L<Imager::Draw/arc>
3332 align_string() - L<Imager::Draw/align_string>
3334 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
3337 box() - L<Imager::Draw/box>
3339 circle() - L<Imager::Draw/circle>
3341 colorcount() - L<Imager::Draw/colorcount>
3343 convert() - L<Imager::Transformations/"Color transformations"> -
3344 transform the color space
3346 copy() - L<Imager::Transformations/copy>
3348 crop() - L<Imager::Transformations/crop> - extract part of an image
3350 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
3352 difference() - L<Imager::Filters/"Image Difference">
3354 errstr() - L<"Basic Overview">
3356 filter() - L<Imager::Filters>
3358 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
3361 flip() - L<Imager::Transformations/flip>
3363 flood_fill() - L<Imager::Draw/flood_fill>
3365 getchannels() - L<Imager::ImageTypes/getchannels>
3367 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
3369 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
3370 palette, if it has one
3372 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3374 getheight() - L<Imager::ImageTypes/getwidth>
3376 getpixel() - L<Imager::Draw/getpixel>
3378 getsamples() - L<Imager::Draw/getsamples>
3380 getscanline() - L<Imager::Draw/getscanline>
3382 getwidth() - L<Imager::ImageTypes/getwidth>
3384 img_set() - L<Imager::ImageTypes/img_set>
3386 line() - L<Imager::Draw/line>
3388 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3391 masked() - L<Imager::ImageTypes/masked> - make a masked image
3393 matrix_transform() - L<Imager::Engines/matrix_transform>
3395 maxcolors() - L<Imager::ImageTypes/maxcolors>
3397 new() - L<Imager::ImageTypes/new>
3399 open() - L<Imager::Files> - an alias for read()
3401 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3403 polygon() - L<Imager::Draw/polygon>
3405 polyline() - L<Imager::Draw/polyline>
3407 read() - L<Imager::Files> - read a single image from an image file
3409 read_multi() - L<Imager::Files> - read multiple images from an image
3412 rotate() - L<Imager::Transformations/rotate>
3414 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3415 image and use the alpha channel
3417 scale() - L<Imager::Transformations/scale>
3419 scaleX() - L<Imager::Transformations/scaleX>
3421 scaleY() - L<Imager::Transformations/scaleY>
3423 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
3426 setpixel() - L<Imager::Draw/setpixel>
3428 setscanline() - L<Imager::Draw/setscanline>
3430 settag() - L<Imager::ImageTypes/settag>
3432 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3434 string() - L<Imager::Draw/string> - draw text on an image
3436 tags() - L<Imager::ImageTypes/tags> - fetch image tags
3438 to_paletted() - L<Imager::ImageTypes/to_paletted>
3440 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
3442 transform() - L<Imager::Engines/"transform">
3444 transform2() - L<Imager::Engines/"transform2">
3446 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
3448 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
3451 write() - L<Imager::Files> - write an image to a file
3453 write_multi() - L<Imager::Files> - write multiple image to an image
3456 =head1 CONCEPT INDEX
3458 animated GIF - L<Imager::File/"Writing an animated GIF">
3460 aspect ratio - L<Imager::ImageTypes/i_xres>,
3461 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3463 blend - alpha blending one image onto another
3464 L<Imager::Transformations/rubthrough>
3466 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3468 boxes, drawing - L<Imager::Draw/box>
3470 changes between image - L<Imager::Filter/"Image Difference">
3472 color - L<Imager::Color>
3474 color names - L<Imager::Color>, L<Imager::Color::Table>
3476 combine modes - L<Imager::Fill/combine>
3478 compare images - L<Imager::Filter/"Image Difference">
3480 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3482 convolution - L<Imager::Filter/conv>
3484 cropping - L<Imager::Transformations/crop>
3486 C<diff> images - L<Imager::Filter/"Image Difference">
3488 dpi - L<Imager::ImageTypes/i_xres>
3490 drawing boxes - L<Imager::Draw/box>
3492 drawing lines - L<Imager::Draw/line>
3494 drawing text - L<Imager::Font/string>, L<Imager::Font/align>
3496 error message - L<"Basic Overview">
3498 files, font - L<Imager::Font>
3500 files, image - L<Imager::Files>
3502 filling, types of fill - L<Imager::Fill>
3504 filling, boxes - L<Imager::Draw/box>
3506 filling, flood fill - L<Imager::Draw/flood_fill>
3508 flood fill - L<Imager::Draw/flood_fill>
3510 fonts - L<Imager::Font>
3512 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3513 L<Imager::Font::Wrap>
3515 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3517 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3519 fountain fill - L<Imager::Fill/"Fountain fills">,
3520 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3521 L<Imager::Filters/gradgen>
3523 GIF files - L<Imager::Files/"GIF">
3525 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3527 gradient fill - L<Imager::Fill/"Fountain fills">,
3528 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3529 L<Imager::Filters/gradgen>
3531 guassian blur - L<Imager::Filter/guassian>
3533 hatch fills - L<Imager::Fill/"Hatched fills">
3535 invert image - L<Imager::Filter/hardinvert>
3537 JPEG - L<Imager::Files/"JPEG">
3539 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3541 lines, drawing - L<Imager::Draw/line>
3543 matrix - L<Imager::Matrix2d>,
3544 L<Imager::Transformations/"Matrix Transformations">,
3545 L<Imager::Font/transform>
3547 metadata, image - L<Imager::ImageTypes/"Tags">
3549 mosaic - L<Imager::Filter/mosaic>
3551 noise, filter - L<Imager::Filter/noise>
3553 noise, rendered - L<Imager::Filter/turbnoise>,
3554 L<Imager::Filter/radnoise>
3556 paste - L<Imager::Transformations/paste>,
3557 L<Imager::Transformations/rubthrough>
3559 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
3560 L<Imager::ImageTypes/new>
3562 posterize - L<Imager::Filter/postlevels>
3564 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3566 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3568 rectangles, drawing - L<Imager::Draw/box>
3570 resizing an image - L<Imager::Transformations/scale>,
3571 L<Imager::Transformations/crop>
3573 saving an image - L<Imager::Files>
3575 scaling - L<Imager::Transformations/scale>
3577 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3579 size, image - L<Imager::ImageTypes/getwidth>,
3580 L<Imager::ImageTypes/getheight>
3582 size, text - L<Imager::Font/bounding_box>
3584 tags, image metadata - L<Imager::ImageTypes/"Tags">
3586 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
3587 L<Imager::Font::Wrap>
3589 text, wrapping text in an area - L<Imager::Font::Wrap>
3591 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3593 tiles, color - L<Imager::Filter/mosaic>
3595 unsharp mask - L<Imager::Filter/unsharpmask>
3597 watermark - L<Imager::Filter/watermark>
3599 writing an image to a file - L<Imager::Files>
3603 The best place to get help with Imager is the mailing list.
3605 To subscribe send a message with C<subscribe> in the body to:
3607 imager-devel+request@molar.is
3613 L<http://www.molar.is/en/lists/imager-devel/>
3617 where you can also find the mailing list archive.
3619 You can report bugs by pointing your browser at:
3623 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
3627 Please remember to include the versions of Imager, perl, supporting
3628 libraries, and any relevant code. If you have specific images that
3629 cause the problems, please include those too.
3633 Bugs are listed individually for relevant pod pages.
3637 Arnar M. Hrafnkelsson and Tony Cook (tony@imager.perl.org) among
3638 others. See the README for a complete list.
3642 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
3643 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
3644 L<Imager::Font>(3), L<Imager::Transformations>(3),
3645 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
3646 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
3648 L<http://imager.perl.org/>
3650 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
3652 Other perl imaging modules include:
3654 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).