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
151 @ISA = qw(Exporter DynaLoader);
152 bootstrap Imager $VERSION;
156 i_init_fonts(); # Initialize font engines
157 Imager::Font::__init();
158 for(i_list_formats()) { $formats{$_}++; }
160 if ($formats{'t1'}) {
164 if (!$formats{'t1'} and !$formats{'tt'}
165 && !$formats{'ft2'} && !$formats{'w32'}) {
166 $fontstate='no font support';
169 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
173 # the members of the subhashes under %filters are:
174 # callseq - a list of the parameters to the underlying filter in the
175 # order they are passed
176 # callsub - a code ref that takes a named parameter list and calls the
178 # defaults - a hash of default values
179 # names - defines names for value of given parameters so if the names
180 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
181 # foo parameter, the filter will receive 1 for the foo
184 callseq => ['image','intensity'],
185 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
189 callseq => ['image', 'amount', 'subtype'],
190 defaults => { amount=>3,subtype=>0 },
191 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
194 $filters{hardinvert} ={
195 callseq => ['image'],
197 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
200 $filters{autolevels} ={
201 callseq => ['image','lsat','usat','skew'],
202 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
203 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
206 $filters{turbnoise} ={
207 callseq => ['image'],
208 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
209 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
212 $filters{radnoise} ={
213 callseq => ['image'],
214 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
215 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
219 callseq => ['image', 'coef'],
221 callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
226 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
227 defaults => { dist => 0 },
231 my @colors = @{$hsh{colors}};
234 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
238 $filters{nearest_color} ={
239 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
241 callsub => sub { my %hsh=@_; i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, $hsh{colors}, $hsh{dist}); }
243 $filters{gaussian} = {
244 callseq => [ 'image', 'stddev' ],
246 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
250 callseq => [ qw(image size) ],
251 defaults => { size => 20 },
252 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
256 callseq => [ qw(image bump elevation lightx lighty st) ],
257 defaults => { elevation=>0, st=> 2 },
260 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
261 $hsh{lightx}, $hsh{lighty}, $hsh{st});
264 $filters{bumpmap_complex} =
266 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
277 Ia => Imager::Color->new(rgb=>[0,0,0]),
278 Il => Imager::Color->new(rgb=>[255,255,255]),
279 Is => Imager::Color->new(rgb=>[255,255,255]),
283 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
284 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
285 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
289 $filters{postlevels} =
291 callseq => [ qw(image levels) ],
292 defaults => { levels => 10 },
293 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
295 $filters{watermark} =
297 callseq => [ qw(image wmark tx ty pixdiff) ],
298 defaults => { pixdiff=>10, tx=>0, ty=>0 },
302 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
308 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
310 ftype => { linear => 0,
316 repeat => { none => 0,
331 multiply => 2, mult => 2,
334 subtract => 5, 'sub' => 5,
344 defaults => { ftype => 0, repeat => 0, combine => 0,
345 super_sample => 0, ssample_param => 4,
348 Imager::Color->new(0,0,0),
349 Imager::Color->new(255, 255, 255),
358 # make sure the segments are specified with colors
360 for my $segment (@{$hsh{segments}}) {
361 my @new_segment = @$segment;
363 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
364 push @segments, \@new_segment;
367 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
368 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
369 $hsh{ssample_param}, \@segments);
372 $filters{unsharpmask} =
374 callseq => [ qw(image stddev scale) ],
375 defaults => { stddev=>2.0, scale=>1.0 },
379 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
383 $FORMATGUESS=\&def_guess_type;
393 # NOTE: this might be moved to an import override later on
397 # (look through @_ for special tags, process, and remove them);
399 # print Dumper($pack);
404 m_init_log($_[0],$_[1]);
405 log_entry("Imager $VERSION starting\n", 1);
410 my %parms=(loglevel=>1,@_);
412 init_log($parms{'log'},$parms{'loglevel'});
415 if (exists $parms{'warn_obsolete'}) {
416 $warn_obsolete = $parms{'warn_obsolete'};
419 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
420 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
424 if (exists $parms{'t1log'}) {
425 i_init_fonts($parms{'t1log'});
431 print "shutdown code\n";
432 # for(keys %instances) { $instances{$_}->DESTROY(); }
433 malloc_state(); # how do decide if this should be used? -- store something from the import
434 print "Imager exiting\n";
438 # Load a filter plugin
443 my ($DSO_handle,$str)=DSO_open($filename);
444 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
445 my %funcs=DSO_funclist($DSO_handle);
446 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
448 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
450 $DSOs{$filename}=[$DSO_handle,\%funcs];
453 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
454 $DEBUG && print "eval string:\n",$evstr,"\n";
466 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
467 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
468 for(keys %{$funcref}) {
470 $DEBUG && print "unloading: $_\n";
472 my $rc=DSO_close($DSO_handle);
473 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
477 # take the results of i_error() and make a message out of it
479 return join(": ", map $_->[0], i_errors());
482 # this function tries to DWIM for color parameters
483 # color objects are used as is
484 # simple scalars are simply treated as single parameters to Imager::Color->new
485 # hashrefs are treated as named argument lists to Imager::Color->new
486 # arrayrefs are treated as list arguments to Imager::Color->new iff any
488 # other arrayrefs are treated as list arguments to Imager::Color::Float
492 # perl 5.6.0 seems to do weird things to $arg if we don't make an
493 # explicitly stringified copy
494 # I vaguely remember a bug on this on p5p, but couldn't find it
495 # through bugs.perl.org (I had trouble getting it to find any bugs)
496 my $copy = $arg . "";
500 if (UNIVERSAL::isa($arg, "Imager::Color")
501 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
505 if ($copy =~ /^HASH\(/) {
506 $result = Imager::Color->new(%$arg);
508 elsif ($copy =~ /^ARRAY\(/) {
509 if (grep $_ > 1, @$arg) {
510 $result = Imager::Color->new(@$arg);
513 $result = Imager::Color::Float->new(@$arg);
517 $Imager::ERRSTR = "Not a color";
522 # assume Imager::Color::new knows how to handle it
523 $result = Imager::Color->new($arg);
531 # Methods to be called on objects.
534 # Create a new Imager object takes very few parameters.
535 # usually you call this method and then call open from
536 # the resulting object
543 $self->{IMG}=undef; # Just to indicate what exists
544 $self->{ERRSTR}=undef; #
545 $self->{DEBUG}=$DEBUG;
546 $self->{DEBUG} && print "Initialized Imager\n";
547 if (defined $hsh{xsize} && defined $hsh{ysize}) {
548 unless ($self->img_set(%hsh)) {
549 $Imager::ERRSTR = $self->{ERRSTR};
556 # Copy an entire image with no changes
557 # - if an image has magic the copy of it will not be magical
561 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
563 unless (defined wantarray) {
565 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
569 my $newcopy=Imager->new();
570 $newcopy->{IMG}=i_img_new();
571 i_copy($newcopy->{IMG},$self->{IMG});
579 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
580 my %input=(left=>0, top=>0, @_);
581 unless($input{img}) {
582 $self->{ERRSTR}="no source image";
585 $input{left}=0 if $input{left} <= 0;
586 $input{top}=0 if $input{top} <= 0;
588 my($r,$b)=i_img_info($src->{IMG});
590 i_copyto($self->{IMG}, $src->{IMG},
591 0,0, $r, $b, $input{left}, $input{top});
592 return $self; # What should go here??
595 # Crop an image - i.e. return a new image that is smaller
599 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
601 unless (defined wantarray) {
603 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
609 my ($w, $h, $l, $r, $b, $t) =
610 @hsh{qw(width height left right bottom top)};
612 # work through the various possibilities
617 elsif (!defined $r) {
618 $r = $self->getwidth;
630 $l = int(0.5+($self->getwidth()-$w)/2);
635 $r = $self->getwidth;
641 elsif (!defined $b) {
642 $b = $self->getheight;
654 $t=int(0.5+($self->getheight()-$h)/2);
659 $b = $self->getheight;
662 ($l,$r)=($r,$l) if $l>$r;
663 ($t,$b)=($b,$t) if $t>$b;
666 $r > $self->getwidth and $r = $self->getwidth;
668 $b > $self->getheight and $b = $self->getheight;
670 if ($l == $r || $t == $b) {
671 $self->_set_error("resulting image would have no content");
675 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
677 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
682 my ($self, %opts) = @_;
684 $self->{IMG} or return $self->_set_error("Not a valid image");
686 my $x = $opts{xsize} || $self->getwidth;
687 my $y = $opts{ysize} || $self->getheight;
688 my $channels = $opts{channels} || $self->getchannels;
690 my $out = Imager->new;
691 if ($channels == $self->getchannels) {
692 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
695 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
697 unless ($out->{IMG}) {
698 $self->{ERRSTR} = $self->_error_as_msg;
705 # Sets an image to a certain size and channel number
706 # if there was previously data in the image it is discarded
711 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
713 if (defined($self->{IMG})) {
714 # let IIM_DESTROY destroy it, it's possible this image is
715 # referenced from a virtual image (like masked)
716 #i_img_destroy($self->{IMG});
720 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
721 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
722 $hsh{maxcolors} || 256);
724 elsif ($hsh{bits} eq 'double') {
725 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
727 elsif ($hsh{bits} == 16) {
728 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
731 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
735 unless ($self->{IMG}) {
736 $self->{ERRSTR} = Imager->_error_as_msg();
743 # created a masked version of the current image
747 $self or return undef;
748 my %opts = (left => 0,
750 right => $self->getwidth,
751 bottom => $self->getheight,
753 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
755 my $result = Imager->new;
756 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
757 $opts{top}, $opts{right} - $opts{left},
758 $opts{bottom} - $opts{top});
759 # keep references to the mask and base images so they don't
761 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
766 # convert an RGB image into a paletted image
770 if (@_ != 1 && !ref $_[0]) {
777 unless (defined wantarray) {
779 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
783 my $result = Imager->new;
784 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
786 #print "Type ", i_img_type($result->{IMG}), "\n";
788 if ($result->{IMG}) {
792 $self->{ERRSTR} = $self->_error_as_msg;
797 # convert a paletted (or any image) to an 8-bit/channel RGB images
802 unless (defined wantarray) {
804 warn "to_rgb8() called in void context - to_rgb8() returns the cropped image at $caller[1] line $caller[2]\n";
809 $result = Imager->new;
810 $result->{IMG} = i_img_to_rgb($self->{IMG})
819 my %opts = (colors=>[], @_);
821 @{$opts{colors}} or return undef;
823 $self->{IMG} and i_addcolors($self->{IMG}, @{$opts{colors}});
828 my %opts = (start=>0, colors=>[], @_);
829 @{$opts{colors}} or return undef;
831 $self->{IMG} and i_setcolors($self->{IMG}, $opts{start}, @{$opts{colors}});
837 if (!exists $opts{start} && !exists $opts{count}) {
840 $opts{count} = $self->colorcount;
842 elsif (!exists $opts{count}) {
845 elsif (!exists $opts{start}) {
850 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
854 i_colorcount($_[0]{IMG});
858 i_maxcolors($_[0]{IMG});
864 $opts{color} or return undef;
866 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
871 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
872 if ($bits && $bits == length(pack("d", 1)) * 8) {
881 return i_img_type($self->{IMG}) ? "paletted" : "direct";
887 $self->{IMG} and i_img_virtual($self->{IMG});
891 my ($self, %opts) = @_;
893 $self->{IMG} or return;
895 if (defined $opts{name}) {
899 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
900 push @result, (i_tags_get($self->{IMG}, $found))[1];
903 return wantarray ? @result : $result[0];
905 elsif (defined $opts{code}) {
909 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
910 push @result, (i_tags_get($self->{IMG}, $found))[1];
917 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
920 return i_tags_count($self->{IMG});
929 return -1 unless $self->{IMG};
931 if (defined $opts{value}) {
932 if ($opts{value} =~ /^\d+$/) {
934 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
937 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
940 elsif (defined $opts{data}) {
941 # force addition as a string
942 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
945 $self->{ERRSTR} = "No value supplied";
949 elsif ($opts{code}) {
950 if (defined $opts{value}) {
951 if ($opts{value} =~ /^\d+$/) {
953 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
956 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
959 elsif (defined $opts{data}) {
960 # force addition as a string
961 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
964 $self->{ERRSTR} = "No value supplied";
977 return 0 unless $self->{IMG};
979 if (defined $opts{'index'}) {
980 return i_tags_delete($self->{IMG}, $opts{'index'});
982 elsif (defined $opts{name}) {
983 return i_tags_delbyname($self->{IMG}, $opts{name});
985 elsif (defined $opts{code}) {
986 return i_tags_delbycode($self->{IMG}, $opts{code});
989 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
995 my ($self, %opts) = @_;
998 $self->deltag(name=>$opts{name});
999 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1001 elsif (defined $opts{code}) {
1002 $self->deltag(code=>$opts{code});
1003 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1011 sub _get_reader_io {
1012 my ($self, $input) = @_;
1015 return $input->{io}, undef;
1017 elsif ($input->{fd}) {
1018 return io_new_fd($input->{fd});
1020 elsif ($input->{fh}) {
1021 my $fd = fileno($input->{fh});
1023 $self->_set_error("Handle in fh option not opened");
1026 return io_new_fd($fd);
1028 elsif ($input->{file}) {
1029 my $file = IO::File->new($input->{file}, "r");
1031 $self->_set_error("Could not open $input->{file}: $!");
1035 return (io_new_fd(fileno($file)), $file);
1037 elsif ($input->{data}) {
1038 return io_new_buffer($input->{data});
1040 elsif ($input->{callback} || $input->{readcb}) {
1041 if (!$input->{seekcb}) {
1042 $self->_set_error("Need a seekcb parameter");
1044 if ($input->{maxbuffer}) {
1045 return io_new_cb($input->{writecb},
1046 $input->{callback} || $input->{readcb},
1047 $input->{seekcb}, $input->{closecb},
1048 $input->{maxbuffer});
1051 return io_new_cb($input->{writecb},
1052 $input->{callback} || $input->{readcb},
1053 $input->{seekcb}, $input->{closecb});
1057 $self->_set_error("file/fd/fh/data/callback parameter missing");
1062 sub _get_writer_io {
1063 my ($self, $input, $type) = @_;
1066 return io_new_fd($input->{fd});
1068 elsif ($input->{fh}) {
1069 my $fd = fileno($input->{fh});
1071 $self->_set_error("Handle in fh option not opened");
1075 my $oldfh = select($input->{fh});
1076 # flush anything that's buffered, and make sure anything else is flushed
1079 return io_new_fd($fd);
1081 elsif ($input->{file}) {
1082 my $fh = new IO::File($input->{file},"w+");
1084 $self->_set_error("Could not open file $input->{file}: $!");
1087 binmode($fh) or die;
1088 return (io_new_fd(fileno($fh)), $fh);
1090 elsif ($input->{data}) {
1091 return io_new_bufchain();
1093 elsif ($input->{callback} || $input->{writecb}) {
1094 if ($input->{maxbuffer}) {
1095 return io_new_cb($input->{callback} || $input->{writecb},
1097 $input->{seekcb}, $input->{closecb},
1098 $input->{maxbuffer});
1101 return io_new_cb($input->{callback} || $input->{writecb},
1103 $input->{seekcb}, $input->{closecb});
1107 $self->_set_error("file/fd/fh/data/callback parameter missing");
1112 # Read an image from file
1118 if (defined($self->{IMG})) {
1119 # let IIM_DESTROY do the destruction, since the image may be
1120 # referenced from elsewhere
1121 #i_img_destroy($self->{IMG});
1122 undef($self->{IMG});
1125 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1127 unless ($input{'type'}) {
1128 $input{'type'} = i_test_format_probe($IO, -1);
1131 unless ($input{'type'}) {
1132 $self->_set_error('type parameter missing and not possible to guess from extension');
1136 unless ($formats{$input{'type'}}) {
1137 $self->_set_error("format '$input{'type'}' not supported");
1142 if ( $input{'type'} eq 'jpeg' ) {
1143 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1144 if ( !defined($self->{IMG}) ) {
1145 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1147 $self->{DEBUG} && print "loading a jpeg file\n";
1151 if ( $input{'type'} eq 'tiff' ) {
1152 my $page = $input{'page'};
1153 defined $page or $page = 0;
1154 # Fixme, check if that length parameter is ever needed
1155 $self->{IMG}=i_readtiff_wiol( $IO, -1, $page );
1156 if ( !defined($self->{IMG}) ) {
1157 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1159 $self->{DEBUG} && print "loading a tiff file\n";
1163 if ( $input{'type'} eq 'pnm' ) {
1164 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1165 if ( !defined($self->{IMG}) ) {
1166 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg(); return undef;
1168 $self->{DEBUG} && print "loading a pnm file\n";
1172 if ( $input{'type'} eq 'png' ) {
1173 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1174 if ( !defined($self->{IMG}) ) {
1175 $self->{ERRSTR} = $self->_error_as_msg();
1178 $self->{DEBUG} && print "loading a png file\n";
1181 if ( $input{'type'} eq 'bmp' ) {
1182 $self->{IMG}=i_readbmp_wiol( $IO );
1183 if ( !defined($self->{IMG}) ) {
1184 $self->{ERRSTR}=$self->_error_as_msg();
1187 $self->{DEBUG} && print "loading a bmp file\n";
1190 if ( $input{'type'} eq 'gif' ) {
1191 if ($input{colors} && !ref($input{colors})) {
1192 # must be a reference to a scalar that accepts the colour map
1193 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1196 if ($input{'gif_consolidate'}) {
1197 if ($input{colors}) {
1199 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1201 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1205 $self->{IMG} =i_readgif_wiol( $IO );
1209 my $page = $input{'page'};
1210 defined $page or $page = 0;
1211 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1212 if ($input{colors}) {
1213 ${ $input{colors} } =
1214 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1218 if ( !defined($self->{IMG}) ) {
1219 $self->{ERRSTR}=$self->_error_as_msg();
1222 $self->{DEBUG} && print "loading a gif file\n";
1225 if ( $input{'type'} eq 'tga' ) {
1226 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1227 if ( !defined($self->{IMG}) ) {
1228 $self->{ERRSTR}=$self->_error_as_msg();
1231 $self->{DEBUG} && print "loading a tga file\n";
1234 if ( $input{'type'} eq 'rgb' ) {
1235 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1236 if ( !defined($self->{IMG}) ) {
1237 $self->{ERRSTR}=$self->_error_as_msg();
1240 $self->{DEBUG} && print "loading a tga file\n";
1244 if ( $input{'type'} eq 'raw' ) {
1245 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1247 if ( !($params{xsize} && $params{ysize}) ) {
1248 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1252 $self->{IMG} = i_readraw_wiol( $IO,
1255 $params{datachannels},
1256 $params{storechannels},
1257 $params{interleave});
1258 if ( !defined($self->{IMG}) ) {
1259 $self->{ERRSTR}='unable to read raw image';
1262 $self->{DEBUG} && print "loading a raw file\n";
1268 sub _fix_gif_positions {
1269 my ($opts, $opt, $msg, @imgs) = @_;
1271 my $positions = $opts->{'gif_positions'};
1273 for my $pos (@$positions) {
1274 my ($x, $y) = @$pos;
1275 my $img = $imgs[$index++];
1276 $img->settag(name=>'gif_left', value=>$x);
1277 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1279 $$msg .= "replaced with the gif_left and gif_top tags";
1284 gif_each_palette=>'gif_local_map',
1285 interlace => 'gif_interlace',
1286 gif_delays => 'gif_delay',
1287 gif_positions => \&_fix_gif_positions,
1288 gif_loop_count => 'gif_loop',
1292 my ($self, $opts, $prefix, @imgs) = @_;
1294 for my $opt (keys %$opts) {
1296 if ($obsolete_opts{$opt}) {
1297 my $new = $obsolete_opts{$opt};
1298 my $msg = "Obsolete option $opt ";
1300 $new->($opts, $opt, \$msg, @imgs);
1303 $msg .= "replaced with the $new tag ";
1306 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1307 warn $msg if $warn_obsolete && $^W;
1309 next unless $tagname =~ /^\Q$prefix/;
1310 my $value = $opts->{$opt};
1312 if (UNIVERSAL::isa($value, "Imager::Color")) {
1313 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1314 for my $img (@imgs) {
1315 $img->settag(name=>$tagname, value=>$tag);
1318 elsif (ref($value) eq 'ARRAY') {
1319 for my $i (0..$#$value) {
1320 my $val = $value->[$i];
1322 if (UNIVERSAL::isa($val, "Imager::Color")) {
1323 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1325 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1328 $self->_set_error("Unknown reference type " . ref($value) .
1329 " supplied in array for $opt");
1335 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1340 $self->_set_error("Unknown reference type " . ref($value) .
1341 " supplied for $opt");
1346 # set it as a tag for every image
1347 for my $img (@imgs) {
1348 $img->settag(name=>$tagname, value=>$value);
1356 # Write an image to file
1359 my %input=(jpegquality=>75,
1369 $self->_set_opts(\%input, "i_", $self)
1372 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1374 if (!$input{'type'} and $input{file}) {
1375 $input{'type'}=$FORMATGUESS->($input{file});
1377 if (!$input{'type'}) {
1378 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1382 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1384 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1387 if ($input{'type'} eq 'tiff') {
1388 $self->_set_opts(\%input, "tiff_", $self)
1390 $self->_set_opts(\%input, "exif_", $self)
1393 if (defined $input{class} && $input{class} eq 'fax') {
1394 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1395 $self->{ERRSTR}='Could not write to buffer';
1399 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1400 $self->{ERRSTR}='Could not write to buffer';
1404 } elsif ( $input{'type'} eq 'pnm' ) {
1405 $self->_set_opts(\%input, "pnm_", $self)
1407 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1408 $self->{ERRSTR}='unable to write pnm image';
1411 $self->{DEBUG} && print "writing a pnm file\n";
1412 } elsif ( $input{'type'} eq 'raw' ) {
1413 $self->_set_opts(\%input, "raw_", $self)
1415 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1416 $self->{ERRSTR}='unable to write raw image';
1419 $self->{DEBUG} && print "writing a raw file\n";
1420 } elsif ( $input{'type'} eq 'png' ) {
1421 $self->_set_opts(\%input, "png_", $self)
1423 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1424 $self->{ERRSTR}='unable to write png image';
1427 $self->{DEBUG} && print "writing a png file\n";
1428 } elsif ( $input{'type'} eq 'jpeg' ) {
1429 $self->_set_opts(\%input, "jpeg_", $self)
1431 $self->_set_opts(\%input, "exif_", $self)
1433 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1434 $self->{ERRSTR} = $self->_error_as_msg();
1437 $self->{DEBUG} && print "writing a jpeg file\n";
1438 } elsif ( $input{'type'} eq 'bmp' ) {
1439 $self->_set_opts(\%input, "bmp_", $self)
1441 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1442 $self->{ERRSTR}='unable to write bmp image';
1445 $self->{DEBUG} && print "writing a bmp file\n";
1446 } elsif ( $input{'type'} eq 'tga' ) {
1447 $self->_set_opts(\%input, "tga_", $self)
1450 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1451 $self->{ERRSTR}=$self->_error_as_msg();
1454 $self->{DEBUG} && print "writing a tga file\n";
1455 } elsif ( $input{'type'} eq 'gif' ) {
1456 $self->_set_opts(\%input, "gif_", $self)
1458 # compatibility with the old interfaces
1459 if ($input{gifquant} eq 'lm') {
1460 $input{make_colors} = 'addi';
1461 $input{translate} = 'perturb';
1462 $input{perturb} = $input{lmdither};
1463 } elsif ($input{gifquant} eq 'gen') {
1464 # just pass options through
1466 $input{make_colors} = 'webmap'; # ignored
1467 $input{translate} = 'giflib';
1469 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1470 $self->{ERRSTR} = $self->_error_as_msg;
1475 if (exists $input{'data'}) {
1476 my $data = io_slurp($IO);
1478 $self->{ERRSTR}='Could not slurp from buffer';
1481 ${$input{data}} = $data;
1487 my ($class, $opts, @images) = @_;
1489 if (!$opts->{'type'} && $opts->{'file'}) {
1490 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1492 unless ($opts->{'type'}) {
1493 $class->_set_error('type parameter missing and not possible to guess from extension');
1496 # translate to ImgRaw
1497 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1498 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1501 $class->_set_opts($opts, "i_", @images)
1503 my @work = map $_->{IMG}, @images;
1504 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1506 if ($opts->{'type'} eq 'gif') {
1507 $class->_set_opts($opts, "gif_", @images)
1509 my $gif_delays = $opts->{gif_delays};
1510 local $opts->{gif_delays} = $gif_delays;
1511 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1512 # assume the caller wants the same delay for each frame
1513 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1515 my $res = i_writegif_wiol($IO, $opts, @work);
1516 $res or $class->_set_error($class->_error_as_msg());
1519 elsif ($opts->{'type'} eq 'tiff') {
1520 $class->_set_opts($opts, "tiff_", @images)
1522 $class->_set_opts($opts, "exif_", @images)
1525 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1526 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1527 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1530 $res = i_writetiff_multi_wiol($IO, @work);
1532 $res or $class->_set_error($class->_error_as_msg());
1536 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1541 # read multiple images from a file
1543 my ($class, %opts) = @_;
1545 if ($opts{file} && !exists $opts{'type'}) {
1547 my $type = $FORMATGUESS->($opts{file});
1548 $opts{'type'} = $type;
1550 unless ($opts{'type'}) {
1551 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1555 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1557 if ($opts{'type'} eq 'gif') {
1559 @imgs = i_readgif_multi_wiol($IO);
1562 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1566 $ERRSTR = _error_as_msg();
1570 elsif ($opts{'type'} eq 'tiff') {
1571 my @imgs = i_readtiff_multi_wiol($IO, -1);
1574 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1578 $ERRSTR = _error_as_msg();
1583 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1587 # Destroy an Imager object
1591 # delete $instances{$self};
1592 if (defined($self->{IMG})) {
1593 # the following is now handled by the XS DESTROY method for
1594 # Imager::ImgRaw object
1595 # Re-enabling this will break virtual images
1596 # tested for in t/t020masked.t
1597 # i_img_destroy($self->{IMG});
1598 undef($self->{IMG});
1600 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1604 # Perform an inplace filter of an image
1605 # that is the image will be overwritten with the data
1611 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1613 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1615 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1616 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1619 if ($filters{$input{'type'}}{names}) {
1620 my $names = $filters{$input{'type'}}{names};
1621 for my $name (keys %$names) {
1622 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1623 $input{$name} = $names->{$name}{$input{$name}};
1627 if (defined($filters{$input{'type'}}{defaults})) {
1628 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1630 %hsh=('image',$self->{IMG},%input);
1633 my @cs=@{$filters{$input{'type'}}{callseq}};
1636 if (!defined($hsh{$_})) {
1637 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1642 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1643 &{$filters{$input{'type'}}{callsub}}(%hsh);
1646 chomp($self->{ERRSTR} = $@);
1652 $self->{DEBUG} && print "callseq is: @cs\n";
1653 $self->{DEBUG} && print "matching callseq is: @b\n";
1658 # Scale an image to requested size and return the scaled version
1662 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1663 my $img = Imager->new();
1664 my $tmp = Imager->new();
1666 unless (defined wantarray) {
1667 my @caller = caller;
1668 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1672 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1674 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1675 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1676 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1677 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1678 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1679 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1681 if ($opts{qtype} eq 'normal') {
1682 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1683 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1684 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1685 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1688 if ($opts{'qtype'} eq 'preview') {
1689 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1690 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1693 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1696 # Scales only along the X axis
1700 my %opts=(scalefactor=>0.5,@_);
1702 unless (defined wantarray) {
1703 my @caller = caller;
1704 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1708 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1710 my $img = Imager->new();
1712 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1714 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1715 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1717 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1721 # Scales only along the Y axis
1725 my %opts=(scalefactor=>0.5,@_);
1727 unless (defined wantarray) {
1728 my @caller = caller;
1729 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1733 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1735 my $img = Imager->new();
1737 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1739 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1740 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1742 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1747 # Transform returns a spatial transformation of the input image
1748 # this moves pixels to a new location in the returned image.
1749 # NOTE - should make a utility function to check transforms for
1754 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1756 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1758 # print Dumper(\%opts);
1761 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1763 eval ("use Affix::Infix2Postfix;");
1766 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1769 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1770 {op=>'-',trans=>'Sub'},
1771 {op=>'*',trans=>'Mult'},
1772 {op=>'/',trans=>'Div'},
1773 {op=>'-','type'=>'unary',trans=>'u-'},
1775 {op=>'func','type'=>'unary'}],
1776 'grouping'=>[qw( \( \) )],
1777 'func'=>[qw( sin cos )],
1782 @xt=$I2P->translate($opts{'xexpr'});
1783 @yt=$I2P->translate($opts{'yexpr'});
1785 $numre=$I2P->{'numre'};
1788 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1789 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1790 @{$opts{'parm'}}=@pt;
1793 # print Dumper(\%opts);
1795 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1796 $self->{ERRSTR}='transform: no xopcodes given.';
1800 @op=@{$opts{'xopcodes'}};
1802 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1803 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1806 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1812 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1813 $self->{ERRSTR}='transform: no yopcodes given.';
1817 @op=@{$opts{'yopcodes'}};
1819 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1820 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1823 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1828 if ( !exists $opts{'parm'}) {
1829 $self->{ERRSTR}='transform: no parameter arg given.';
1833 # print Dumper(\@ropx);
1834 # print Dumper(\@ropy);
1835 # print Dumper(\@ropy);
1837 my $img = Imager->new();
1838 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1839 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1845 my ($opts, @imgs) = @_;
1847 require "Imager/Expr.pm";
1849 $opts->{variables} = [ qw(x y) ];
1850 my ($width, $height) = @{$opts}{qw(width height)};
1852 $width ||= $imgs[0]->getwidth();
1853 $height ||= $imgs[0]->getheight();
1855 for my $img (@imgs) {
1856 $opts->{constants}{"w$img_num"} = $img->getwidth();
1857 $opts->{constants}{"h$img_num"} = $img->getheight();
1858 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1859 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1864 $opts->{constants}{w} = $width;
1865 $opts->{constants}{cx} = $width/2;
1868 $Imager::ERRSTR = "No width supplied";
1872 $opts->{constants}{h} = $height;
1873 $opts->{constants}{cy} = $height/2;
1876 $Imager::ERRSTR = "No height supplied";
1879 my $code = Imager::Expr->new($opts);
1881 $Imager::ERRSTR = Imager::Expr::error();
1884 my $channels = $opts->{channels} || 3;
1885 unless ($channels >= 1 && $channels <= 4) {
1886 return Imager->_set_error("channels must be an integer between 1 and 4");
1889 my $img = Imager->new();
1890 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1891 $channels, $code->code(),
1892 $code->nregs(), $code->cregs(),
1893 [ map { $_->{IMG} } @imgs ]);
1894 if (!defined $img->{IMG}) {
1895 $Imager::ERRSTR = Imager->_error_as_msg();
1904 my %opts=(tx => 0,ty => 0, @_);
1906 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1907 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1909 %opts = (src_minx => 0,
1911 src_maxx => $opts{src}->getwidth(),
1912 src_maxy => $opts{src}->getheight(),
1915 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1916 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1917 $self->{ERRSTR} = $self->_error_as_msg();
1927 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
1929 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
1930 $dir = $xlate{$opts{'dir'}};
1931 return $self if i_flipxy($self->{IMG}, $dir);
1939 unless (defined wantarray) {
1940 my @caller = caller;
1941 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
1945 if (defined $opts{right}) {
1946 my $degrees = $opts{right};
1948 $degrees += 360 * int(((-$degrees)+360)/360);
1950 $degrees = $degrees % 360;
1951 if ($degrees == 0) {
1952 return $self->copy();
1954 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
1955 my $result = Imager->new();
1956 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
1960 $self->{ERRSTR} = $self->_error_as_msg();
1965 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
1969 elsif (defined $opts{radians} || defined $opts{degrees}) {
1970 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
1972 my $result = Imager->new;
1974 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
1977 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
1979 if ($result->{IMG}) {
1983 $self->{ERRSTR} = $self->_error_as_msg();
1988 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
1993 sub matrix_transform {
1997 unless (defined wantarray) {
1998 my @caller = caller;
1999 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2003 if ($opts{matrix}) {
2004 my $xsize = $opts{xsize} || $self->getwidth;
2005 my $ysize = $opts{ysize} || $self->getheight;
2007 my $result = Imager->new;
2009 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2010 $opts{matrix}, $opts{back})
2014 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2022 $self->{ERRSTR} = "matrix parameter required";
2028 *yatf = \&matrix_transform;
2030 # These two are supported for legacy code only
2033 return Imager::Color->new(@_);
2037 return Imager::Color::set(@_);
2040 # Draws a box between the specified corner points.
2043 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2044 my $dflcl=i_color_new(255,255,255,255);
2045 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2047 if (exists $opts{'box'}) {
2048 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
2049 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
2050 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
2051 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
2054 if ($opts{filled}) {
2055 my $color = _color($opts{'color'});
2057 $self->{ERRSTR} = $Imager::ERRSTR;
2060 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2061 $opts{ymax}, $color);
2063 elsif ($opts{fill}) {
2064 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2065 # assume it's a hash ref
2066 require 'Imager/Fill.pm';
2067 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2068 $self->{ERRSTR} = $Imager::ERRSTR;
2072 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2073 $opts{ymax},$opts{fill}{fill});
2076 my $color = _color($opts{'color'});
2078 $self->{ERRSTR} = $Imager::ERRSTR;
2081 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2087 # Draws an arc - this routine SUCKS and is buggy - it sometimes doesn't work when the arc is a convex polygon
2091 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2092 my $dflcl=i_color_new(255,255,255,255);
2093 my %opts=(color=>$dflcl,
2094 'r'=>min($self->getwidth(),$self->getheight())/3,
2095 'x'=>$self->getwidth()/2,
2096 'y'=>$self->getheight()/2,
2097 'd1'=>0, 'd2'=>361, @_);
2099 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2100 # assume it's a hash ref
2101 require 'Imager/Fill.pm';
2102 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2103 $self->{ERRSTR} = $Imager::ERRSTR;
2107 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2108 $opts{'d2'}, $opts{fill}{fill});
2111 my $color = _color($opts{'color'});
2113 $self->{ERRSTR} = $Imager::ERRSTR;
2116 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2117 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2121 if ($opts{'d1'} <= $opts{'d2'}) {
2122 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2123 $opts{'d1'}, $opts{'d2'}, $color);
2126 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2127 $opts{'d1'}, 361, $color);
2128 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2129 0, $opts{'d2'}, $color);
2137 # Draws a line from one point to the other
2138 # the endpoint is set if the endp parameter is set which it is by default.
2139 # to turn of the endpoint being set use endp=>0 when calling line.
2143 my $dflcl=i_color_new(0,0,0,0);
2144 my %opts=(color=>$dflcl,
2147 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2149 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2150 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2152 my $color = _color($opts{'color'});
2154 $self->{ERRSTR} = $Imager::ERRSTR;
2158 $opts{antialias} = $opts{aa} if defined $opts{aa};
2159 if ($opts{antialias}) {
2160 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2161 $color, $opts{endp});
2163 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2164 $color, $opts{endp});
2169 # Draws a line between an ordered set of points - It more or less just transforms this
2170 # into a list of lines.
2174 my ($pt,$ls,@points);
2175 my $dflcl=i_color_new(0,0,0,0);
2176 my %opts=(color=>$dflcl,@_);
2178 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2180 if (exists($opts{points})) { @points=@{$opts{points}}; }
2181 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2182 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2185 # print Dumper(\@points);
2187 my $color = _color($opts{'color'});
2189 $self->{ERRSTR} = $Imager::ERRSTR;
2192 $opts{antialias} = $opts{aa} if defined $opts{aa};
2193 if ($opts{antialias}) {
2196 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2203 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2213 my ($pt,$ls,@points);
2214 my $dflcl = i_color_new(0,0,0,0);
2215 my %opts = (color=>$dflcl, @_);
2217 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2219 if (exists($opts{points})) {
2220 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2221 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2224 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2225 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2228 if ($opts{'fill'}) {
2229 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2230 # assume it's a hash ref
2231 require 'Imager/Fill.pm';
2232 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2233 $self->{ERRSTR} = $Imager::ERRSTR;
2237 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2238 $opts{'fill'}{'fill'});
2241 my $color = _color($opts{'color'});
2243 $self->{ERRSTR} = $Imager::ERRSTR;
2246 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2253 # this the multipoint bezier curve
2254 # this is here more for testing that actual usage since
2255 # this is not a good algorithm. Usually the curve would be
2256 # broken into smaller segments and each done individually.
2260 my ($pt,$ls,@points);
2261 my $dflcl=i_color_new(0,0,0,0);
2262 my %opts=(color=>$dflcl,@_);
2264 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2266 if (exists $opts{points}) {
2267 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2268 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2271 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2272 $self->{ERRSTR}='Missing or invalid points.';
2276 my $color = _color($opts{'color'});
2278 $self->{ERRSTR} = $Imager::ERRSTR;
2281 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2287 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2290 unless (exists $opts{'x'} && exists $opts{'y'}) {
2291 $self->{ERRSTR} = "missing seed x and y parameters";
2296 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2297 # assume it's a hash ref
2298 require 'Imager/Fill.pm';
2299 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2300 $self->{ERRSTR} = $Imager::ERRSTR;
2304 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2307 my $color = _color($opts{'color'});
2309 $self->{ERRSTR} = $Imager::ERRSTR;
2312 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2314 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2320 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2322 unless (exists $opts{'x'} && exists $opts{'y'}) {
2323 $self->{ERRSTR} = 'missing x and y parameters';
2329 my $color = _color($opts{color})
2331 if (ref $x && ref $y) {
2332 unless (@$x == @$y) {
2333 $self->{ERRSTR} = 'length of x and y mismatch';
2336 if ($color->isa('Imager::Color')) {
2337 for my $i (0..$#{$opts{'x'}}) {
2338 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2342 for my $i (0..$#{$opts{'x'}}) {
2343 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2348 if ($color->isa('Imager::Color')) {
2349 i_ppix($self->{IMG}, $x, $y, $color);
2352 i_ppixf($self->{IMG}, $x, $y, $color);
2362 my %opts = ( "type"=>'8bit', @_);
2364 unless (exists $opts{'x'} && exists $opts{'y'}) {
2365 $self->{ERRSTR} = 'missing x and y parameters';
2371 if (ref $x && ref $y) {
2372 unless (@$x == @$y) {
2373 $self->{ERRSTR} = 'length of x and y mismatch';
2377 if ($opts{"type"} eq '8bit') {
2378 for my $i (0..$#{$opts{'x'}}) {
2379 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2383 for my $i (0..$#{$opts{'x'}}) {
2384 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2387 return wantarray ? @result : \@result;
2390 if ($opts{"type"} eq '8bit') {
2391 return i_get_pixel($self->{IMG}, $x, $y);
2394 return i_gpixf($self->{IMG}, $x, $y);
2403 my %opts = ( type => '8bit', x=>0, @_);
2405 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2407 unless (defined $opts{'y'}) {
2408 $self->_set_error("missing y parameter");
2412 if ($opts{type} eq '8bit') {
2413 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2416 elsif ($opts{type} eq 'float') {
2417 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2421 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2428 my %opts = ( x=>0, @_);
2430 unless (defined $opts{'y'}) {
2431 $self->_set_error("missing y parameter");
2436 if (ref $opts{pixels} && @{$opts{pixels}}) {
2437 # try to guess the type
2438 if ($opts{pixels}[0]->isa('Imager::Color')) {
2439 $opts{type} = '8bit';
2441 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2442 $opts{type} = 'float';
2445 $self->_set_error("missing type parameter and could not guess from pixels");
2451 $opts{type} = '8bit';
2455 if ($opts{type} eq '8bit') {
2456 if (ref $opts{pixels}) {
2457 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2460 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2463 elsif ($opts{type} eq 'float') {
2464 if (ref $opts{pixels}) {
2465 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2468 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2472 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2479 my %opts = ( type => '8bit', x=>0, @_);
2481 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2483 unless (defined $opts{'y'}) {
2484 $self->_set_error("missing y parameter");
2488 unless ($opts{channels}) {
2489 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2492 if ($opts{type} eq '8bit') {
2493 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2494 $opts{y}, @{$opts{channels}});
2496 elsif ($opts{type} eq 'float') {
2497 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2498 $opts{y}, @{$opts{channels}});
2501 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2506 # make an identity matrix of the given size
2510 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2511 for my $c (0 .. ($size-1)) {
2512 $matrix->[$c][$c] = 1;
2517 # general function to convert an image
2519 my ($self, %opts) = @_;
2522 unless (defined wantarray) {
2523 my @caller = caller;
2524 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2528 # the user can either specify a matrix or preset
2529 # the matrix overrides the preset
2530 if (!exists($opts{matrix})) {
2531 unless (exists($opts{preset})) {
2532 $self->{ERRSTR} = "convert() needs a matrix or preset";
2536 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2537 # convert to greyscale, keeping the alpha channel if any
2538 if ($self->getchannels == 3) {
2539 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2541 elsif ($self->getchannels == 4) {
2542 # preserve the alpha channel
2543 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2548 $matrix = _identity($self->getchannels);
2551 elsif ($opts{preset} eq 'noalpha') {
2552 # strip the alpha channel
2553 if ($self->getchannels == 2 or $self->getchannels == 4) {
2554 $matrix = _identity($self->getchannels);
2555 pop(@$matrix); # lose the alpha entry
2558 $matrix = _identity($self->getchannels);
2561 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2563 $matrix = [ [ 1 ] ];
2565 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2566 $matrix = [ [ 0, 1 ] ];
2568 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2569 $matrix = [ [ 0, 0, 1 ] ];
2571 elsif ($opts{preset} eq 'alpha') {
2572 if ($self->getchannels == 2 or $self->getchannels == 4) {
2573 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2576 # the alpha is just 1 <shrug>
2577 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2580 elsif ($opts{preset} eq 'rgb') {
2581 if ($self->getchannels == 1) {
2582 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2584 elsif ($self->getchannels == 2) {
2585 # preserve the alpha channel
2586 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2589 $matrix = _identity($self->getchannels);
2592 elsif ($opts{preset} eq 'addalpha') {
2593 if ($self->getchannels == 1) {
2594 $matrix = _identity(2);
2596 elsif ($self->getchannels == 3) {
2597 $matrix = _identity(4);
2600 $matrix = _identity($self->getchannels);
2604 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2610 $matrix = $opts{matrix};
2613 my $new = Imager->new();
2614 $new->{IMG} = i_img_new();
2615 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2616 # most likely a bad matrix
2617 $self->{ERRSTR} = _error_as_msg();
2624 # general function to map an image through lookup tables
2627 my ($self, %opts) = @_;
2628 my @chlist = qw( red green blue alpha );
2630 if (!exists($opts{'maps'})) {
2631 # make maps from channel maps
2633 for $chnum (0..$#chlist) {
2634 if (exists $opts{$chlist[$chnum]}) {
2635 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2636 } elsif (exists $opts{'all'}) {
2637 $opts{'maps'}[$chnum] = $opts{'all'};
2641 if ($opts{'maps'} and $self->{IMG}) {
2642 i_map($self->{IMG}, $opts{'maps'} );
2648 my ($self, %opts) = @_;
2650 defined $opts{mindist} or $opts{mindist} = 0;
2652 defined $opts{other}
2653 or return $self->_set_error("No 'other' parameter supplied");
2654 defined $opts{other}{IMG}
2655 or return $self->_set_error("No image data in 'other' image");
2658 or return $self->_set_error("No image data");
2660 my $result = Imager->new;
2661 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2663 or return $self->_set_error($self->_error_as_msg());
2668 # destructive border - image is shrunk by one pixel all around
2671 my ($self,%opts)=@_;
2672 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2673 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2677 # Get the width of an image
2681 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2682 return (i_img_info($self->{IMG}))[0];
2685 # Get the height of an image
2689 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2690 return (i_img_info($self->{IMG}))[1];
2693 # Get number of channels in an image
2697 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2698 return i_img_getchannels($self->{IMG});
2705 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2706 return i_img_getmask($self->{IMG});
2714 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2715 i_img_setmask( $self->{IMG} , $opts{mask} );
2718 # Get number of colors in an image
2722 my %opts=('maxcolors'=>2**30,@_);
2723 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2724 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2725 return ($rc==-1? undef : $rc);
2728 # draw string to an image
2732 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2734 my %input=('x'=>0, 'y'=>0, @_);
2735 $input{string}||=$input{text};
2737 unless(exists $input{string}) {
2738 $self->{ERRSTR}="missing required parameter 'string'";
2742 unless($input{font}) {
2743 $self->{ERRSTR}="missing required parameter 'font'";
2747 unless ($input{font}->draw(image=>$self, %input)) {
2748 $self->{ERRSTR} = $self->_error_as_msg();
2755 my @file_limit_names = qw/width height bytes/;
2757 sub set_file_limits {
2764 @values{@file_limit_names} = (0) x @file_limit_names;
2767 @values{@file_limit_names} = i_get_image_file_limits();
2770 for my $key (keys %values) {
2771 defined $opts{$key} and $values{$key} = $opts{$key};
2774 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
2777 sub get_file_limits {
2778 i_get_image_file_limits();
2781 # Shortcuts that can be exported
2783 sub newcolor { Imager::Color->new(@_); }
2784 sub newfont { Imager::Font->new(@_); }
2786 *NC=*newcolour=*newcolor;
2793 #### Utility routines
2796 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2800 my ($self, $msg) = @_;
2803 $self->{ERRSTR} = $msg;
2811 # Default guess for the type of an image from extension
2813 sub def_guess_type {
2816 $ext=($name =~ m/\.([^\.]+)$/)[0];
2817 return 'tiff' if ($ext =~ m/^tiff?$/);
2818 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2819 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2820 return 'png' if ($ext eq "png");
2821 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2822 return 'tga' if ($ext eq "tga");
2823 return 'rgb' if ($ext eq "rgb");
2824 return 'gif' if ($ext eq "gif");
2825 return 'raw' if ($ext eq "raw");
2829 # get the minimum of a list
2833 for(@_) { if ($_<$mx) { $mx=$_; }}
2837 # get the maximum of a list
2841 for(@_) { if ($_>$mx) { $mx=$_; }}
2845 # string stuff for iptc headers
2849 $str = substr($str,3);
2850 $str =~ s/[\n\r]//g;
2857 # A little hack to parse iptc headers.
2862 my($caption,$photogr,$headln,$credit);
2864 my $str=$self->{IPTCRAW};
2868 @ar=split(/8BIM/,$str);
2873 @sar=split(/\034\002/);
2874 foreach $item (@sar) {
2875 if ($item =~ m/^x/) {
2876 $caption=&clean($item);
2879 if ($item =~ m/^P/) {
2880 $photogr=&clean($item);
2883 if ($item =~ m/^i/) {
2884 $headln=&clean($item);
2887 if ($item =~ m/^n/) {
2888 $credit=&clean($item);
2894 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
2897 # Autoload methods go after =cut, and are processed by the autosplit program.
2901 # Below is the stub of documentation for your module. You better edit it!
2905 Imager - Perl extension for Generating 24 bit Images
2915 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
2920 my $img = Imager->new();
2921 # see Imager::Files for information on the read() method
2922 $img->read(file=>$file) or die $img->errstr();
2924 $file =~ s/\.[^.]*$//;
2926 # Create smaller version
2927 # documented in Imager::Transformations
2928 my $thumb = $img->scale(scalefactor=>.3);
2930 # Autostretch individual channels
2931 $thumb->filter(type=>'autolevels');
2933 # try to save in one of these formats
2936 for $format ( qw( png gif jpg tiff ppm ) ) {
2937 # Check if given format is supported
2938 if ($Imager::formats{$format}) {
2939 $file.="_low.$format";
2940 print "Storing image as: $file\n";
2941 # documented in Imager::Files
2942 $thumb->write(file=>$file) or
2950 Imager is a module for creating and altering images. It can read and
2951 write various image formats, draw primitive shapes like lines,and
2952 polygons, blend multiple images together in various ways, scale, crop,
2953 render text and more.
2955 =head2 Overview of documentation
2961 Imager - This document - Synopsis Example, Table of Contents and
2966 L<Imager::Tutorial> - a brief introduction to Imager.
2970 L<Imager::Cookbook> - how to do various things with Imager.
2974 L<Imager::ImageTypes> - Basics of constructing image objects with
2975 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
2976 8/16/double bits/channel, color maps, channel masks, image tags, color
2977 quantization. Also discusses basic image information methods.
2981 L<Imager::Files> - IO interaction, reading/writing images, format
2986 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
2991 L<Imager::Color> - Color specification.
2995 L<Imager::Fill> - Fill pattern specification.
2999 L<Imager::Font> - General font rendering, bounding boxes and font
3004 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3005 blending, pasting, convert and map.
3009 L<Imager::Engines> - Programmable transformations through
3010 C<transform()>, C<transform2()> and C<matrix_transform()>.
3014 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3019 L<Imager::Expr> - Expressions for evaluation engine used by
3024 L<Imager::Matrix2d> - Helper class for affine transformations.
3028 L<Imager::Fountain> - Helper for making gradient profiles.
3032 =head2 Basic Overview
3034 An Image object is created with C<$img = Imager-E<gt>new()>.
3037 $img=Imager->new(); # create empty image
3038 $img->read(file=>'lena.png',type=>'png') or # read image from file
3039 die $img->errstr(); # give an explanation
3040 # if something failed
3042 or if you want to create an empty image:
3044 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3046 This example creates a completely black image of width 400 and height
3049 When an operation fails which can be directly associated with an image
3050 the error message is stored can be retrieved with
3051 C<$img-E<gt>errstr()>.
3053 In cases where no image object is associated with an operation
3054 C<$Imager::ERRSTR> is used to report errors not directly associated
3055 with an image object. You can also call C<Imager->errstr> to get this
3058 The C<Imager-E<gt>new> method is described in detail in
3059 L<Imager::ImageTypes>.
3063 Where to find information on methods for Imager class objects.
3065 addcolors() - L<Imager::ImageTypes>
3067 addtag() - L<Imager::ImageTypes> - add image tags
3069 arc() - L<Imager::Draw/arc>
3071 bits() - L<Imager::ImageTypes> - number of bits per sample for the
3074 box() - L<Imager::Draw/box>
3076 circle() - L<Imager::Draw/circle>
3078 colorcount() - L<Imager::Draw/colorcount>
3080 convert() - L<Imager::Transformations/"Color transformations"> -
3081 transform the color space
3083 copy() - L<Imager::Transformations/copy>
3085 crop() - L<Imager::Transformations/crop> - extract part of an image
3087 deltag() - L<Imager::ImageTypes> - delete image tags
3089 difference() - L<Imager::Filters/"Image Difference">
3091 errstr() - L<Imager/"Basic Overview">
3093 filter() - L<Imager::Filters>
3095 findcolor() - L<Imager::ImageTypes> - search the image palette, if it
3098 flip() - L<Imager::Transformations/flip>
3100 flood_fill() - L<Imager::Draw/flood_fill>
3102 getchannels() - L<Imager::ImageTypes>
3104 getcolorcount() - L<Imager::ImageTypes>
3106 getcolors() - L<Imager::ImageTypes> - get colors from the image
3107 palette, if it has one
3109 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3111 getheight() - L<Imager::ImageTypes>
3113 getpixel() - L<Imager::Draw/setpixel and getpixel>
3115 getsamples() - L<Imager::Draw/getsamples>
3117 getscanline() - L<Imager::Draw/getscanline>
3119 getwidth() - L<Imager::ImageTypes>
3121 img_set() - L<Imager::ImageTypes>
3123 line() - L<Imager::Draw/line>
3125 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3128 masked() - L<Imager::ImageTypes> - make a masked image
3130 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
3132 maxcolors() - L<Imager::ImageTypes/maxcolor>
3134 new() - L<Imager::ImageTypes>
3136 open() - L<Imager::Files> - an alias for read()
3138 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3140 polygon() - L<Imager::Draw/polygon>
3142 polyline() - L<Imager::Draw/polyline>
3144 read() - L<Imager::Files> - read a single image from an image file
3146 read_multi() - L<Imager::Files> - read multiple images from an image
3149 rotate() - L<Imager::Transformations/rotate>
3151 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3152 image and use the alpha channel
3154 scale() - L<Imager::Transformations/scale>
3156 setscanline() - L<Imager::Draw/setscanline>
3158 scaleX() - L<Imager::Transformations/scaleX>
3160 scaleY() - L<Imager::Transformations/scaleY>
3162 setcolors() - L<Imager::ImageTypes> - set palette colors in a paletted image
3164 setpixel() - L<Imager::Draw/setpixel and getpixel>
3166 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3168 string() - L<Imager::Font/string> - draw text on an image
3170 tags() - L<Imager::ImageTypes> - fetch image tags
3172 to_paletted() - L<Imager::ImageTypes>
3174 to_rgb8() - L<Imager::ImageTypes>
3176 transform() - L<Imager::Engines/"transform">
3178 transform2() - L<Imager::Engines/"transform2">
3180 type() - L<Imager::ImageTypes> - type of image (direct vs paletted)
3182 virtual() - L<Imager::ImageTypes> - whether the image has it's own
3185 write() - L<Imager::Files> - write an image to a file
3187 write_multi() - L<Imager::Files> - write multiple image to an image
3190 =head1 CONCEPT INDEX
3192 animated GIF - L<Imager::File/"Writing an animated GIF">
3194 aspect ratio - L<Imager::ImageTypes/i_xres>,
3195 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3197 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3199 boxes, drawing - L<Imager::Draw/box>
3201 color - L<Imager::Color>
3203 color names - L<Imager::Color>, L<Imager::Color::Table>
3205 combine modes - L<Imager::Fill/combine>
3207 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3209 convolution - L<Imager::Filter/conv>
3211 cropping - L<Imager::Transformations/crop>
3213 dpi - L<Imager::ImageTypes/i_xres>
3215 drawing boxes - L<Imager::Draw/box>
3217 drawing lines - L<Imager::Draw/line>
3219 drawing text - L<Imager::Font/string>, L<Imager::Font/align>
3221 error message - L<Imager/"Basic Overview">
3223 files, font - L<Imager::Font>
3225 files, image - L<Imager::Files>
3227 filling, types of fill - L<Imager::Fill>
3229 filling, boxes - L<Imager::Draw/box>
3231 filling, flood fill - L<Imager::Draw/flood_fill>
3233 flood fill - L<Imager::Draw/flood_fill>
3235 fonts - L<Imager::Font>
3237 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3238 L<Imager::Font::Wrap>
3240 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3242 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3244 fountain fill - L<Imager::Fill/"Fountain fills">,
3245 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3246 L<Imager::Filters/gradgen>
3248 GIF files - L<Imager::Files/"GIF">
3250 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3252 gradient fill - L<Imager::Fill/"Fountain fills">,
3253 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3254 L<Imager::Filters/gradgen>
3256 guassian blur - L<Imager::Filter/guassian>
3258 hatch fills - L<Imager::Fill/"Hatched fills">
3260 invert image - L<Imager::Filter/hardinvert>
3262 JPEG - L<Imager::Files/"JPEG">
3264 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3266 lines, drawing - L<Imager::Draw/line>
3268 matrix - L<Imager::Matrix2d>,
3269 L<Imager::Transformations/"Matrix Transformations">,
3270 L<Imager::Font/transform>
3272 metadata, image - L<Imager::ImageTypes/"Tags">
3274 mosaic - L<Imager::Filter/mosaic>
3276 noise, filter - L<Imager::Filter/noise>
3278 noise, rendered - L<Imager::Filter/turbnoise>,
3279 L<Imager::Filter/radnoise>
3281 posterize - L<Imager::Filter/postlevels>
3283 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3285 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3287 rectangles, drawing - L<Imager::Draw/box>
3289 resizing an image - L<Imager::Transformations/scale>,
3290 L<Imager::Transformations/crop>
3292 saving an image - L<Imager::Files>
3294 scaling - L<Imager::Transformations/scale>
3296 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3298 size, image - L<Imager::ImageTypes/getwidth>,
3299 L<Imager::ImageTypes/getheight>
3301 size, text - L<Imager::Font/bounding_box>
3303 text, drawing - L<Imager::Font/string>, L<Imager::Font/align>,
3304 L<Imager::Font::Wrap>
3306 text, wrapping text in an area - L<Imager::Font::Wrap>
3308 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3310 tiles, color - L<Imager::Filter/mosaic>
3312 unsharp mask - L<Imager::Filter/unsharpmask>
3314 watermark - L<Imager::Filter/watermark>
3316 writing an image - L<Imager::Files>
3320 You can ask for help, report bugs or express your undying love for
3321 Imager on the Imager-devel mailing list.
3323 To subscribe send a message with C<subscribe> in the body to:
3325 imager-devel+request@molar.is
3329 http://www.molar.is/en/lists/imager-devel/
3330 (annonymous is temporarily off due to spam)
3332 where you can also find the mailing list archive.
3334 If you're into IRC, you can typically find the developers in #Imager
3335 on irc.perl.org. As with any IRC channel, the participants could be
3336 occupied or asleep, so please be patient.
3338 You can report bugs by pointing your browser at:
3340 https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager
3342 Please remember to include the versions of Imager, perl, supporting
3343 libraries, and any relevant code. If you have specific images that
3344 cause the problems, please include those too.
3348 Bugs are listed individually for relevant pod pages.
3352 Arnar M. Hrafnkelsson (addi@imager.perl.org) and Tony Cook
3353 (tony@imager.perl.org) See the README for a complete list.
3357 perl(1), Imager::ImageTypes(3), Imager::Files(3), Imager::Draw(3),
3358 Imager::Color(3), Imager::Fill(3), Imager::Font(3),
3359 Imager::Transformations(3), Imager::Engines(3), Imager::Filters(3),
3360 Imager::Expr(3), Imager::Matrix2d(3), Imager::Fountain(3)
3362 Affix::Infix2Postfix(3), Parse::RecDescent(3)
3363 http://imager.perl.org/