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{colors}) {
1198 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1200 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1204 $self->{IMG} =i_readgif_wiol( $IO );
1206 if ( !defined($self->{IMG}) ) {
1207 $self->{ERRSTR}=$self->_error_as_msg();
1210 $self->{DEBUG} && print "loading a gif file\n";
1213 if ( $input{'type'} eq 'tga' ) {
1214 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1215 if ( !defined($self->{IMG}) ) {
1216 $self->{ERRSTR}=$self->_error_as_msg();
1219 $self->{DEBUG} && print "loading a tga file\n";
1222 if ( $input{'type'} eq 'rgb' ) {
1223 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1224 if ( !defined($self->{IMG}) ) {
1225 $self->{ERRSTR}=$self->_error_as_msg();
1228 $self->{DEBUG} && print "loading a tga file\n";
1232 if ( $input{'type'} eq 'raw' ) {
1233 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1235 if ( !($params{xsize} && $params{ysize}) ) {
1236 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1240 $self->{IMG} = i_readraw_wiol( $IO,
1243 $params{datachannels},
1244 $params{storechannels},
1245 $params{interleave});
1246 if ( !defined($self->{IMG}) ) {
1247 $self->{ERRSTR}='unable to read raw image';
1250 $self->{DEBUG} && print "loading a raw file\n";
1256 sub _fix_gif_positions {
1257 my ($opts, $opt, $msg, @imgs) = @_;
1259 my $positions = $opts->{'gif_positions'};
1261 for my $pos (@$positions) {
1262 my ($x, $y) = @$pos;
1263 my $img = $imgs[$index++];
1264 $img->settag(name=>'gif_left', value=>$x);
1265 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1267 $$msg .= "replaced with the gif_left and gif_top tags";
1272 gif_each_palette=>'gif_local_map',
1273 interlace => 'gif_interlace',
1274 gif_delays => 'gif_delay',
1275 gif_positions => \&_fix_gif_positions,
1276 gif_loop_count => 'gif_loop',
1280 my ($self, $opts, $prefix, @imgs) = @_;
1282 for my $opt (keys %$opts) {
1284 if ($obsolete_opts{$opt}) {
1285 my $new = $obsolete_opts{$opt};
1286 my $msg = "Obsolete option $opt ";
1288 $new->($opts, $opt, \$msg, @imgs);
1291 $msg .= "replaced with the $new tag ";
1294 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1295 warn $msg if $warn_obsolete && $^W;
1297 next unless $tagname =~ /^\Q$prefix/;
1298 my $value = $opts->{$opt};
1300 if (UNIVERSAL::isa($value, "Imager::Color")) {
1301 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1302 for my $img (@imgs) {
1303 $img->settag(name=>$tagname, value=>$tag);
1306 elsif (ref($value) eq 'ARRAY') {
1307 for my $i (0..$#$value) {
1308 my $val = $value->[$i];
1310 if (UNIVERSAL::isa($val, "Imager::Color")) {
1311 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1313 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1316 $self->_set_error("Unknown reference type " . ref($value) .
1317 " supplied in array for $opt");
1323 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1328 $self->_set_error("Unknown reference type " . ref($value) .
1329 " supplied for $opt");
1334 # set it as a tag for every image
1335 for my $img (@imgs) {
1336 $img->settag(name=>$tagname, value=>$value);
1344 # Write an image to file
1347 my %input=(jpegquality=>75,
1357 $self->_set_opts(\%input, "i_", $self)
1360 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1362 if (!$input{'type'} and $input{file}) {
1363 $input{'type'}=$FORMATGUESS->($input{file});
1365 if (!$input{'type'}) {
1366 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1370 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1372 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1375 if ($input{'type'} eq 'tiff') {
1376 $self->_set_opts(\%input, "tiff_", $self)
1378 $self->_set_opts(\%input, "exif_", $self)
1381 if (defined $input{class} && $input{class} eq 'fax') {
1382 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1383 $self->{ERRSTR}='Could not write to buffer';
1387 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1388 $self->{ERRSTR}='Could not write to buffer';
1392 } elsif ( $input{'type'} eq 'pnm' ) {
1393 $self->_set_opts(\%input, "pnm_", $self)
1395 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1396 $self->{ERRSTR}='unable to write pnm image';
1399 $self->{DEBUG} && print "writing a pnm file\n";
1400 } elsif ( $input{'type'} eq 'raw' ) {
1401 $self->_set_opts(\%input, "raw_", $self)
1403 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1404 $self->{ERRSTR}='unable to write raw image';
1407 $self->{DEBUG} && print "writing a raw file\n";
1408 } elsif ( $input{'type'} eq 'png' ) {
1409 $self->_set_opts(\%input, "png_", $self)
1411 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1412 $self->{ERRSTR}='unable to write png image';
1415 $self->{DEBUG} && print "writing a png file\n";
1416 } elsif ( $input{'type'} eq 'jpeg' ) {
1417 $self->_set_opts(\%input, "jpeg_", $self)
1419 $self->_set_opts(\%input, "exif_", $self)
1421 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1422 $self->{ERRSTR} = $self->_error_as_msg();
1425 $self->{DEBUG} && print "writing a jpeg file\n";
1426 } elsif ( $input{'type'} eq 'bmp' ) {
1427 $self->_set_opts(\%input, "bmp_", $self)
1429 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1430 $self->{ERRSTR}='unable to write bmp image';
1433 $self->{DEBUG} && print "writing a bmp file\n";
1434 } elsif ( $input{'type'} eq 'tga' ) {
1435 $self->_set_opts(\%input, "tga_", $self)
1438 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1439 $self->{ERRSTR}=$self->_error_as_msg();
1442 $self->{DEBUG} && print "writing a tga file\n";
1443 } elsif ( $input{'type'} eq 'gif' ) {
1444 $self->_set_opts(\%input, "gif_", $self)
1446 # compatibility with the old interfaces
1447 if ($input{gifquant} eq 'lm') {
1448 $input{make_colors} = 'addi';
1449 $input{translate} = 'perturb';
1450 $input{perturb} = $input{lmdither};
1451 } elsif ($input{gifquant} eq 'gen') {
1452 # just pass options through
1454 $input{make_colors} = 'webmap'; # ignored
1455 $input{translate} = 'giflib';
1457 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1458 $self->{ERRSTR} = $self->_error_as_msg;
1463 if (exists $input{'data'}) {
1464 my $data = io_slurp($IO);
1466 $self->{ERRSTR}='Could not slurp from buffer';
1469 ${$input{data}} = $data;
1475 my ($class, $opts, @images) = @_;
1477 if (!$opts->{'type'} && $opts->{'file'}) {
1478 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1480 unless ($opts->{'type'}) {
1481 $class->_set_error('type parameter missing and not possible to guess from extension');
1484 # translate to ImgRaw
1485 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1486 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1489 $class->_set_opts($opts, "i_", @images)
1491 my @work = map $_->{IMG}, @images;
1492 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1494 if ($opts->{'type'} eq 'gif') {
1495 $class->_set_opts($opts, "gif_", @images)
1497 my $gif_delays = $opts->{gif_delays};
1498 local $opts->{gif_delays} = $gif_delays;
1499 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1500 # assume the caller wants the same delay for each frame
1501 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1503 my $res = i_writegif_wiol($IO, $opts, @work);
1504 $res or $class->_set_error($class->_error_as_msg());
1507 elsif ($opts->{'type'} eq 'tiff') {
1508 $class->_set_opts($opts, "tiff_", @images)
1510 $class->_set_opts($opts, "exif_", @images)
1513 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1514 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1515 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1518 $res = i_writetiff_multi_wiol($IO, @work);
1520 $res or $class->_set_error($class->_error_as_msg());
1524 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1529 # read multiple images from a file
1531 my ($class, %opts) = @_;
1533 if ($opts{file} && !exists $opts{'type'}) {
1535 my $type = $FORMATGUESS->($opts{file});
1536 $opts{'type'} = $type;
1538 unless ($opts{'type'}) {
1539 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1543 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1545 if ($opts{'type'} eq 'gif') {
1547 @imgs = i_readgif_multi_wiol($IO);
1550 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1554 $ERRSTR = _error_as_msg();
1558 elsif ($opts{'type'} eq 'tiff') {
1559 my @imgs = i_readtiff_multi_wiol($IO, -1);
1562 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1566 $ERRSTR = _error_as_msg();
1571 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1575 # Destroy an Imager object
1579 # delete $instances{$self};
1580 if (defined($self->{IMG})) {
1581 # the following is now handled by the XS DESTROY method for
1582 # Imager::ImgRaw object
1583 # Re-enabling this will break virtual images
1584 # tested for in t/t020masked.t
1585 # i_img_destroy($self->{IMG});
1586 undef($self->{IMG});
1588 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1592 # Perform an inplace filter of an image
1593 # that is the image will be overwritten with the data
1599 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1601 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1603 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1604 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1607 if ($filters{$input{'type'}}{names}) {
1608 my $names = $filters{$input{'type'}}{names};
1609 for my $name (keys %$names) {
1610 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1611 $input{$name} = $names->{$name}{$input{$name}};
1615 if (defined($filters{$input{'type'}}{defaults})) {
1616 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1618 %hsh=('image',$self->{IMG},%input);
1621 my @cs=@{$filters{$input{'type'}}{callseq}};
1624 if (!defined($hsh{$_})) {
1625 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1630 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1631 &{$filters{$input{'type'}}{callsub}}(%hsh);
1634 chomp($self->{ERRSTR} = $@);
1640 $self->{DEBUG} && print "callseq is: @cs\n";
1641 $self->{DEBUG} && print "matching callseq is: @b\n";
1646 # Scale an image to requested size and return the scaled version
1650 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1651 my $img = Imager->new();
1652 my $tmp = Imager->new();
1654 unless (defined wantarray) {
1655 my @caller = caller;
1656 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1660 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1662 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1663 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1664 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1665 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1666 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1667 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1669 if ($opts{qtype} eq 'normal') {
1670 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1671 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1672 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1673 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1676 if ($opts{'qtype'} eq 'preview') {
1677 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1678 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1681 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1684 # Scales only along the X axis
1688 my %opts=(scalefactor=>0.5,@_);
1690 unless (defined wantarray) {
1691 my @caller = caller;
1692 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1696 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1698 my $img = Imager->new();
1700 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1702 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1703 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1705 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1709 # Scales only along the Y axis
1713 my %opts=(scalefactor=>0.5,@_);
1715 unless (defined wantarray) {
1716 my @caller = caller;
1717 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1721 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1723 my $img = Imager->new();
1725 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1727 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1728 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1730 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1735 # Transform returns a spatial transformation of the input image
1736 # this moves pixels to a new location in the returned image.
1737 # NOTE - should make a utility function to check transforms for
1742 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1744 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1746 # print Dumper(\%opts);
1749 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1751 eval ("use Affix::Infix2Postfix;");
1754 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1757 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1758 {op=>'-',trans=>'Sub'},
1759 {op=>'*',trans=>'Mult'},
1760 {op=>'/',trans=>'Div'},
1761 {op=>'-','type'=>'unary',trans=>'u-'},
1763 {op=>'func','type'=>'unary'}],
1764 'grouping'=>[qw( \( \) )],
1765 'func'=>[qw( sin cos )],
1770 @xt=$I2P->translate($opts{'xexpr'});
1771 @yt=$I2P->translate($opts{'yexpr'});
1773 $numre=$I2P->{'numre'};
1776 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1777 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1778 @{$opts{'parm'}}=@pt;
1781 # print Dumper(\%opts);
1783 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1784 $self->{ERRSTR}='transform: no xopcodes given.';
1788 @op=@{$opts{'xopcodes'}};
1790 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1791 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1794 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1800 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1801 $self->{ERRSTR}='transform: no yopcodes given.';
1805 @op=@{$opts{'yopcodes'}};
1807 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1808 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1811 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1816 if ( !exists $opts{'parm'}) {
1817 $self->{ERRSTR}='transform: no parameter arg given.';
1821 # print Dumper(\@ropx);
1822 # print Dumper(\@ropy);
1823 # print Dumper(\@ropy);
1825 my $img = Imager->new();
1826 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1827 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1833 my ($opts, @imgs) = @_;
1835 require "Imager/Expr.pm";
1837 $opts->{variables} = [ qw(x y) ];
1838 my ($width, $height) = @{$opts}{qw(width height)};
1840 $width ||= $imgs[0]->getwidth();
1841 $height ||= $imgs[0]->getheight();
1843 for my $img (@imgs) {
1844 $opts->{constants}{"w$img_num"} = $img->getwidth();
1845 $opts->{constants}{"h$img_num"} = $img->getheight();
1846 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1847 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1852 $opts->{constants}{w} = $width;
1853 $opts->{constants}{cx} = $width/2;
1856 $Imager::ERRSTR = "No width supplied";
1860 $opts->{constants}{h} = $height;
1861 $opts->{constants}{cy} = $height/2;
1864 $Imager::ERRSTR = "No height supplied";
1867 my $code = Imager::Expr->new($opts);
1869 $Imager::ERRSTR = Imager::Expr::error();
1872 my $channels = $opts->{channels} || 3;
1873 unless ($channels >= 1 && $channels <= 4) {
1874 return Imager->_set_error("channels must be an integer between 1 and 4");
1877 my $img = Imager->new();
1878 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1879 $channels, $code->code(),
1880 $code->nregs(), $code->cregs(),
1881 [ map { $_->{IMG} } @imgs ]);
1882 if (!defined $img->{IMG}) {
1883 $Imager::ERRSTR = Imager->_error_as_msg();
1892 my %opts=(tx => 0,ty => 0, @_);
1894 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1895 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1897 %opts = (src_minx => 0,
1899 src_maxx => $opts{src}->getwidth(),
1900 src_maxy => $opts{src}->getheight(),
1903 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1904 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1905 $self->{ERRSTR} = $self->_error_as_msg();
1915 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
1917 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
1918 $dir = $xlate{$opts{'dir'}};
1919 return $self if i_flipxy($self->{IMG}, $dir);
1927 unless (defined wantarray) {
1928 my @caller = caller;
1929 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
1933 if (defined $opts{right}) {
1934 my $degrees = $opts{right};
1936 $degrees += 360 * int(((-$degrees)+360)/360);
1938 $degrees = $degrees % 360;
1939 if ($degrees == 0) {
1940 return $self->copy();
1942 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
1943 my $result = Imager->new();
1944 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
1948 $self->{ERRSTR} = $self->_error_as_msg();
1953 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
1957 elsif (defined $opts{radians} || defined $opts{degrees}) {
1958 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
1960 my $result = Imager->new;
1962 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
1965 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
1967 if ($result->{IMG}) {
1971 $self->{ERRSTR} = $self->_error_as_msg();
1976 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
1981 sub matrix_transform {
1985 unless (defined wantarray) {
1986 my @caller = caller;
1987 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
1991 if ($opts{matrix}) {
1992 my $xsize = $opts{xsize} || $self->getwidth;
1993 my $ysize = $opts{ysize} || $self->getheight;
1995 my $result = Imager->new;
1997 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
1998 $opts{matrix}, $opts{back})
2002 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2010 $self->{ERRSTR} = "matrix parameter required";
2016 *yatf = \&matrix_transform;
2018 # These two are supported for legacy code only
2021 return Imager::Color->new(@_);
2025 return Imager::Color::set(@_);
2028 # Draws a box between the specified corner points.
2031 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2032 my $dflcl=i_color_new(255,255,255,255);
2033 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2035 if (exists $opts{'box'}) {
2036 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
2037 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
2038 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
2039 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
2042 if ($opts{filled}) {
2043 my $color = _color($opts{'color'});
2045 $self->{ERRSTR} = $Imager::ERRSTR;
2048 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2049 $opts{ymax}, $color);
2051 elsif ($opts{fill}) {
2052 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2053 # assume it's a hash ref
2054 require 'Imager/Fill.pm';
2055 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2056 $self->{ERRSTR} = $Imager::ERRSTR;
2060 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2061 $opts{ymax},$opts{fill}{fill});
2064 my $color = _color($opts{'color'});
2066 $self->{ERRSTR} = $Imager::ERRSTR;
2069 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2075 # Draws an arc - this routine SUCKS and is buggy - it sometimes doesn't work when the arc is a convex polygon
2079 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2080 my $dflcl=i_color_new(255,255,255,255);
2081 my %opts=(color=>$dflcl,
2082 'r'=>min($self->getwidth(),$self->getheight())/3,
2083 'x'=>$self->getwidth()/2,
2084 'y'=>$self->getheight()/2,
2085 'd1'=>0, 'd2'=>361, @_);
2087 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2088 # assume it's a hash ref
2089 require 'Imager/Fill.pm';
2090 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2091 $self->{ERRSTR} = $Imager::ERRSTR;
2095 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2096 $opts{'d2'}, $opts{fill}{fill});
2099 my $color = _color($opts{'color'});
2101 $self->{ERRSTR} = $Imager::ERRSTR;
2104 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2105 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2109 if ($opts{'d1'} <= $opts{'d2'}) {
2110 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2111 $opts{'d1'}, $opts{'d2'}, $color);
2114 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2115 $opts{'d1'}, 361, $color);
2116 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2117 0, $opts{'d2'}, $color);
2125 # Draws a line from one point to the other
2126 # the endpoint is set if the endp parameter is set which it is by default.
2127 # to turn of the endpoint being set use endp=>0 when calling line.
2131 my $dflcl=i_color_new(0,0,0,0);
2132 my %opts=(color=>$dflcl,
2135 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2137 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2138 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2140 my $color = _color($opts{'color'});
2142 $self->{ERRSTR} = $Imager::ERRSTR;
2146 $opts{antialias} = $opts{aa} if defined $opts{aa};
2147 if ($opts{antialias}) {
2148 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2149 $color, $opts{endp});
2151 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2152 $color, $opts{endp});
2157 # Draws a line between an ordered set of points - It more or less just transforms this
2158 # into a list of lines.
2162 my ($pt,$ls,@points);
2163 my $dflcl=i_color_new(0,0,0,0);
2164 my %opts=(color=>$dflcl,@_);
2166 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2168 if (exists($opts{points})) { @points=@{$opts{points}}; }
2169 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2170 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2173 # print Dumper(\@points);
2175 my $color = _color($opts{'color'});
2177 $self->{ERRSTR} = $Imager::ERRSTR;
2180 $opts{antialias} = $opts{aa} if defined $opts{aa};
2181 if ($opts{antialias}) {
2184 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2191 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2201 my ($pt,$ls,@points);
2202 my $dflcl = i_color_new(0,0,0,0);
2203 my %opts = (color=>$dflcl, @_);
2205 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2207 if (exists($opts{points})) {
2208 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2209 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2212 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2213 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2216 if ($opts{'fill'}) {
2217 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2218 # assume it's a hash ref
2219 require 'Imager/Fill.pm';
2220 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2221 $self->{ERRSTR} = $Imager::ERRSTR;
2225 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2226 $opts{'fill'}{'fill'});
2229 my $color = _color($opts{'color'});
2231 $self->{ERRSTR} = $Imager::ERRSTR;
2234 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2241 # this the multipoint bezier curve
2242 # this is here more for testing that actual usage since
2243 # this is not a good algorithm. Usually the curve would be
2244 # broken into smaller segments and each done individually.
2248 my ($pt,$ls,@points);
2249 my $dflcl=i_color_new(0,0,0,0);
2250 my %opts=(color=>$dflcl,@_);
2252 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2254 if (exists $opts{points}) {
2255 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2256 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2259 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2260 $self->{ERRSTR}='Missing or invalid points.';
2264 my $color = _color($opts{'color'});
2266 $self->{ERRSTR} = $Imager::ERRSTR;
2269 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2275 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2278 unless (exists $opts{'x'} && exists $opts{'y'}) {
2279 $self->{ERRSTR} = "missing seed x and y parameters";
2284 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2285 # assume it's a hash ref
2286 require 'Imager/Fill.pm';
2287 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2288 $self->{ERRSTR} = $Imager::ERRSTR;
2292 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2295 my $color = _color($opts{'color'});
2297 $self->{ERRSTR} = $Imager::ERRSTR;
2300 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2302 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2308 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2310 unless (exists $opts{'x'} && exists $opts{'y'}) {
2311 $self->{ERRSTR} = 'missing x and y parameters';
2317 my $color = _color($opts{color})
2319 if (ref $x && ref $y) {
2320 unless (@$x == @$y) {
2321 $self->{ERRSTR} = 'length of x and y mismatch';
2324 if ($color->isa('Imager::Color')) {
2325 for my $i (0..$#{$opts{'x'}}) {
2326 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2330 for my $i (0..$#{$opts{'x'}}) {
2331 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2336 if ($color->isa('Imager::Color')) {
2337 i_ppix($self->{IMG}, $x, $y, $color);
2340 i_ppixf($self->{IMG}, $x, $y, $color);
2350 my %opts = ( "type"=>'8bit', @_);
2352 unless (exists $opts{'x'} && exists $opts{'y'}) {
2353 $self->{ERRSTR} = 'missing x and y parameters';
2359 if (ref $x && ref $y) {
2360 unless (@$x == @$y) {
2361 $self->{ERRSTR} = 'length of x and y mismatch';
2365 if ($opts{"type"} eq '8bit') {
2366 for my $i (0..$#{$opts{'x'}}) {
2367 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2371 for my $i (0..$#{$opts{'x'}}) {
2372 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2375 return wantarray ? @result : \@result;
2378 if ($opts{"type"} eq '8bit') {
2379 return i_get_pixel($self->{IMG}, $x, $y);
2382 return i_gpixf($self->{IMG}, $x, $y);
2391 my %opts = ( type => '8bit', x=>0, @_);
2393 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2395 unless (defined $opts{'y'}) {
2396 $self->_set_error("missing y parameter");
2400 if ($opts{type} eq '8bit') {
2401 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2404 elsif ($opts{type} eq 'float') {
2405 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2409 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2416 my %opts = ( x=>0, @_);
2418 unless (defined $opts{'y'}) {
2419 $self->_set_error("missing y parameter");
2424 if (ref $opts{pixels} && @{$opts{pixels}}) {
2425 # try to guess the type
2426 if ($opts{pixels}[0]->isa('Imager::Color')) {
2427 $opts{type} = '8bit';
2429 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2430 $opts{type} = 'float';
2433 $self->_set_error("missing type parameter and could not guess from pixels");
2439 $opts{type} = '8bit';
2443 if ($opts{type} eq '8bit') {
2444 if (ref $opts{pixels}) {
2445 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2448 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2451 elsif ($opts{type} eq 'float') {
2452 if (ref $opts{pixels}) {
2453 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2456 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2460 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2467 my %opts = ( type => '8bit', x=>0, @_);
2469 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2471 unless (defined $opts{'y'}) {
2472 $self->_set_error("missing y parameter");
2476 unless ($opts{channels}) {
2477 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2480 if ($opts{type} eq '8bit') {
2481 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2482 $opts{y}, @{$opts{channels}});
2484 elsif ($opts{type} eq 'float') {
2485 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2486 $opts{y}, @{$opts{channels}});
2489 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2494 # make an identity matrix of the given size
2498 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2499 for my $c (0 .. ($size-1)) {
2500 $matrix->[$c][$c] = 1;
2505 # general function to convert an image
2507 my ($self, %opts) = @_;
2510 unless (defined wantarray) {
2511 my @caller = caller;
2512 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2516 # the user can either specify a matrix or preset
2517 # the matrix overrides the preset
2518 if (!exists($opts{matrix})) {
2519 unless (exists($opts{preset})) {
2520 $self->{ERRSTR} = "convert() needs a matrix or preset";
2524 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2525 # convert to greyscale, keeping the alpha channel if any
2526 if ($self->getchannels == 3) {
2527 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2529 elsif ($self->getchannels == 4) {
2530 # preserve the alpha channel
2531 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2536 $matrix = _identity($self->getchannels);
2539 elsif ($opts{preset} eq 'noalpha') {
2540 # strip the alpha channel
2541 if ($self->getchannels == 2 or $self->getchannels == 4) {
2542 $matrix = _identity($self->getchannels);
2543 pop(@$matrix); # lose the alpha entry
2546 $matrix = _identity($self->getchannels);
2549 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2551 $matrix = [ [ 1 ] ];
2553 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2554 $matrix = [ [ 0, 1 ] ];
2556 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2557 $matrix = [ [ 0, 0, 1 ] ];
2559 elsif ($opts{preset} eq 'alpha') {
2560 if ($self->getchannels == 2 or $self->getchannels == 4) {
2561 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2564 # the alpha is just 1 <shrug>
2565 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2568 elsif ($opts{preset} eq 'rgb') {
2569 if ($self->getchannels == 1) {
2570 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2572 elsif ($self->getchannels == 2) {
2573 # preserve the alpha channel
2574 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2577 $matrix = _identity($self->getchannels);
2580 elsif ($opts{preset} eq 'addalpha') {
2581 if ($self->getchannels == 1) {
2582 $matrix = _identity(2);
2584 elsif ($self->getchannels == 3) {
2585 $matrix = _identity(4);
2588 $matrix = _identity($self->getchannels);
2592 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2598 $matrix = $opts{matrix};
2601 my $new = Imager->new();
2602 $new->{IMG} = i_img_new();
2603 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2604 # most likely a bad matrix
2605 $self->{ERRSTR} = _error_as_msg();
2612 # general function to map an image through lookup tables
2615 my ($self, %opts) = @_;
2616 my @chlist = qw( red green blue alpha );
2618 if (!exists($opts{'maps'})) {
2619 # make maps from channel maps
2621 for $chnum (0..$#chlist) {
2622 if (exists $opts{$chlist[$chnum]}) {
2623 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2624 } elsif (exists $opts{'all'}) {
2625 $opts{'maps'}[$chnum] = $opts{'all'};
2629 if ($opts{'maps'} and $self->{IMG}) {
2630 i_map($self->{IMG}, $opts{'maps'} );
2636 my ($self, %opts) = @_;
2638 defined $opts{mindist} or $opts{mindist} = 0;
2640 defined $opts{other}
2641 or return $self->_set_error("No 'other' parameter supplied");
2642 defined $opts{other}{IMG}
2643 or return $self->_set_error("No image data in 'other' image");
2646 or return $self->_set_error("No image data");
2648 my $result = Imager->new;
2649 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2651 or return $self->_set_error($self->_error_as_msg());
2656 # destructive border - image is shrunk by one pixel all around
2659 my ($self,%opts)=@_;
2660 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2661 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2665 # Get the width of an image
2669 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2670 return (i_img_info($self->{IMG}))[0];
2673 # Get the height of an image
2677 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2678 return (i_img_info($self->{IMG}))[1];
2681 # Get number of channels in an image
2685 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2686 return i_img_getchannels($self->{IMG});
2693 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2694 return i_img_getmask($self->{IMG});
2702 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2703 i_img_setmask( $self->{IMG} , $opts{mask} );
2706 # Get number of colors in an image
2710 my %opts=('maxcolors'=>2**30,@_);
2711 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2712 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2713 return ($rc==-1? undef : $rc);
2716 # draw string to an image
2720 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2722 my %input=('x'=>0, 'y'=>0, @_);
2723 $input{string}||=$input{text};
2725 unless(exists $input{string}) {
2726 $self->{ERRSTR}="missing required parameter 'string'";
2730 unless($input{font}) {
2731 $self->{ERRSTR}="missing required parameter 'font'";
2735 unless ($input{font}->draw(image=>$self, %input)) {
2736 $self->{ERRSTR} = $self->_error_as_msg();
2743 my @file_limit_names = qw/width height bytes/;
2745 sub set_file_limits {
2752 @values{@file_limit_names} = (0) x @file_limit_names;
2755 @values{@file_limit_names} = i_get_image_file_limits();
2758 for my $key (keys %values) {
2759 defined $opts{$key} and $values{$key} = $opts{$key};
2762 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
2765 sub get_file_limits {
2766 i_get_image_file_limits();
2769 # Shortcuts that can be exported
2771 sub newcolor { Imager::Color->new(@_); }
2772 sub newfont { Imager::Font->new(@_); }
2774 *NC=*newcolour=*newcolor;
2781 #### Utility routines
2784 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2788 my ($self, $msg) = @_;
2791 $self->{ERRSTR} = $msg;
2799 # Default guess for the type of an image from extension
2801 sub def_guess_type {
2804 $ext=($name =~ m/\.([^\.]+)$/)[0];
2805 return 'tiff' if ($ext =~ m/^tiff?$/);
2806 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2807 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2808 return 'png' if ($ext eq "png");
2809 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2810 return 'tga' if ($ext eq "tga");
2811 return 'rgb' if ($ext eq "rgb");
2812 return 'gif' if ($ext eq "gif");
2813 return 'raw' if ($ext eq "raw");
2817 # get the minimum of a list
2821 for(@_) { if ($_<$mx) { $mx=$_; }}
2825 # get the maximum of a list
2829 for(@_) { if ($_>$mx) { $mx=$_; }}
2833 # string stuff for iptc headers
2837 $str = substr($str,3);
2838 $str =~ s/[\n\r]//g;
2845 # A little hack to parse iptc headers.
2850 my($caption,$photogr,$headln,$credit);
2852 my $str=$self->{IPTCRAW};
2856 @ar=split(/8BIM/,$str);
2861 @sar=split(/\034\002/);
2862 foreach $item (@sar) {
2863 if ($item =~ m/^x/) {
2864 $caption=&clean($item);
2867 if ($item =~ m/^P/) {
2868 $photogr=&clean($item);
2871 if ($item =~ m/^i/) {
2872 $headln=&clean($item);
2875 if ($item =~ m/^n/) {
2876 $credit=&clean($item);
2882 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
2885 # Autoload methods go after =cut, and are processed by the autosplit program.
2889 # Below is the stub of documentation for your module. You better edit it!
2893 Imager - Perl extension for Generating 24 bit Images
2903 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
2908 my $img = Imager->new();
2909 # see Imager::Files for information on the read() method
2910 $img->read(file=>$file) or die $img->errstr();
2912 $file =~ s/\.[^.]*$//;
2914 # Create smaller version
2915 # documented in Imager::Transformations
2916 my $thumb = $img->scale(scalefactor=>.3);
2918 # Autostretch individual channels
2919 $thumb->filter(type=>'autolevels');
2921 # try to save in one of these formats
2924 for $format ( qw( png gif jpg tiff ppm ) ) {
2925 # Check if given format is supported
2926 if ($Imager::formats{$format}) {
2927 $file.="_low.$format";
2928 print "Storing image as: $file\n";
2929 # documented in Imager::Files
2930 $thumb->write(file=>$file) or
2938 Imager is a module for creating and altering images. It can read and
2939 write various image formats, draw primitive shapes like lines,and
2940 polygons, blend multiple images together in various ways, scale, crop,
2941 render text and more.
2943 =head2 Overview of documentation
2949 Imager - This document - Synopsis Example, Table of Contents and
2954 L<Imager::Tutorial> - a brief introduction to Imager.
2958 L<Imager::Cookbook> - how to do various things with Imager.
2962 L<Imager::ImageTypes> - Basics of constructing image objects with
2963 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
2964 8/16/double bits/channel, color maps, channel masks, image tags, color
2965 quantization. Also discusses basic image information methods.
2969 L<Imager::Files> - IO interaction, reading/writing images, format
2974 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
2979 L<Imager::Color> - Color specification.
2983 L<Imager::Fill> - Fill pattern specification.
2987 L<Imager::Font> - General font rendering, bounding boxes and font
2992 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
2993 blending, pasting, convert and map.
2997 L<Imager::Engines> - Programmable transformations through
2998 C<transform()>, C<transform2()> and C<matrix_transform()>.
3002 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3007 L<Imager::Expr> - Expressions for evaluation engine used by
3012 L<Imager::Matrix2d> - Helper class for affine transformations.
3016 L<Imager::Fountain> - Helper for making gradient profiles.
3020 =head2 Basic Overview
3022 An Image object is created with C<$img = Imager-E<gt>new()>.
3025 $img=Imager->new(); # create empty image
3026 $img->read(file=>'lena.png',type=>'png') or # read image from file
3027 die $img->errstr(); # give an explanation
3028 # if something failed
3030 or if you want to create an empty image:
3032 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3034 This example creates a completely black image of width 400 and height
3037 When an operation fails which can be directly associated with an image
3038 the error message is stored can be retrieved with
3039 C<$img-E<gt>errstr()>.
3041 In cases where no image object is associated with an operation
3042 C<$Imager::ERRSTR> is used to report errors not directly associated
3043 with an image object. You can also call C<Imager->errstr> to get this
3046 The C<Imager-E<gt>new> method is described in detail in
3047 L<Imager::ImageTypes>.
3051 Where to find information on methods for Imager class objects.
3053 addcolors() - L<Imager::ImageTypes>
3055 addtag() - L<Imager::ImageTypes> - add image tags
3057 arc() - L<Imager::Draw/arc>
3059 bits() - L<Imager::ImageTypes> - number of bits per sample for the
3062 box() - L<Imager::Draw/box>
3064 circle() - L<Imager::Draw/circle>
3066 colorcount() - L<Imager::Draw/colorcount>
3068 convert() - L<Imager::Transformations/"Color transformations"> -
3069 transform the color space
3071 copy() - L<Imager::Transformations/copy>
3073 crop() - L<Imager::Transformations/crop> - extract part of an image
3075 deltag() - L<Imager::ImageTypes> - delete image tags
3077 difference() - L<Imager::Filters/"Image Difference">
3079 errstr() - L<Imager/"Basic Overview">
3081 filter() - L<Imager::Filters>
3083 findcolor() - L<Imager::ImageTypes> - search the image palette, if it
3086 flip() - L<Imager::Transformations/flip>
3088 flood_fill() - L<Imager::Draw/flood_fill>
3090 getchannels() - L<Imager::ImageTypes>
3092 getcolorcount() - L<Imager::ImageTypes>
3094 getcolors() - L<Imager::ImageTypes> - get colors from the image
3095 palette, if it has one
3097 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3099 getheight() - L<Imager::ImageTypes>
3101 getpixel() - L<Imager::Draw/setpixel and getpixel>
3103 getsamples() - L<Imager::Draw/getsamples>
3105 getscanline() - L<Imager::Draw/getscanline>
3107 getwidth() - L<Imager::ImageTypes>
3109 img_set() - L<Imager::ImageTypes>
3111 line() - L<Imager::Draw/line>
3113 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3116 masked() - L<Imager::ImageTypes> - make a masked image
3118 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
3120 maxcolors() - L<Imager::ImageTypes/maxcolor>
3122 new() - L<Imager::ImageTypes>
3124 open() - L<Imager::Files> - an alias for read()
3126 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3128 polygon() - L<Imager::Draw/polygon>
3130 polyline() - L<Imager::Draw/polyline>
3132 read() - L<Imager::Files> - read a single image from an image file
3134 read_multi() - L<Imager::Files> - read multiple images from an image
3137 rotate() - L<Imager::Transformations/rotate>
3139 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3140 image and use the alpha channel
3142 scale() - L<Imager::Transformations/scale>
3144 setscanline() - L<Imager::Draw/setscanline>
3146 scaleX() - L<Imager::Transformations/scaleX>
3148 scaleY() - L<Imager::Transformations/scaleY>
3150 setcolors() - L<Imager::ImageTypes> - set palette colors in a paletted image
3152 setpixel() - L<Imager::Draw/setpixel and getpixel>
3154 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3156 string() - L<Imager::Font/string> - draw text on an image
3158 tags() - L<Imager::ImageTypes> - fetch image tags
3160 to_paletted() - L<Imager::ImageTypes>
3162 to_rgb8() - L<Imager::ImageTypes>
3164 transform() - L<Imager::Engines/"transform">
3166 transform2() - L<Imager::Engines/"transform2">
3168 type() - L<Imager::ImageTypes> - type of image (direct vs paletted)
3170 virtual() - L<Imager::ImageTypes> - whether the image has it's own
3173 write() - L<Imager::Files> - write an image to a file
3175 write_multi() - L<Imager::Files> - write multiple image to an image
3178 =head1 CONCEPT INDEX
3180 animated GIF - L<Imager::File/"Writing an animated GIF">
3182 aspect ratio - L<Imager::ImageTypes/i_xres>,
3183 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3185 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3187 boxes, drawing - L<Imager::Draw/box>
3189 color - L<Imager::Color>
3191 color names - L<Imager::Color>, L<Imager::Color::Table>
3193 combine modes - L<Imager::Fill/combine>
3195 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3197 convolution - L<Imager::Filter/conv>
3199 cropping - L<Imager::Transformations/crop>
3201 dpi - L<Imager::ImageTypes/i_xres>
3203 drawing boxes - L<Imager::Draw/box>
3205 drawing lines - L<Imager::Draw/line>
3207 drawing text - L<Imager::Font/string>, L<Imager::Font/align>
3209 error message - L<Imager/"Basic Overview">
3211 files, font - L<Imager::Font>
3213 files, image - L<Imager::Files>
3215 filling, types of fill - L<Imager::Fill>
3217 filling, boxes - L<Imager::Draw/box>
3219 filling, flood fill - L<Imager::Draw/flood_fill>
3221 flood fill - L<Imager::Draw/flood_fill>
3223 fonts - L<Imager::Font>
3225 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3226 L<Imager::Font::Wrap>
3228 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3230 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3232 fountain fill - L<Imager::Fill/"Fountain fills">,
3233 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3234 L<Imager::Filters/gradgen>
3236 GIF files - L<Imager::Files/"GIF">
3238 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3240 gradient fill - L<Imager::Fill/"Fountain fills">,
3241 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3242 L<Imager::Filters/gradgen>
3244 guassian blur - L<Imager::Filter/guassian>
3246 hatch fills - L<Imager::Fill/"Hatched fills">
3248 invert image - L<Imager::Filter/hardinvert>
3250 JPEG - L<Imager::Files/"JPEG">
3252 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3254 lines, drawing - L<Imager::Draw/line>
3256 matrix - L<Imager::Matrix2d>,
3257 L<Imager::Transformations/"Matrix Transformations">,
3258 L<Imager::Font/transform>
3260 metadata, image - L<Imager::ImageTypes/"Tags">
3262 mosaic - L<Imager::Filter/mosaic>
3264 noise, filter - L<Imager::Filter/noise>
3266 noise, rendered - L<Imager::Filter/turbnoise>,
3267 L<Imager::Filter/radnoise>
3269 posterize - L<Imager::Filter/postlevels>
3271 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3273 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3275 rectangles, drawing - L<Imager::Draw/box>
3277 resizing an image - L<Imager::Transformations/scale>,
3278 L<Imager::Transformations/crop>
3280 saving an image - L<Imager::Files>
3282 scaling - L<Imager::Transformations/scale>
3284 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3286 size, image - L<Imager::ImageTypes/getwidth>,
3287 L<Imager::ImageTypes/getheight>
3289 size, text - L<Imager::Font/bounding_box>
3291 text, drawing - L<Imager::Font/string>, L<Imager::Font/align>,
3292 L<Imager::Font::Wrap>
3294 text, wrapping text in an area - L<Imager::Font::Wrap>
3296 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3298 tiles, color - L<Imager::Filter/mosaic>
3300 unsharp mask - L<Imager::Filter/unsharpmask>
3302 watermark - L<Imager::Filter/watermark>
3304 writing an image - L<Imager::Files>
3308 You can ask for help, report bugs or express your undying love for
3309 Imager on the Imager-devel mailing list.
3311 To subscribe send a message with C<subscribe> in the body to:
3313 imager-devel+request@molar.is
3317 http://www.molar.is/en/lists/imager-devel/
3318 (annonymous is temporarily off due to spam)
3320 where you can also find the mailing list archive.
3322 If you're into IRC, you can typically find the developers in #Imager
3323 on irc.perl.org. As with any IRC channel, the participants could be
3324 occupied or asleep, so please be patient.
3326 You can report bugs by pointing your browser at:
3328 https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager
3330 Please remember to include the versions of Imager, perl, supporting
3331 libraries, and any relevant code. If you have specific images that
3332 cause the problems, please include those too.
3336 Bugs are listed individually for relevant pod pages.
3340 Arnar M. Hrafnkelsson (addi@imager.perl.org) and Tony Cook
3341 (tony@imager.perl.org) See the README for a complete list.
3345 perl(1), Imager::ImageTypes(3), Imager::Files(3), Imager::Draw(3),
3346 Imager::Color(3), Imager::Fill(3), Imager::Font(3),
3347 Imager::Transformations(3), Imager::Engines(3), Imager::Filters(3),
3348 Imager::Expr(3), Imager::Matrix2d(3), Imager::Fountain(3)
3350 Affix::Infix2Postfix(3), Parse::RecDescent(3)
3351 http://imager.perl.org/