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 $self->{IMG}=i_readtiff_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1153 if ( !defined($self->{IMG}) ) {
1154 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1156 $self->{DEBUG} && print "loading a tiff file\n";
1160 if ( $input{'type'} eq 'pnm' ) {
1161 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1162 if ( !defined($self->{IMG}) ) {
1163 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg(); return undef;
1165 $self->{DEBUG} && print "loading a pnm file\n";
1169 if ( $input{'type'} eq 'png' ) {
1170 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1171 if ( !defined($self->{IMG}) ) {
1172 $self->{ERRSTR} = $self->_error_as_msg();
1175 $self->{DEBUG} && print "loading a png file\n";
1178 if ( $input{'type'} eq 'bmp' ) {
1179 $self->{IMG}=i_readbmp_wiol( $IO );
1180 if ( !defined($self->{IMG}) ) {
1181 $self->{ERRSTR}=$self->_error_as_msg();
1184 $self->{DEBUG} && print "loading a bmp file\n";
1187 if ( $input{'type'} eq 'gif' ) {
1188 if ($input{colors} && !ref($input{colors})) {
1189 # must be a reference to a scalar that accepts the colour map
1190 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1193 if ($input{colors}) {
1195 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1197 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1201 $self->{IMG} =i_readgif_wiol( $IO );
1203 if ( !defined($self->{IMG}) ) {
1204 $self->{ERRSTR}=$self->_error_as_msg();
1207 $self->{DEBUG} && print "loading a gif file\n";
1210 if ( $input{'type'} eq 'tga' ) {
1211 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1212 if ( !defined($self->{IMG}) ) {
1213 $self->{ERRSTR}=$self->_error_as_msg();
1216 $self->{DEBUG} && print "loading a tga file\n";
1219 if ( $input{'type'} eq 'rgb' ) {
1220 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1221 if ( !defined($self->{IMG}) ) {
1222 $self->{ERRSTR}=$self->_error_as_msg();
1225 $self->{DEBUG} && print "loading a tga file\n";
1229 if ( $input{'type'} eq 'raw' ) {
1230 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1232 if ( !($params{xsize} && $params{ysize}) ) {
1233 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1237 $self->{IMG} = i_readraw_wiol( $IO,
1240 $params{datachannels},
1241 $params{storechannels},
1242 $params{interleave});
1243 if ( !defined($self->{IMG}) ) {
1244 $self->{ERRSTR}='unable to read raw image';
1247 $self->{DEBUG} && print "loading a raw file\n";
1253 sub _fix_gif_positions {
1254 my ($opts, $opt, $msg, @imgs) = @_;
1256 my $positions = $opts->{'gif_positions'};
1258 for my $pos (@$positions) {
1259 my ($x, $y) = @$pos;
1260 my $img = $imgs[$index++];
1261 $img->settag(name=>'gif_left', value=>$x);
1262 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1264 $$msg .= "replaced with the gif_left and gif_top tags";
1269 gif_each_palette=>'gif_local_map',
1270 interlace => 'gif_interlace',
1271 gif_delays => 'gif_delay',
1272 gif_positions => \&_fix_gif_positions,
1273 gif_loop_count => 'gif_loop',
1277 my ($self, $opts, $prefix, @imgs) = @_;
1279 for my $opt (keys %$opts) {
1281 if ($obsolete_opts{$opt}) {
1282 my $new = $obsolete_opts{$opt};
1283 my $msg = "Obsolete option $opt ";
1285 $new->($opts, $opt, \$msg, @imgs);
1288 $msg .= "replaced with the $new tag ";
1291 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1292 warn $msg if $warn_obsolete && $^W;
1294 next unless $tagname =~ /^\Q$prefix/;
1295 my $value = $opts->{$opt};
1297 if (UNIVERSAL::isa($value, "Imager::Color")) {
1298 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1299 for my $img (@imgs) {
1300 $img->settag(name=>$tagname, value=>$tag);
1303 elsif (ref($value) eq 'ARRAY') {
1304 for my $i (0..$#$value) {
1305 my $val = $value->[$i];
1307 if (UNIVERSAL::isa($val, "Imager::Color")) {
1308 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1310 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1313 $self->_set_error("Unknown reference type " . ref($value) .
1314 " supplied in array for $opt");
1320 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1325 $self->_set_error("Unknown reference type " . ref($value) .
1326 " supplied for $opt");
1331 # set it as a tag for every image
1332 for my $img (@imgs) {
1333 $img->settag(name=>$tagname, value=>$value);
1341 # Write an image to file
1344 my %input=(jpegquality=>75,
1354 $self->_set_opts(\%input, "i_", $self)
1357 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1359 if (!$input{'type'} and $input{file}) {
1360 $input{'type'}=$FORMATGUESS->($input{file});
1362 if (!$input{'type'}) {
1363 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1367 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1369 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1372 if ($input{'type'} eq 'tiff') {
1373 $self->_set_opts(\%input, "tiff_", $self)
1375 $self->_set_opts(\%input, "exif_", $self)
1378 if (defined $input{class} && $input{class} eq 'fax') {
1379 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1380 $self->{ERRSTR}='Could not write to buffer';
1384 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1385 $self->{ERRSTR}='Could not write to buffer';
1389 } elsif ( $input{'type'} eq 'pnm' ) {
1390 $self->_set_opts(\%input, "pnm_", $self)
1392 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1393 $self->{ERRSTR}='unable to write pnm image';
1396 $self->{DEBUG} && print "writing a pnm file\n";
1397 } elsif ( $input{'type'} eq 'raw' ) {
1398 $self->_set_opts(\%input, "raw_", $self)
1400 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1401 $self->{ERRSTR}='unable to write raw image';
1404 $self->{DEBUG} && print "writing a raw file\n";
1405 } elsif ( $input{'type'} eq 'png' ) {
1406 $self->_set_opts(\%input, "png_", $self)
1408 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1409 $self->{ERRSTR}='unable to write png image';
1412 $self->{DEBUG} && print "writing a png file\n";
1413 } elsif ( $input{'type'} eq 'jpeg' ) {
1414 $self->_set_opts(\%input, "jpeg_", $self)
1416 $self->_set_opts(\%input, "exif_", $self)
1418 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1419 $self->{ERRSTR} = $self->_error_as_msg();
1422 $self->{DEBUG} && print "writing a jpeg file\n";
1423 } elsif ( $input{'type'} eq 'bmp' ) {
1424 $self->_set_opts(\%input, "bmp_", $self)
1426 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1427 $self->{ERRSTR}='unable to write bmp image';
1430 $self->{DEBUG} && print "writing a bmp file\n";
1431 } elsif ( $input{'type'} eq 'tga' ) {
1432 $self->_set_opts(\%input, "tga_", $self)
1435 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1436 $self->{ERRSTR}=$self->_error_as_msg();
1439 $self->{DEBUG} && print "writing a tga file\n";
1440 } elsif ( $input{'type'} eq 'gif' ) {
1441 $self->_set_opts(\%input, "gif_", $self)
1443 # compatibility with the old interfaces
1444 if ($input{gifquant} eq 'lm') {
1445 $input{make_colors} = 'addi';
1446 $input{translate} = 'perturb';
1447 $input{perturb} = $input{lmdither};
1448 } elsif ($input{gifquant} eq 'gen') {
1449 # just pass options through
1451 $input{make_colors} = 'webmap'; # ignored
1452 $input{translate} = 'giflib';
1454 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1455 $self->{ERRSTR} = $self->_error_as_msg;
1460 if (exists $input{'data'}) {
1461 my $data = io_slurp($IO);
1463 $self->{ERRSTR}='Could not slurp from buffer';
1466 ${$input{data}} = $data;
1472 my ($class, $opts, @images) = @_;
1474 if (!$opts->{'type'} && $opts->{'file'}) {
1475 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1477 unless ($opts->{'type'}) {
1478 $class->_set_error('type parameter missing and not possible to guess from extension');
1481 # translate to ImgRaw
1482 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1483 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1486 $class->_set_opts($opts, "i_", @images)
1488 my @work = map $_->{IMG}, @images;
1489 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1491 if ($opts->{'type'} eq 'gif') {
1492 $class->_set_opts($opts, "gif_", @images)
1494 my $gif_delays = $opts->{gif_delays};
1495 local $opts->{gif_delays} = $gif_delays;
1496 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1497 # assume the caller wants the same delay for each frame
1498 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1500 my $res = i_writegif_wiol($IO, $opts, @work);
1501 $res or $class->_set_error($class->_error_as_msg());
1504 elsif ($opts->{'type'} eq 'tiff') {
1505 $class->_set_opts($opts, "tiff_", @images)
1507 $class->_set_opts($opts, "exif_", @images)
1510 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1511 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1512 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1515 $res = i_writetiff_multi_wiol($IO, @work);
1517 $res or $class->_set_error($class->_error_as_msg());
1521 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1526 # read multiple images from a file
1528 my ($class, %opts) = @_;
1530 if ($opts{file} && !exists $opts{'type'}) {
1532 my $type = $FORMATGUESS->($opts{file});
1533 $opts{'type'} = $type;
1535 unless ($opts{'type'}) {
1536 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1540 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1542 if ($opts{'type'} eq 'gif') {
1544 @imgs = i_readgif_multi_wiol($IO);
1547 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1551 $ERRSTR = _error_as_msg();
1555 elsif ($opts{'type'} eq 'tiff') {
1556 my @imgs = i_readtiff_multi_wiol($IO, -1);
1559 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1563 $ERRSTR = _error_as_msg();
1568 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1572 # Destroy an Imager object
1576 # delete $instances{$self};
1577 if (defined($self->{IMG})) {
1578 # the following is now handled by the XS DESTROY method for
1579 # Imager::ImgRaw object
1580 # Re-enabling this will break virtual images
1581 # tested for in t/t020masked.t
1582 # i_img_destroy($self->{IMG});
1583 undef($self->{IMG});
1585 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1589 # Perform an inplace filter of an image
1590 # that is the image will be overwritten with the data
1596 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1598 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1600 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1601 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1604 if ($filters{$input{'type'}}{names}) {
1605 my $names = $filters{$input{'type'}}{names};
1606 for my $name (keys %$names) {
1607 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1608 $input{$name} = $names->{$name}{$input{$name}};
1612 if (defined($filters{$input{'type'}}{defaults})) {
1613 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1615 %hsh=('image',$self->{IMG},%input);
1618 my @cs=@{$filters{$input{'type'}}{callseq}};
1621 if (!defined($hsh{$_})) {
1622 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1627 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1628 &{$filters{$input{'type'}}{callsub}}(%hsh);
1631 chomp($self->{ERRSTR} = $@);
1637 $self->{DEBUG} && print "callseq is: @cs\n";
1638 $self->{DEBUG} && print "matching callseq is: @b\n";
1643 # Scale an image to requested size and return the scaled version
1647 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1648 my $img = Imager->new();
1649 my $tmp = Imager->new();
1651 unless (defined wantarray) {
1652 my @caller = caller;
1653 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1657 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1659 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1660 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1661 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1662 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1663 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1664 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1666 if ($opts{qtype} eq 'normal') {
1667 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1668 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1669 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1670 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1673 if ($opts{'qtype'} eq 'preview') {
1674 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1675 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1678 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1681 # Scales only along the X axis
1685 my %opts=(scalefactor=>0.5,@_);
1687 unless (defined wantarray) {
1688 my @caller = caller;
1689 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1693 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1695 my $img = Imager->new();
1697 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1699 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1700 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1702 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1706 # Scales only along the Y axis
1710 my %opts=(scalefactor=>0.5,@_);
1712 unless (defined wantarray) {
1713 my @caller = caller;
1714 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1718 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1720 my $img = Imager->new();
1722 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1724 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1725 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1727 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1732 # Transform returns a spatial transformation of the input image
1733 # this moves pixels to a new location in the returned image.
1734 # NOTE - should make a utility function to check transforms for
1739 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1741 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1743 # print Dumper(\%opts);
1746 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1748 eval ("use Affix::Infix2Postfix;");
1751 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1754 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1755 {op=>'-',trans=>'Sub'},
1756 {op=>'*',trans=>'Mult'},
1757 {op=>'/',trans=>'Div'},
1758 {op=>'-','type'=>'unary',trans=>'u-'},
1760 {op=>'func','type'=>'unary'}],
1761 'grouping'=>[qw( \( \) )],
1762 'func'=>[qw( sin cos )],
1767 @xt=$I2P->translate($opts{'xexpr'});
1768 @yt=$I2P->translate($opts{'yexpr'});
1770 $numre=$I2P->{'numre'};
1773 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1774 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1775 @{$opts{'parm'}}=@pt;
1778 # print Dumper(\%opts);
1780 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1781 $self->{ERRSTR}='transform: no xopcodes given.';
1785 @op=@{$opts{'xopcodes'}};
1787 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1788 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1791 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1797 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1798 $self->{ERRSTR}='transform: no yopcodes given.';
1802 @op=@{$opts{'yopcodes'}};
1804 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1805 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1808 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1813 if ( !exists $opts{'parm'}) {
1814 $self->{ERRSTR}='transform: no parameter arg given.';
1818 # print Dumper(\@ropx);
1819 # print Dumper(\@ropy);
1820 # print Dumper(\@ropy);
1822 my $img = Imager->new();
1823 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1824 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1830 my ($opts, @imgs) = @_;
1832 require "Imager/Expr.pm";
1834 $opts->{variables} = [ qw(x y) ];
1835 my ($width, $height) = @{$opts}{qw(width height)};
1837 $width ||= $imgs[0]->getwidth();
1838 $height ||= $imgs[0]->getheight();
1840 for my $img (@imgs) {
1841 $opts->{constants}{"w$img_num"} = $img->getwidth();
1842 $opts->{constants}{"h$img_num"} = $img->getheight();
1843 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1844 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1849 $opts->{constants}{w} = $width;
1850 $opts->{constants}{cx} = $width/2;
1853 $Imager::ERRSTR = "No width supplied";
1857 $opts->{constants}{h} = $height;
1858 $opts->{constants}{cy} = $height/2;
1861 $Imager::ERRSTR = "No height supplied";
1864 my $code = Imager::Expr->new($opts);
1866 $Imager::ERRSTR = Imager::Expr::error();
1869 my $channels = $opts->{channels} || 3;
1870 unless ($channels >= 1 && $channels <= 4) {
1871 return Imager->_set_error("channels must be an integer between 1 and 4");
1874 my $img = Imager->new();
1875 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1876 $channels, $code->code(),
1877 $code->nregs(), $code->cregs(),
1878 [ map { $_->{IMG} } @imgs ]);
1879 if (!defined $img->{IMG}) {
1880 $Imager::ERRSTR = Imager->_error_as_msg();
1889 my %opts=(tx => 0,ty => 0, @_);
1891 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1892 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1894 %opts = (src_minx => 0,
1896 src_maxx => $opts{src}->getwidth(),
1897 src_maxy => $opts{src}->getheight(),
1900 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1901 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1902 $self->{ERRSTR} = $self->_error_as_msg();
1912 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
1914 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
1915 $dir = $xlate{$opts{'dir'}};
1916 return $self if i_flipxy($self->{IMG}, $dir);
1924 unless (defined wantarray) {
1925 my @caller = caller;
1926 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
1930 if (defined $opts{right}) {
1931 my $degrees = $opts{right};
1933 $degrees += 360 * int(((-$degrees)+360)/360);
1935 $degrees = $degrees % 360;
1936 if ($degrees == 0) {
1937 return $self->copy();
1939 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
1940 my $result = Imager->new();
1941 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
1945 $self->{ERRSTR} = $self->_error_as_msg();
1950 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
1954 elsif (defined $opts{radians} || defined $opts{degrees}) {
1955 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
1957 my $result = Imager->new;
1959 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
1962 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
1964 if ($result->{IMG}) {
1968 $self->{ERRSTR} = $self->_error_as_msg();
1973 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
1978 sub matrix_transform {
1982 unless (defined wantarray) {
1983 my @caller = caller;
1984 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
1988 if ($opts{matrix}) {
1989 my $xsize = $opts{xsize} || $self->getwidth;
1990 my $ysize = $opts{ysize} || $self->getheight;
1992 my $result = Imager->new;
1994 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1995 $opts{matrix}, $opts{back})
1999 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2007 $self->{ERRSTR} = "matrix parameter required";
2013 *yatf = \&matrix_transform;
2015 # These two are supported for legacy code only
2018 return Imager::Color->new(@_);
2022 return Imager::Color::set(@_);
2025 # Draws a box between the specified corner points.
2028 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2029 my $dflcl=i_color_new(255,255,255,255);
2030 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2032 if (exists $opts{'box'}) {
2033 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
2034 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
2035 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
2036 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
2039 if ($opts{filled}) {
2040 my $color = _color($opts{'color'});
2042 $self->{ERRSTR} = $Imager::ERRSTR;
2045 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2046 $opts{ymax}, $color);
2048 elsif ($opts{fill}) {
2049 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2050 # assume it's a hash ref
2051 require 'Imager/Fill.pm';
2052 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2053 $self->{ERRSTR} = $Imager::ERRSTR;
2057 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2058 $opts{ymax},$opts{fill}{fill});
2061 my $color = _color($opts{'color'});
2063 $self->{ERRSTR} = $Imager::ERRSTR;
2066 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2072 # Draws an arc - this routine SUCKS and is buggy - it sometimes doesn't work when the arc is a convex polygon
2076 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2077 my $dflcl=i_color_new(255,255,255,255);
2078 my %opts=(color=>$dflcl,
2079 'r'=>min($self->getwidth(),$self->getheight())/3,
2080 'x'=>$self->getwidth()/2,
2081 'y'=>$self->getheight()/2,
2082 'd1'=>0, 'd2'=>361, @_);
2084 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2085 # assume it's a hash ref
2086 require 'Imager/Fill.pm';
2087 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2088 $self->{ERRSTR} = $Imager::ERRSTR;
2092 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2093 $opts{'d2'}, $opts{fill}{fill});
2096 my $color = _color($opts{'color'});
2098 $self->{ERRSTR} = $Imager::ERRSTR;
2101 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2102 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2106 if ($opts{'d1'} <= $opts{'d2'}) {
2107 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2108 $opts{'d1'}, $opts{'d2'}, $color);
2111 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2112 $opts{'d1'}, 361, $color);
2113 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2114 0, $opts{'d2'}, $color);
2122 # Draws a line from one point to the other
2123 # the endpoint is set if the endp parameter is set which it is by default.
2124 # to turn of the endpoint being set use endp=>0 when calling line.
2128 my $dflcl=i_color_new(0,0,0,0);
2129 my %opts=(color=>$dflcl,
2132 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2134 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2135 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2137 my $color = _color($opts{'color'});
2139 $self->{ERRSTR} = $Imager::ERRSTR;
2143 $opts{antialias} = $opts{aa} if defined $opts{aa};
2144 if ($opts{antialias}) {
2145 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2146 $color, $opts{endp});
2148 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2149 $color, $opts{endp});
2154 # Draws a line between an ordered set of points - It more or less just transforms this
2155 # into a list of lines.
2159 my ($pt,$ls,@points);
2160 my $dflcl=i_color_new(0,0,0,0);
2161 my %opts=(color=>$dflcl,@_);
2163 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2165 if (exists($opts{points})) { @points=@{$opts{points}}; }
2166 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2167 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2170 # print Dumper(\@points);
2172 my $color = _color($opts{'color'});
2174 $self->{ERRSTR} = $Imager::ERRSTR;
2177 $opts{antialias} = $opts{aa} if defined $opts{aa};
2178 if ($opts{antialias}) {
2181 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2188 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2198 my ($pt,$ls,@points);
2199 my $dflcl = i_color_new(0,0,0,0);
2200 my %opts = (color=>$dflcl, @_);
2202 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2204 if (exists($opts{points})) {
2205 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2206 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2209 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2210 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2213 if ($opts{'fill'}) {
2214 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2215 # assume it's a hash ref
2216 require 'Imager/Fill.pm';
2217 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2218 $self->{ERRSTR} = $Imager::ERRSTR;
2222 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2223 $opts{'fill'}{'fill'});
2226 my $color = _color($opts{'color'});
2228 $self->{ERRSTR} = $Imager::ERRSTR;
2231 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2238 # this the multipoint bezier curve
2239 # this is here more for testing that actual usage since
2240 # this is not a good algorithm. Usually the curve would be
2241 # broken into smaller segments and each done individually.
2245 my ($pt,$ls,@points);
2246 my $dflcl=i_color_new(0,0,0,0);
2247 my %opts=(color=>$dflcl,@_);
2249 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2251 if (exists $opts{points}) {
2252 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2253 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2256 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2257 $self->{ERRSTR}='Missing or invalid points.';
2261 my $color = _color($opts{'color'});
2263 $self->{ERRSTR} = $Imager::ERRSTR;
2266 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2272 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2275 unless (exists $opts{'x'} && exists $opts{'y'}) {
2276 $self->{ERRSTR} = "missing seed x and y parameters";
2281 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2282 # assume it's a hash ref
2283 require 'Imager/Fill.pm';
2284 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2285 $self->{ERRSTR} = $Imager::ERRSTR;
2289 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2292 my $color = _color($opts{'color'});
2294 $self->{ERRSTR} = $Imager::ERRSTR;
2297 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2299 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2305 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2307 unless (exists $opts{'x'} && exists $opts{'y'}) {
2308 $self->{ERRSTR} = 'missing x and y parameters';
2314 my $color = _color($opts{color})
2316 if (ref $x && ref $y) {
2317 unless (@$x == @$y) {
2318 $self->{ERRSTR} = 'length of x and y mismatch';
2321 if ($color->isa('Imager::Color')) {
2322 for my $i (0..$#{$opts{'x'}}) {
2323 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2327 for my $i (0..$#{$opts{'x'}}) {
2328 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2333 if ($color->isa('Imager::Color')) {
2334 i_ppix($self->{IMG}, $x, $y, $color);
2337 i_ppixf($self->{IMG}, $x, $y, $color);
2347 my %opts = ( "type"=>'8bit', @_);
2349 unless (exists $opts{'x'} && exists $opts{'y'}) {
2350 $self->{ERRSTR} = 'missing x and y parameters';
2356 if (ref $x && ref $y) {
2357 unless (@$x == @$y) {
2358 $self->{ERRSTR} = 'length of x and y mismatch';
2362 if ($opts{"type"} eq '8bit') {
2363 for my $i (0..$#{$opts{'x'}}) {
2364 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2368 for my $i (0..$#{$opts{'x'}}) {
2369 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2372 return wantarray ? @result : \@result;
2375 if ($opts{"type"} eq '8bit') {
2376 return i_get_pixel($self->{IMG}, $x, $y);
2379 return i_gpixf($self->{IMG}, $x, $y);
2388 my %opts = ( type => '8bit', x=>0, @_);
2390 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2392 unless (defined $opts{'y'}) {
2393 $self->_set_error("missing y parameter");
2397 if ($opts{type} eq '8bit') {
2398 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2401 elsif ($opts{type} eq 'float') {
2402 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2406 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2413 my %opts = ( x=>0, @_);
2415 unless (defined $opts{'y'}) {
2416 $self->_set_error("missing y parameter");
2421 if (ref $opts{pixels} && @{$opts{pixels}}) {
2422 # try to guess the type
2423 if ($opts{pixels}[0]->isa('Imager::Color')) {
2424 $opts{type} = '8bit';
2426 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2427 $opts{type} = 'float';
2430 $self->_set_error("missing type parameter and could not guess from pixels");
2436 $opts{type} = '8bit';
2440 if ($opts{type} eq '8bit') {
2441 if (ref $opts{pixels}) {
2442 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2445 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2448 elsif ($opts{type} eq 'float') {
2449 if (ref $opts{pixels}) {
2450 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2453 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2457 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2464 my %opts = ( type => '8bit', x=>0, @_);
2466 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2468 unless (defined $opts{'y'}) {
2469 $self->_set_error("missing y parameter");
2473 unless ($opts{channels}) {
2474 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2477 if ($opts{type} eq '8bit') {
2478 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2479 $opts{y}, @{$opts{channels}});
2481 elsif ($opts{type} eq 'float') {
2482 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2483 $opts{y}, @{$opts{channels}});
2486 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2491 # make an identity matrix of the given size
2495 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2496 for my $c (0 .. ($size-1)) {
2497 $matrix->[$c][$c] = 1;
2502 # general function to convert an image
2504 my ($self, %opts) = @_;
2507 unless (defined wantarray) {
2508 my @caller = caller;
2509 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2513 # the user can either specify a matrix or preset
2514 # the matrix overrides the preset
2515 if (!exists($opts{matrix})) {
2516 unless (exists($opts{preset})) {
2517 $self->{ERRSTR} = "convert() needs a matrix or preset";
2521 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2522 # convert to greyscale, keeping the alpha channel if any
2523 if ($self->getchannels == 3) {
2524 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2526 elsif ($self->getchannels == 4) {
2527 # preserve the alpha channel
2528 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2533 $matrix = _identity($self->getchannels);
2536 elsif ($opts{preset} eq 'noalpha') {
2537 # strip the alpha channel
2538 if ($self->getchannels == 2 or $self->getchannels == 4) {
2539 $matrix = _identity($self->getchannels);
2540 pop(@$matrix); # lose the alpha entry
2543 $matrix = _identity($self->getchannels);
2546 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2548 $matrix = [ [ 1 ] ];
2550 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2551 $matrix = [ [ 0, 1 ] ];
2553 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2554 $matrix = [ [ 0, 0, 1 ] ];
2556 elsif ($opts{preset} eq 'alpha') {
2557 if ($self->getchannels == 2 or $self->getchannels == 4) {
2558 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2561 # the alpha is just 1 <shrug>
2562 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2565 elsif ($opts{preset} eq 'rgb') {
2566 if ($self->getchannels == 1) {
2567 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2569 elsif ($self->getchannels == 2) {
2570 # preserve the alpha channel
2571 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2574 $matrix = _identity($self->getchannels);
2577 elsif ($opts{preset} eq 'addalpha') {
2578 if ($self->getchannels == 1) {
2579 $matrix = _identity(2);
2581 elsif ($self->getchannels == 3) {
2582 $matrix = _identity(4);
2585 $matrix = _identity($self->getchannels);
2589 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2595 $matrix = $opts{matrix};
2598 my $new = Imager->new();
2599 $new->{IMG} = i_img_new();
2600 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2601 # most likely a bad matrix
2602 $self->{ERRSTR} = _error_as_msg();
2609 # general function to map an image through lookup tables
2612 my ($self, %opts) = @_;
2613 my @chlist = qw( red green blue alpha );
2615 if (!exists($opts{'maps'})) {
2616 # make maps from channel maps
2618 for $chnum (0..$#chlist) {
2619 if (exists $opts{$chlist[$chnum]}) {
2620 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2621 } elsif (exists $opts{'all'}) {
2622 $opts{'maps'}[$chnum] = $opts{'all'};
2626 if ($opts{'maps'} and $self->{IMG}) {
2627 i_map($self->{IMG}, $opts{'maps'} );
2633 my ($self, %opts) = @_;
2635 defined $opts{mindist} or $opts{mindist} = 0;
2637 defined $opts{other}
2638 or return $self->_set_error("No 'other' parameter supplied");
2639 defined $opts{other}{IMG}
2640 or return $self->_set_error("No image data in 'other' image");
2643 or return $self->_set_error("No image data");
2645 my $result = Imager->new;
2646 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2648 or return $self->_set_error($self->_error_as_msg());
2653 # destructive border - image is shrunk by one pixel all around
2656 my ($self,%opts)=@_;
2657 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2658 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2662 # Get the width of an image
2666 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2667 return (i_img_info($self->{IMG}))[0];
2670 # Get the height of an image
2674 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2675 return (i_img_info($self->{IMG}))[1];
2678 # Get number of channels in an image
2682 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2683 return i_img_getchannels($self->{IMG});
2690 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2691 return i_img_getmask($self->{IMG});
2699 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2700 i_img_setmask( $self->{IMG} , $opts{mask} );
2703 # Get number of colors in an image
2707 my %opts=('maxcolors'=>2**30,@_);
2708 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2709 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2710 return ($rc==-1? undef : $rc);
2713 # draw string to an image
2717 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2719 my %input=('x'=>0, 'y'=>0, @_);
2720 $input{string}||=$input{text};
2722 unless(exists $input{string}) {
2723 $self->{ERRSTR}="missing required parameter 'string'";
2727 unless($input{font}) {
2728 $self->{ERRSTR}="missing required parameter 'font'";
2732 unless ($input{font}->draw(image=>$self, %input)) {
2733 $self->{ERRSTR} = $self->_error_as_msg();
2740 my @file_limit_names = qw/width height bytes/;
2742 sub set_file_limits {
2749 @values{@file_limit_names} = (0) x @file_limit_names;
2752 @values{@file_limit_names} = i_get_image_file_limits();
2755 for my $key (keys %values) {
2756 defined $opts{$key} and $values{$key} = $opts{$key};
2759 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
2762 sub get_file_limits {
2763 i_get_image_file_limits();
2766 # Shortcuts that can be exported
2768 sub newcolor { Imager::Color->new(@_); }
2769 sub newfont { Imager::Font->new(@_); }
2771 *NC=*newcolour=*newcolor;
2778 #### Utility routines
2781 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2785 my ($self, $msg) = @_;
2788 $self->{ERRSTR} = $msg;
2796 # Default guess for the type of an image from extension
2798 sub def_guess_type {
2801 $ext=($name =~ m/\.([^\.]+)$/)[0];
2802 return 'tiff' if ($ext =~ m/^tiff?$/);
2803 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2804 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2805 return 'png' if ($ext eq "png");
2806 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2807 return 'tga' if ($ext eq "tga");
2808 return 'rgb' if ($ext eq "rgb");
2809 return 'gif' if ($ext eq "gif");
2810 return 'raw' if ($ext eq "raw");
2814 # get the minimum of a list
2818 for(@_) { if ($_<$mx) { $mx=$_; }}
2822 # get the maximum of a list
2826 for(@_) { if ($_>$mx) { $mx=$_; }}
2830 # string stuff for iptc headers
2834 $str = substr($str,3);
2835 $str =~ s/[\n\r]//g;
2842 # A little hack to parse iptc headers.
2847 my($caption,$photogr,$headln,$credit);
2849 my $str=$self->{IPTCRAW};
2853 @ar=split(/8BIM/,$str);
2858 @sar=split(/\034\002/);
2859 foreach $item (@sar) {
2860 if ($item =~ m/^x/) {
2861 $caption=&clean($item);
2864 if ($item =~ m/^P/) {
2865 $photogr=&clean($item);
2868 if ($item =~ m/^i/) {
2869 $headln=&clean($item);
2872 if ($item =~ m/^n/) {
2873 $credit=&clean($item);
2879 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
2882 # Autoload methods go after =cut, and are processed by the autosplit program.
2886 # Below is the stub of documentation for your module. You better edit it!
2890 Imager - Perl extension for Generating 24 bit Images
2900 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
2905 my $img = Imager->new();
2906 # see Imager::Files for information on the read() method
2907 $img->read(file=>$file) or die $img->errstr();
2909 $file =~ s/\.[^.]*$//;
2911 # Create smaller version
2912 # documented in Imager::Transformations
2913 my $thumb = $img->scale(scalefactor=>.3);
2915 # Autostretch individual channels
2916 $thumb->filter(type=>'autolevels');
2918 # try to save in one of these formats
2921 for $format ( qw( png gif jpg tiff ppm ) ) {
2922 # Check if given format is supported
2923 if ($Imager::formats{$format}) {
2924 $file.="_low.$format";
2925 print "Storing image as: $file\n";
2926 # documented in Imager::Files
2927 $thumb->write(file=>$file) or
2935 Imager is a module for creating and altering images. It can read and
2936 write various image formats, draw primitive shapes like lines,and
2937 polygons, blend multiple images together in various ways, scale, crop,
2938 render text and more.
2940 =head2 Overview of documentation
2946 Imager - This document - Synopsis Example, Table of Contents and
2951 L<Imager::Cookbook> - how to do various things with Imager.
2955 L<Imager::ImageTypes> - Basics of constructing image objects with
2956 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
2957 8/16/double bits/channel, color maps, channel masks, image tags, color
2958 quantization. Also discusses basic image information methods.
2962 L<Imager::Files> - IO interaction, reading/writing images, format
2967 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
2972 L<Imager::Color> - Color specification.
2976 L<Imager::Fill> - Fill pattern specification.
2980 L<Imager::Font> - General font rendering, bounding boxes and font
2985 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
2986 blending, pasting, convert and map.
2990 L<Imager::Engines> - Programmable transformations through
2991 C<transform()>, C<transform2()> and C<matrix_transform()>.
2995 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3000 L<Imager::Expr> - Expressions for evaluation engine used by
3005 L<Imager::Matrix2d> - Helper class for affine transformations.
3009 L<Imager::Fountain> - Helper for making gradient profiles.
3013 =head2 Basic Overview
3015 An Image object is created with C<$img = Imager-E<gt>new()>.
3018 $img=Imager->new(); # create empty image
3019 $img->read(file=>'lena.png',type=>'png') or # read image from file
3020 die $img->errstr(); # give an explanation
3021 # if something failed
3023 or if you want to create an empty image:
3025 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3027 This example creates a completely black image of width 400 and height
3030 When an operation fails which can be directly associated with an image
3031 the error message is stored can be retrieved with
3032 C<$img-E<gt>errstr()>.
3034 In cases where no image object is associated with an operation
3035 C<$Imager::ERRSTR> is used to report errors not directly associated
3036 with an image object. You can also call C<Imager->errstr> to get this
3039 The C<Imager-E<gt>new> method is described in detail in
3040 L<Imager::ImageTypes>.
3044 Where to find information on methods for Imager class objects.
3046 addcolors() - L<Imager::ImageTypes>
3048 addtag() - L<Imager::ImageTypes> - add image tags
3050 arc() - L<Imager::Draw/arc>
3052 bits() - L<Imager::ImageTypes> - number of bits per sample for the
3055 box() - L<Imager::Draw/box>
3057 circle() - L<Imager::Draw/circle>
3059 colorcount() - L<Imager::Draw/colorcount>
3061 convert() - L<Imager::Transformations/"Color transformations"> -
3062 transform the color space
3064 copy() - L<Imager::Transformations/copy>
3066 crop() - L<Imager::Transformations/crop> - extract part of an image
3068 deltag() - L<Imager::ImageTypes> - delete image tags
3070 difference() - L<Imager::Filters/"Image Difference">
3072 errstr() - L<Imager/"Basic Overview">
3074 filter() - L<Imager::Filters>
3076 findcolor() - L<Imager::ImageTypes> - search the image palette, if it
3079 flip() - L<Imager::Transformations/flip>
3081 flood_fill() - L<Imager::Draw/flood_fill>
3083 getchannels() - L<Imager::ImageTypes>
3085 getcolorcount() - L<Imager::ImageTypes>
3087 getcolors() - L<Imager::ImageTypes> - get colors from the image
3088 palette, if it has one
3090 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3092 getheight() - L<Imager::ImageTypes>
3094 getpixel() - L<Imager::Draw/setpixel and getpixel>
3096 getsamples() - L<Imager::Draw/getsamples>
3098 getscanline() - L<Imager::Draw/getscanline>
3100 getwidth() - L<Imager::ImageTypes>
3102 img_set() - L<Imager::ImageTypes>
3104 line() - L<Imager::Draw/line>
3106 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3109 masked() - L<Imager::ImageTypes> - make a masked image
3111 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
3113 maxcolors() - L<Imager::ImageTypes/maxcolor>
3115 new() - L<Imager::ImageTypes>
3117 open() - L<Imager::Files> - an alias for read()
3119 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3121 polygon() - L<Imager::Draw/polygon>
3123 polyline() - L<Imager::Draw/polyline>
3125 read() - L<Imager::Files> - read a single image from an image file
3127 read_multi() - L<Imager::Files> - read multiple images from an image
3130 rotate() - L<Imager::Transformations/rotate>
3132 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3133 image and use the alpha channel
3135 scale() - L<Imager::Transformations/scale>
3137 setscanline() - L<Imager::Draw/setscanline>
3139 scaleX() - L<Imager::Transformations/scaleX>
3141 scaleY() - L<Imager::Transformations/scaleY>
3143 setcolors() - L<Imager::ImageTypes> - set palette colors in a paletted image
3145 setpixel() - L<Imager::Draw/setpixel and getpixel>
3147 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3149 string() - L<Imager::Font/string> - draw text on an image
3151 tags() - L<Imager::ImageTypes> - fetch image tags
3153 to_paletted() - L<Imager::ImageTypes>
3155 to_rgb8() - L<Imager::ImageTypes>
3157 transform() - L<Imager::Engines/"transform">
3159 transform2() - L<Imager::Engines/"transform2">
3161 type() - L<Imager::ImageTypes> - type of image (direct vs paletted)
3163 virtual() - L<Imager::ImageTypes> - whether the image has it's own
3166 write() - L<Imager::Files> - write an image to a file
3168 write_multi() - L<Imager::Files> - write multiple image to an image
3171 =head1 CONCEPT INDEX
3173 animated GIF - L<Imager::File/"Writing an animated GIF">
3175 aspect ratio - L<Imager::ImageTypes/i_xres>,
3176 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3178 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3180 boxes, drawing - L<Imager::Draw/box>
3182 color - L<Imager::Color>
3184 color names - L<Imager::Color>, L<Imager::Color::Table>
3186 combine modes - L<Imager::Fill/combine>
3188 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3190 convolution - L<Imager::Filter/conv>
3192 cropping - L<Imager::Transformations/crop>
3194 dpi - L<Imager::ImageTypes/i_xres>
3196 drawing boxes - L<Imager::Draw/box>
3198 drawing lines - L<Imager::Draw/line>
3200 drawing text - L<Imager::Font/string>
3202 error message - L<Imager/"Basic Overview">
3204 files, font - L<Imager::Font>
3206 files, image - L<Imager::Files>
3208 filling, types of fill - L<Imager::Fill>
3210 filling, boxes - L<Imager::Draw/box>
3212 filling, flood fill - L<Imager::Draw/flood_fill>
3214 flood fill - L<Imager::Draw/flood_fill>
3216 fonts - L<Imager::Font>
3218 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3219 L<Imager::Font::Wrap>
3221 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3223 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3225 fountain fill - L<Imager::Fill/"Fountain fills">,
3226 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3227 L<Imager::Filters/gradgen>
3229 GIF files - L<Imager::Files/"GIF">
3231 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3233 gradient fill - L<Imager::Fill/"Fountain fills">,
3234 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3235 L<Imager::Filters/gradgen>
3237 guassian blur - L<Imager::Filter/guassian>
3239 hatch fills - L<Imager::Fill/"Hatched fills">
3241 invert image - L<Imager::Filter/hardinvert>
3243 JPEG - L<Imager::Files/"JPEG">
3245 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3247 lines, drawing - L<Imager::Draw/line>
3249 matrix - L<Imager::Matrix2d>,
3250 L<Imager::Transformations/"Matrix Transformations">,
3251 L<Imager::Font/transform>
3253 metadata, image - L<Imager::ImageTypes/"Tags">
3255 mosaic - L<Imager::Filter/mosaic>
3257 noise, filter - L<Imager::Filter/noise>
3259 noise, rendered - L<Imager::Filter/turbnoise>,
3260 L<Imager::Filter/radnoise>
3262 posterize - L<Imager::Filter/postlevels>
3264 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3266 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3268 rectangles, drawing - L<Imager::Draw/box>
3270 resizing an image - L<Imager::Transformations/scale>,
3271 L<Imager::Transformations/crop>
3273 saving an image - L<Imager::Files>
3275 scaling - L<Imager::Transformations/scale>
3277 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3279 size, image - L<Imager::ImageTypes/getwidth>,
3280 L<Imager::ImageTypes/getheight>
3282 size, text - L<Imager::Font/bounding_box>
3284 text, drawing - L<Imager::Font/string>, L<Imager::Font/align>,
3285 L<Imager::Font::Wrap>
3287 text, wrapping text in an area - L<Imager::Font::Wrap>
3289 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3291 tiles, color - L<Imager::Filter/mosaic>
3293 unsharp mask - L<Imager::Filter/unsharpmask>
3295 watermark - L<Imager::Filter/watermark>
3297 writing an image - L<Imager::Files>
3301 You can ask for help, report bugs or express your undying love for
3302 Imager on the Imager-devel mailing list.
3304 To subscribe send a message with C<subscribe> in the body to:
3306 imager-devel+request@molar.is
3310 http://www.molar.is/en/lists/imager-devel/
3311 (annonymous is temporarily off due to spam)
3313 where you can also find the mailing list archive.
3315 If you're into IRC, you can typically find the developers in #Imager
3316 on irc.perl.org. As with any IRC channel, the participants could be
3317 occupied or asleep, so please be patient.
3319 You can report bugs by pointing your browser at:
3321 https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager
3323 Please remember to include the versions of Imager, perl, supporting
3324 libraries, and any relevant code. If you have specific images that
3325 cause the problems, please include those too.
3329 Bugs are listed individually for relevant pod pages.
3333 Arnar M. Hrafnkelsson (addi@imager.perl.org) and Tony Cook
3334 (tony@imager.perl.org) See the README for a complete list.
3338 perl(1), Imager::ImageTypes(3), Imager::Files(3), Imager::Draw(3),
3339 Imager::Color(3), Imager::Fill(3), Imager::Font(3),
3340 Imager::Transformations(3), Imager::Engines(3), Imager::Filters(3),
3341 Imager::Expr(3), Imager::Matrix2d(3), Imager::Fountain(3)
3343 Affix::Infix2Postfix(3), Parse::RecDescent(3)
3344 http://imager.perl.org/