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
146 # registered file readers
149 # registered file writers
152 # modules we attempted to autoload
153 my %attempted_to_load;
158 $VERSION = '0.51_01';
161 XSLoader::load(Imager => $VERSION);
165 push @ISA, 'DynaLoader';
166 bootstrap Imager $VERSION;
171 i_init_fonts(); # Initialize font engines
172 Imager::Font::__init();
173 for(i_list_formats()) { $formats{$_}++; }
175 if ($formats{'t1'}) {
179 if (!$formats{'t1'} and !$formats{'tt'}
180 && !$formats{'ft2'} && !$formats{'w32'}) {
181 $fontstate='no font support';
184 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
188 # the members of the subhashes under %filters are:
189 # callseq - a list of the parameters to the underlying filter in the
190 # order they are passed
191 # callsub - a code ref that takes a named parameter list and calls the
193 # defaults - a hash of default values
194 # names - defines names for value of given parameters so if the names
195 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
196 # foo parameter, the filter will receive 1 for the foo
199 callseq => ['image','intensity'],
200 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
204 callseq => ['image', 'amount', 'subtype'],
205 defaults => { amount=>3,subtype=>0 },
206 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
209 $filters{hardinvert} ={
210 callseq => ['image'],
212 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
215 $filters{autolevels} ={
216 callseq => ['image','lsat','usat','skew'],
217 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
218 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
221 $filters{turbnoise} ={
222 callseq => ['image'],
223 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
224 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
227 $filters{radnoise} ={
228 callseq => ['image'],
229 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
230 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
234 callseq => ['image', 'coef'],
236 callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
241 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
242 defaults => { dist => 0 },
246 my @colors = @{$hsh{colors}};
249 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
253 $filters{nearest_color} =
255 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
260 # make sure the segments are specified with colors
262 for my $color (@{$hsh{colors}}) {
263 my $new_color = _color($color)
264 or die $Imager::ERRSTR."\n";
265 push @colors, $new_color;
268 i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
270 or die Imager->_error_as_msg() . "\n";
273 $filters{gaussian} = {
274 callseq => [ 'image', 'stddev' ],
276 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
280 callseq => [ qw(image size) ],
281 defaults => { size => 20 },
282 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
286 callseq => [ qw(image bump elevation lightx lighty st) ],
287 defaults => { elevation=>0, st=> 2 },
290 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
291 $hsh{lightx}, $hsh{lighty}, $hsh{st});
294 $filters{bumpmap_complex} =
296 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
307 Ia => Imager::Color->new(rgb=>[0,0,0]),
308 Il => Imager::Color->new(rgb=>[255,255,255]),
309 Is => Imager::Color->new(rgb=>[255,255,255]),
313 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
314 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
315 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
319 $filters{postlevels} =
321 callseq => [ qw(image levels) ],
322 defaults => { levels => 10 },
323 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
325 $filters{watermark} =
327 callseq => [ qw(image wmark tx ty pixdiff) ],
328 defaults => { pixdiff=>10, tx=>0, ty=>0 },
332 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
338 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
340 ftype => { linear => 0,
346 repeat => { none => 0,
361 multiply => 2, mult => 2,
364 subtract => 5, 'sub' => 5,
374 defaults => { ftype => 0, repeat => 0, combine => 0,
375 super_sample => 0, ssample_param => 4,
378 Imager::Color->new(0,0,0),
379 Imager::Color->new(255, 255, 255),
388 # make sure the segments are specified with colors
390 for my $segment (@{$hsh{segments}}) {
391 my @new_segment = @$segment;
393 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
394 push @segments, \@new_segment;
397 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
398 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
399 $hsh{ssample_param}, \@segments)
400 or die Imager->_error_as_msg() . "\n";
403 $filters{unsharpmask} =
405 callseq => [ qw(image stddev scale) ],
406 defaults => { stddev=>2.0, scale=>1.0 },
410 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
414 $FORMATGUESS=\&def_guess_type;
424 # NOTE: this might be moved to an import override later on
428 # (look through @_ for special tags, process, and remove them);
430 # print Dumper($pack);
435 i_init_log($_[0],$_[1]);
436 i_log_entry("Imager $VERSION starting\n", 1);
441 my %parms=(loglevel=>1,@_);
443 init_log($parms{'log'},$parms{'loglevel'});
446 if (exists $parms{'warn_obsolete'}) {
447 $warn_obsolete = $parms{'warn_obsolete'};
450 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
451 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
455 if (exists $parms{'t1log'}) {
456 i_init_fonts($parms{'t1log'});
462 print "shutdown code\n";
463 # for(keys %instances) { $instances{$_}->DESTROY(); }
464 malloc_state(); # how do decide if this should be used? -- store something from the import
465 print "Imager exiting\n";
469 # Load a filter plugin
474 my ($DSO_handle,$str)=DSO_open($filename);
475 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
476 my %funcs=DSO_funclist($DSO_handle);
477 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
479 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
481 $DSOs{$filename}=[$DSO_handle,\%funcs];
484 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
485 $DEBUG && print "eval string:\n",$evstr,"\n";
497 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
498 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
499 for(keys %{$funcref}) {
501 $DEBUG && print "unloading: $_\n";
503 my $rc=DSO_close($DSO_handle);
504 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
508 # take the results of i_error() and make a message out of it
510 return join(": ", map $_->[0], i_errors());
513 # this function tries to DWIM for color parameters
514 # color objects are used as is
515 # simple scalars are simply treated as single parameters to Imager::Color->new
516 # hashrefs are treated as named argument lists to Imager::Color->new
517 # arrayrefs are treated as list arguments to Imager::Color->new iff any
519 # other arrayrefs are treated as list arguments to Imager::Color::Float
523 # perl 5.6.0 seems to do weird things to $arg if we don't make an
524 # explicitly stringified copy
525 # I vaguely remember a bug on this on p5p, but couldn't find it
526 # through bugs.perl.org (I had trouble getting it to find any bugs)
527 my $copy = $arg . "";
531 if (UNIVERSAL::isa($arg, "Imager::Color")
532 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
536 if ($copy =~ /^HASH\(/) {
537 $result = Imager::Color->new(%$arg);
539 elsif ($copy =~ /^ARRAY\(/) {
540 $result = Imager::Color->new(@$arg);
543 $Imager::ERRSTR = "Not a color";
548 # assume Imager::Color::new knows how to handle it
549 $result = Imager::Color->new($arg);
557 # Methods to be called on objects.
560 # Create a new Imager object takes very few parameters.
561 # usually you call this method and then call open from
562 # the resulting object
569 $self->{IMG}=undef; # Just to indicate what exists
570 $self->{ERRSTR}=undef; #
571 $self->{DEBUG}=$DEBUG;
572 $self->{DEBUG} && print "Initialized Imager\n";
573 if (defined $hsh{xsize} && defined $hsh{ysize}) {
574 unless ($self->img_set(%hsh)) {
575 $Imager::ERRSTR = $self->{ERRSTR};
582 # Copy an entire image with no changes
583 # - if an image has magic the copy of it will not be magical
587 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
589 unless (defined wantarray) {
591 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
595 my $newcopy=Imager->new();
596 $newcopy->{IMG} = i_copy($self->{IMG});
605 unless ($self->{IMG}) {
606 $self->_set_error('empty input image');
609 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
610 my $src = $input{img} || $input{src};
612 $self->_set_error("no source image");
615 $input{left}=0 if $input{left} <= 0;
616 $input{top}=0 if $input{top} <= 0;
618 my($r,$b)=i_img_info($src->{IMG});
619 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
620 my ($src_right, $src_bottom);
621 if ($input{src_coords}) {
622 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
625 if (defined $input{src_maxx}) {
626 $src_right = $input{src_maxx};
628 elsif (defined $input{width}) {
629 if ($input{width} <= 0) {
630 $self->_set_error("paste: width must me positive");
633 $src_right = $src_left + $input{width};
638 if (defined $input{src_maxy}) {
639 $src_bottom = $input{src_maxy};
641 elsif (defined $input{height}) {
642 if ($input{height} < 0) {
643 $self->_set_error("paste: height must be positive");
646 $src_bottom = $src_top + $input{height};
653 $src_right > $r and $src_right = $r;
654 $src_bottom > $b and $src_bottom = $b;
656 if ($src_right <= $src_left
657 || $src_bottom < $src_top) {
658 $self->_set_error("nothing to paste");
662 i_copyto($self->{IMG}, $src->{IMG},
663 $src_left, $src_top, $src_right, $src_bottom,
664 $input{left}, $input{top});
666 return $self; # What should go here??
669 # Crop an image - i.e. return a new image that is smaller
673 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
675 unless (defined wantarray) {
677 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
683 my ($w, $h, $l, $r, $b, $t) =
684 @hsh{qw(width height left right bottom top)};
686 # work through the various possibilities
691 elsif (!defined $r) {
692 $r = $self->getwidth;
704 $l = int(0.5+($self->getwidth()-$w)/2);
709 $r = $self->getwidth;
715 elsif (!defined $b) {
716 $b = $self->getheight;
728 $t=int(0.5+($self->getheight()-$h)/2);
733 $b = $self->getheight;
736 ($l,$r)=($r,$l) if $l>$r;
737 ($t,$b)=($b,$t) if $t>$b;
740 $r > $self->getwidth and $r = $self->getwidth;
742 $b > $self->getheight and $b = $self->getheight;
744 if ($l == $r || $t == $b) {
745 $self->_set_error("resulting image would have no content");
749 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
751 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
756 my ($self, %opts) = @_;
758 $self->{IMG} or return $self->_set_error("Not a valid image");
760 my $x = $opts{xsize} || $self->getwidth;
761 my $y = $opts{ysize} || $self->getheight;
762 my $channels = $opts{channels} || $self->getchannels;
764 my $out = Imager->new;
765 if ($channels == $self->getchannels) {
766 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
769 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
771 unless ($out->{IMG}) {
772 $self->{ERRSTR} = $self->_error_as_msg;
779 # Sets an image to a certain size and channel number
780 # if there was previously data in the image it is discarded
785 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
787 if (defined($self->{IMG})) {
788 # let IIM_DESTROY destroy it, it's possible this image is
789 # referenced from a virtual image (like masked)
790 #i_img_destroy($self->{IMG});
794 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
795 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
796 $hsh{maxcolors} || 256);
798 elsif ($hsh{bits} eq 'double') {
799 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
801 elsif ($hsh{bits} == 16) {
802 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
805 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
809 unless ($self->{IMG}) {
810 $self->{ERRSTR} = Imager->_error_as_msg();
817 # created a masked version of the current image
821 $self or return undef;
822 my %opts = (left => 0,
824 right => $self->getwidth,
825 bottom => $self->getheight,
827 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
829 my $result = Imager->new;
830 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
831 $opts{top}, $opts{right} - $opts{left},
832 $opts{bottom} - $opts{top});
833 # keep references to the mask and base images so they don't
835 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
840 # convert an RGB image into a paletted image
844 if (@_ != 1 && !ref $_[0]) {
851 unless (defined wantarray) {
853 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
857 my $result = Imager->new;
858 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
860 #print "Type ", i_img_type($result->{IMG}), "\n";
862 if ($result->{IMG}) {
866 $self->{ERRSTR} = $self->_error_as_msg;
871 # convert a paletted (or any image) to an 8-bit/channel RGB images
876 unless (defined wantarray) {
878 warn "to_rgb8() called in void context - to_rgb8() returns the cropped image at $caller[1] line $caller[2]\n";
883 $result = Imager->new;
884 $result->{IMG} = i_img_to_rgb($self->{IMG})
893 my %opts = (colors=>[], @_);
895 @{$opts{colors}} or return undef;
897 $self->{IMG} and i_addcolors($self->{IMG}, @{$opts{colors}});
902 my %opts = (start=>0, colors=>[], @_);
903 @{$opts{colors}} or return undef;
905 $self->{IMG} and i_setcolors($self->{IMG}, $opts{start}, @{$opts{colors}});
911 if (!exists $opts{start} && !exists $opts{count}) {
914 $opts{count} = $self->colorcount;
916 elsif (!exists $opts{count}) {
919 elsif (!exists $opts{start}) {
924 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
928 i_colorcount($_[0]{IMG});
932 i_maxcolors($_[0]{IMG});
938 $opts{color} or return undef;
940 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
945 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
946 if ($bits && $bits == length(pack("d", 1)) * 8) {
955 return i_img_type($self->{IMG}) ? "paletted" : "direct";
961 $self->{IMG} and i_img_virtual($self->{IMG});
965 my ($self, %opts) = @_;
967 $self->{IMG} or return;
969 if (defined $opts{name}) {
973 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
974 push @result, (i_tags_get($self->{IMG}, $found))[1];
977 return wantarray ? @result : $result[0];
979 elsif (defined $opts{code}) {
983 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
984 push @result, (i_tags_get($self->{IMG}, $found))[1];
991 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
994 return i_tags_count($self->{IMG});
1003 return -1 unless $self->{IMG};
1005 if (defined $opts{value}) {
1006 if ($opts{value} =~ /^\d+$/) {
1008 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1011 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1014 elsif (defined $opts{data}) {
1015 # force addition as a string
1016 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1019 $self->{ERRSTR} = "No value supplied";
1023 elsif ($opts{code}) {
1024 if (defined $opts{value}) {
1025 if ($opts{value} =~ /^\d+$/) {
1027 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1030 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1033 elsif (defined $opts{data}) {
1034 # force addition as a string
1035 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1038 $self->{ERRSTR} = "No value supplied";
1051 return 0 unless $self->{IMG};
1053 if (defined $opts{'index'}) {
1054 return i_tags_delete($self->{IMG}, $opts{'index'});
1056 elsif (defined $opts{name}) {
1057 return i_tags_delbyname($self->{IMG}, $opts{name});
1059 elsif (defined $opts{code}) {
1060 return i_tags_delbycode($self->{IMG}, $opts{code});
1063 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1069 my ($self, %opts) = @_;
1072 $self->deltag(name=>$opts{name});
1073 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1075 elsif (defined $opts{code}) {
1076 $self->deltag(code=>$opts{code});
1077 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1085 sub _get_reader_io {
1086 my ($self, $input) = @_;
1089 return $input->{io}, undef;
1091 elsif ($input->{fd}) {
1092 return io_new_fd($input->{fd});
1094 elsif ($input->{fh}) {
1095 my $fd = fileno($input->{fh});
1097 $self->_set_error("Handle in fh option not opened");
1100 return io_new_fd($fd);
1102 elsif ($input->{file}) {
1103 my $file = IO::File->new($input->{file}, "r");
1105 $self->_set_error("Could not open $input->{file}: $!");
1109 return (io_new_fd(fileno($file)), $file);
1111 elsif ($input->{data}) {
1112 return io_new_buffer($input->{data});
1114 elsif ($input->{callback} || $input->{readcb}) {
1115 if (!$input->{seekcb}) {
1116 $self->_set_error("Need a seekcb parameter");
1118 if ($input->{maxbuffer}) {
1119 return io_new_cb($input->{writecb},
1120 $input->{callback} || $input->{readcb},
1121 $input->{seekcb}, $input->{closecb},
1122 $input->{maxbuffer});
1125 return io_new_cb($input->{writecb},
1126 $input->{callback} || $input->{readcb},
1127 $input->{seekcb}, $input->{closecb});
1131 $self->_set_error("file/fd/fh/data/callback parameter missing");
1136 sub _get_writer_io {
1137 my ($self, $input, $type) = @_;
1140 return io_new_fd($input->{fd});
1142 elsif ($input->{fh}) {
1143 my $fd = fileno($input->{fh});
1145 $self->_set_error("Handle in fh option not opened");
1149 my $oldfh = select($input->{fh});
1150 # flush anything that's buffered, and make sure anything else is flushed
1153 return io_new_fd($fd);
1155 elsif ($input->{file}) {
1156 my $fh = new IO::File($input->{file},"w+");
1158 $self->_set_error("Could not open file $input->{file}: $!");
1161 binmode($fh) or die;
1162 return (io_new_fd(fileno($fh)), $fh);
1164 elsif ($input->{data}) {
1165 return io_new_bufchain();
1167 elsif ($input->{callback} || $input->{writecb}) {
1168 if ($input->{maxbuffer}) {
1169 return io_new_cb($input->{callback} || $input->{writecb},
1171 $input->{seekcb}, $input->{closecb},
1172 $input->{maxbuffer});
1175 return io_new_cb($input->{callback} || $input->{writecb},
1177 $input->{seekcb}, $input->{closecb});
1181 $self->_set_error("file/fd/fh/data/callback parameter missing");
1186 # Read an image from file
1192 if (defined($self->{IMG})) {
1193 # let IIM_DESTROY do the destruction, since the image may be
1194 # referenced from elsewhere
1195 #i_img_destroy($self->{IMG});
1196 undef($self->{IMG});
1199 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1201 unless ($input{'type'}) {
1202 $input{'type'} = i_test_format_probe($IO, -1);
1205 unless ($input{'type'}) {
1206 $self->_set_error('type parameter missing and not possible to guess from extension');
1210 _reader_autoload($input{type});
1212 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1213 return $readers{$input{type}}{single}->($self, $IO, %input);
1216 unless ($formats{$input{'type'}}) {
1217 $self->_set_error("format '$input{'type'}' not supported");
1222 if ( $input{'type'} eq 'jpeg' ) {
1223 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1224 if ( !defined($self->{IMG}) ) {
1225 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1227 $self->{DEBUG} && print "loading a jpeg file\n";
1231 if ( $input{'type'} eq 'tiff' ) {
1232 my $page = $input{'page'};
1233 defined $page or $page = 0;
1234 # Fixme, check if that length parameter is ever needed
1235 $self->{IMG}=i_readtiff_wiol( $IO, -1, $page );
1236 if ( !defined($self->{IMG}) ) {
1237 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1239 $self->{DEBUG} && print "loading a tiff file\n";
1243 if ( $input{'type'} eq 'pnm' ) {
1244 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1245 if ( !defined($self->{IMG}) ) {
1246 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1249 $self->{DEBUG} && print "loading a pnm file\n";
1253 if ( $input{'type'} eq 'png' ) {
1254 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1255 if ( !defined($self->{IMG}) ) {
1256 $self->{ERRSTR} = $self->_error_as_msg();
1259 $self->{DEBUG} && print "loading a png file\n";
1262 if ( $input{'type'} eq 'bmp' ) {
1263 $self->{IMG}=i_readbmp_wiol( $IO );
1264 if ( !defined($self->{IMG}) ) {
1265 $self->{ERRSTR}=$self->_error_as_msg();
1268 $self->{DEBUG} && print "loading a bmp file\n";
1271 if ( $input{'type'} eq 'gif' ) {
1272 if ($input{colors} && !ref($input{colors})) {
1273 # must be a reference to a scalar that accepts the colour map
1274 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1277 if ($input{'gif_consolidate'}) {
1278 if ($input{colors}) {
1280 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1282 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1286 $self->{IMG} =i_readgif_wiol( $IO );
1290 my $page = $input{'page'};
1291 defined $page or $page = 0;
1292 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1293 if ($input{colors}) {
1294 ${ $input{colors} } =
1295 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1299 if ( !defined($self->{IMG}) ) {
1300 $self->{ERRSTR}=$self->_error_as_msg();
1303 $self->{DEBUG} && print "loading a gif file\n";
1306 if ( $input{'type'} eq 'tga' ) {
1307 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1308 if ( !defined($self->{IMG}) ) {
1309 $self->{ERRSTR}=$self->_error_as_msg();
1312 $self->{DEBUG} && print "loading a tga file\n";
1315 if ( $input{'type'} eq 'rgb' ) {
1316 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1317 if ( !defined($self->{IMG}) ) {
1318 $self->{ERRSTR}=$self->_error_as_msg();
1321 $self->{DEBUG} && print "loading a tga file\n";
1325 if ( $input{'type'} eq 'raw' ) {
1326 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1328 if ( !($params{xsize} && $params{ysize}) ) {
1329 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1333 $self->{IMG} = i_readraw_wiol( $IO,
1336 $params{datachannels},
1337 $params{storechannels},
1338 $params{interleave});
1339 if ( !defined($self->{IMG}) ) {
1340 $self->{ERRSTR}=$self->_error_as_msg();
1343 $self->{DEBUG} && print "loading a raw file\n";
1349 sub register_reader {
1350 my ($class, %opts) = @_;
1353 or die "register_reader called with no type parameter\n";
1355 my $type = $opts{type};
1357 defined $opts{single} || defined $opts{multiple}
1358 or die "register_reader called with no single or multiple parameter\n";
1360 $readers{$type} = { };
1361 if ($opts{single}) {
1362 $readers{$type}{single} = $opts{single};
1364 if ($opts{multiple}) {
1365 $readers{$type}{multiple} = $opts{multiple};
1371 sub register_writer {
1372 my ($class, %opts) = @_;
1375 or die "register_writer called with no type parameter\n";
1377 my $type = $opts{type};
1379 defined $opts{single} || defined $opts{multiple}
1380 or die "register_writer called with no single or multiple parameter\n";
1382 $writers{$type} = { };
1383 if ($opts{single}) {
1384 $writers{$type}{single} = $opts{single};
1386 if ($opts{multiple}) {
1387 $writers{$type}{multiple} = $opts{multiple};
1393 # probes for an Imager::File::whatever module
1394 sub _reader_autoload {
1397 return if $formats{$type} || $readers{$type};
1399 return unless $type =~ /^\w+$/;
1401 my $file = "Imager/File/\U$type\E.pm";
1403 unless ($attempted_to_load{$file}) {
1405 ++$attempted_to_load{$file};
1409 # try to get a reader specific module
1410 my $file = "Imager/File/\U$type\EReader.pm";
1411 unless ($attempted_to_load{$file}) {
1413 ++$attempted_to_load{$file};
1421 # probes for an Imager::File::whatever module
1422 sub _writer_autoload {
1425 return if $formats{$type} || $readers{$type};
1427 return unless $type =~ /^\w+$/;
1429 my $file = "Imager/File/\U$type\E.pm";
1431 unless ($attempted_to_load{$file}) {
1433 ++$attempted_to_load{$file};
1437 # try to get a writer specific module
1438 my $file = "Imager/File/\U$type\EWriter.pm";
1439 unless ($attempted_to_load{$file}) {
1441 ++$attempted_to_load{$file};
1449 sub _fix_gif_positions {
1450 my ($opts, $opt, $msg, @imgs) = @_;
1452 my $positions = $opts->{'gif_positions'};
1454 for my $pos (@$positions) {
1455 my ($x, $y) = @$pos;
1456 my $img = $imgs[$index++];
1457 $img->settag(name=>'gif_left', value=>$x);
1458 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1460 $$msg .= "replaced with the gif_left and gif_top tags";
1465 gif_each_palette=>'gif_local_map',
1466 interlace => 'gif_interlace',
1467 gif_delays => 'gif_delay',
1468 gif_positions => \&_fix_gif_positions,
1469 gif_loop_count => 'gif_loop',
1473 my ($self, $opts, $prefix, @imgs) = @_;
1475 for my $opt (keys %$opts) {
1477 if ($obsolete_opts{$opt}) {
1478 my $new = $obsolete_opts{$opt};
1479 my $msg = "Obsolete option $opt ";
1481 $new->($opts, $opt, \$msg, @imgs);
1484 $msg .= "replaced with the $new tag ";
1487 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1488 warn $msg if $warn_obsolete && $^W;
1490 next unless $tagname =~ /^\Q$prefix/;
1491 my $value = $opts->{$opt};
1493 if (UNIVERSAL::isa($value, "Imager::Color")) {
1494 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1495 for my $img (@imgs) {
1496 $img->settag(name=>$tagname, value=>$tag);
1499 elsif (ref($value) eq 'ARRAY') {
1500 for my $i (0..$#$value) {
1501 my $val = $value->[$i];
1503 if (UNIVERSAL::isa($val, "Imager::Color")) {
1504 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1506 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1509 $self->_set_error("Unknown reference type " . ref($value) .
1510 " supplied in array for $opt");
1516 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1521 $self->_set_error("Unknown reference type " . ref($value) .
1522 " supplied for $opt");
1527 # set it as a tag for every image
1528 for my $img (@imgs) {
1529 $img->settag(name=>$tagname, value=>$value);
1537 # Write an image to file
1540 my %input=(jpegquality=>75,
1550 $self->_set_opts(\%input, "i_", $self)
1553 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1555 if (!$input{'type'} and $input{file}) {
1556 $input{'type'}=$FORMATGUESS->($input{file});
1558 if (!$input{'type'}) {
1559 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1563 _writer_autoload($input{type});
1566 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1567 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1570 $writers{$input{type}}{single}->($self, $IO, %input)
1574 if (!$formats{$input{'type'}}) {
1575 $self->{ERRSTR}='format not supported';
1579 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1582 if ($input{'type'} eq 'tiff') {
1583 $self->_set_opts(\%input, "tiff_", $self)
1585 $self->_set_opts(\%input, "exif_", $self)
1588 if (defined $input{class} && $input{class} eq 'fax') {
1589 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1590 $self->{ERRSTR} = $self->_error_as_msg();
1594 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1595 $self->{ERRSTR} = $self->_error_as_msg();
1599 } elsif ( $input{'type'} eq 'pnm' ) {
1600 $self->_set_opts(\%input, "pnm_", $self)
1602 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1603 $self->{ERRSTR} = $self->_error_as_msg();
1606 $self->{DEBUG} && print "writing a pnm file\n";
1607 } elsif ( $input{'type'} eq 'raw' ) {
1608 $self->_set_opts(\%input, "raw_", $self)
1610 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1611 $self->{ERRSTR} = $self->_error_as_msg();
1614 $self->{DEBUG} && print "writing a raw file\n";
1615 } elsif ( $input{'type'} eq 'png' ) {
1616 $self->_set_opts(\%input, "png_", $self)
1618 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1619 $self->{ERRSTR}='unable to write png image';
1622 $self->{DEBUG} && print "writing a png file\n";
1623 } elsif ( $input{'type'} eq 'jpeg' ) {
1624 $self->_set_opts(\%input, "jpeg_", $self)
1626 $self->_set_opts(\%input, "exif_", $self)
1628 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1629 $self->{ERRSTR} = $self->_error_as_msg();
1632 $self->{DEBUG} && print "writing a jpeg file\n";
1633 } elsif ( $input{'type'} eq 'bmp' ) {
1634 $self->_set_opts(\%input, "bmp_", $self)
1636 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1637 $self->{ERRSTR}='unable to write bmp image';
1640 $self->{DEBUG} && print "writing a bmp file\n";
1641 } elsif ( $input{'type'} eq 'tga' ) {
1642 $self->_set_opts(\%input, "tga_", $self)
1645 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1646 $self->{ERRSTR}=$self->_error_as_msg();
1649 $self->{DEBUG} && print "writing a tga file\n";
1650 } elsif ( $input{'type'} eq 'gif' ) {
1651 $self->_set_opts(\%input, "gif_", $self)
1653 # compatibility with the old interfaces
1654 if ($input{gifquant} eq 'lm') {
1655 $input{make_colors} = 'addi';
1656 $input{translate} = 'perturb';
1657 $input{perturb} = $input{lmdither};
1658 } elsif ($input{gifquant} eq 'gen') {
1659 # just pass options through
1661 $input{make_colors} = 'webmap'; # ignored
1662 $input{translate} = 'giflib';
1664 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1665 $self->{ERRSTR} = $self->_error_as_msg;
1671 if (exists $input{'data'}) {
1672 my $data = io_slurp($IO);
1674 $self->{ERRSTR}='Could not slurp from buffer';
1677 ${$input{data}} = $data;
1683 my ($class, $opts, @images) = @_;
1685 my $type = $opts->{type};
1687 if (!$type && $opts->{'file'}) {
1688 $type = $FORMATGUESS->($opts->{'file'});
1691 $class->_set_error('type parameter missing and not possible to guess from extension');
1694 # translate to ImgRaw
1695 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1696 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1699 $class->_set_opts($opts, "i_", @images)
1701 my @work = map $_->{IMG}, @images;
1703 _writer_autoload($type);
1706 if ($writers{$type} && $writers{$type}{multiple}) {
1707 ($IO, $file) = $class->_get_writer_io($opts, $type)
1710 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1714 if (!$formats{$type}) {
1715 $class->_set_error("format $type not supported");
1719 ($IO, $file) = $class->_get_writer_io($opts, $type)
1722 if ($type eq 'gif') {
1723 $class->_set_opts($opts, "gif_", @images)
1725 my $gif_delays = $opts->{gif_delays};
1726 local $opts->{gif_delays} = $gif_delays;
1727 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1728 # assume the caller wants the same delay for each frame
1729 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1731 unless (i_writegif_wiol($IO, $opts, @work)) {
1732 $class->_set_error($class->_error_as_msg());
1736 elsif ($type eq 'tiff') {
1737 $class->_set_opts($opts, "tiff_", @images)
1739 $class->_set_opts($opts, "exif_", @images)
1742 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1743 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1744 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1747 $res = i_writetiff_multi_wiol($IO, @work);
1750 $class->_set_error($class->_error_as_msg());
1755 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1760 if (exists $opts->{'data'}) {
1761 my $data = io_slurp($IO);
1763 Imager->_set_error('Could not slurp from buffer');
1766 ${$opts->{data}} = $data;
1771 # read multiple images from a file
1773 my ($class, %opts) = @_;
1775 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1778 my $type = $opts{'type'};
1780 $type = i_test_format_probe($IO, -1);
1783 if ($opts{file} && !$type) {
1785 $type = $FORMATGUESS->($opts{file});
1789 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1793 _reader_autoload($type);
1795 if ($readers{$type} && $readers{$type}{multiple}) {
1796 return $readers{$type}{multiple}->($IO, %opts);
1799 if ($type eq 'gif') {
1801 @imgs = i_readgif_multi_wiol($IO);
1804 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1808 $ERRSTR = _error_as_msg();
1812 elsif ($type eq 'tiff') {
1813 my @imgs = i_readtiff_multi_wiol($IO, -1);
1816 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1820 $ERRSTR = _error_as_msg();
1825 $ERRSTR = "Cannot read multiple images from $type files";
1829 # Destroy an Imager object
1833 # delete $instances{$self};
1834 if (defined($self->{IMG})) {
1835 # the following is now handled by the XS DESTROY method for
1836 # Imager::ImgRaw object
1837 # Re-enabling this will break virtual images
1838 # tested for in t/t020masked.t
1839 # i_img_destroy($self->{IMG});
1840 undef($self->{IMG});
1842 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1846 # Perform an inplace filter of an image
1847 # that is the image will be overwritten with the data
1853 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1855 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1857 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1858 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1861 if ($filters{$input{'type'}}{names}) {
1862 my $names = $filters{$input{'type'}}{names};
1863 for my $name (keys %$names) {
1864 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1865 $input{$name} = $names->{$name}{$input{$name}};
1869 if (defined($filters{$input{'type'}}{defaults})) {
1870 %hsh=( image => $self->{IMG},
1872 %{$filters{$input{'type'}}{defaults}},
1875 %hsh=( image => $self->{IMG},
1880 my @cs=@{$filters{$input{'type'}}{callseq}};
1883 if (!defined($hsh{$_})) {
1884 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1889 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1890 &{$filters{$input{'type'}}{callsub}}(%hsh);
1893 chomp($self->{ERRSTR} = $@);
1899 $self->{DEBUG} && print "callseq is: @cs\n";
1900 $self->{DEBUG} && print "matching callseq is: @b\n";
1905 sub register_filter {
1907 my %hsh = ( defaults => {}, @_ );
1910 or die "register_filter() with no type\n";
1911 defined $hsh{callsub}
1912 or die "register_filter() with no callsub\n";
1913 defined $hsh{callseq}
1914 or die "register_filter() with no callseq\n";
1916 exists $filters{$hsh{type}}
1919 $filters{$hsh{type}} = \%hsh;
1924 # Scale an image to requested size and return the scaled version
1928 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1929 my $img = Imager->new();
1930 my $tmp = Imager->new();
1932 my $scalefactor = $opts{scalefactor};
1934 unless (defined wantarray) {
1935 my @caller = caller;
1936 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1940 unless ($self->{IMG}) {
1941 $self->_set_error('empty input image');
1945 # work out the scaling
1946 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1947 my ($xpix, $ypix)=( $opts{xpixels} / $self->getwidth() ,
1948 $opts{ypixels} / $self->getheight() );
1949 if ($opts{'type'} eq 'min') {
1950 $scalefactor = _min($xpix,$ypix);
1952 elsif ($opts{'type'} eq 'max') {
1953 $scalefactor = _max($xpix,$ypix);
1956 $self->_set_error('invalid value for type parameter');
1959 } elsif ($opts{xpixels}) {
1960 $scalefactor = $opts{xpixels} / $self->getwidth();
1962 elsif ($opts{ypixels}) {
1963 $scalefactor = $opts{ypixels}/$self->getheight();
1965 elsif ($opts{constrain} && ref $opts{constrain}
1966 && $opts{constrain}->can('constrain')) {
1967 # we've been passed an Image::Math::Constrain object or something
1968 # that looks like one
1969 (undef, undef, $scalefactor)
1970 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
1971 unless ($scalefactor) {
1972 $self->_set_error('constrain method failed on constrain parameter');
1977 if ($opts{qtype} eq 'normal') {
1978 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
1979 if ( !defined($tmp->{IMG}) ) {
1980 $self->{ERRSTR} = 'unable to scale image';
1983 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $scalefactor, 1);
1984 if ( !defined($img->{IMG}) ) {
1985 $self->{ERRSTR}='unable to scale image';
1991 elsif ($opts{'qtype'} eq 'preview') {
1992 $img->{IMG} = i_scale_nn($self->{IMG}, $scalefactor, $scalefactor);
1993 if ( !defined($img->{IMG}) ) {
1994 $self->{ERRSTR}='unable to scale image';
2000 $self->_set_error('invalid value for qtype parameter');
2005 # Scales only along the X axis
2009 my %opts = ( scalefactor=>0.5, @_ );
2011 unless (defined wantarray) {
2012 my @caller = caller;
2013 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2017 unless ($self->{IMG}) {
2018 $self->{ERRSTR} = 'empty input image';
2022 my $img = Imager->new();
2024 my $scalefactor = $opts{scalefactor};
2026 if ($opts{pixels}) {
2027 $scalefactor = $opts{pixels} / $self->getwidth();
2030 unless ($self->{IMG}) {
2031 $self->{ERRSTR}='empty input image';
2035 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2037 if ( !defined($img->{IMG}) ) {
2038 $self->{ERRSTR} = 'unable to scale image';
2045 # Scales only along the Y axis
2049 my %opts = ( scalefactor => 0.5, @_ );
2051 unless (defined wantarray) {
2052 my @caller = caller;
2053 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2057 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2059 my $img = Imager->new();
2061 my $scalefactor = $opts{scalefactor};
2063 if ($opts{pixels}) {
2064 $scalefactor = $opts{pixels} / $self->getheight();
2067 unless ($self->{IMG}) {
2068 $self->{ERRSTR} = 'empty input image';
2071 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2073 if ( !defined($img->{IMG}) ) {
2074 $self->{ERRSTR} = 'unable to scale image';
2081 # Transform returns a spatial transformation of the input image
2082 # this moves pixels to a new location in the returned image.
2083 # NOTE - should make a utility function to check transforms for
2088 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2090 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2092 # print Dumper(\%opts);
2095 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2097 eval ("use Affix::Infix2Postfix;");
2100 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2103 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2104 {op=>'-',trans=>'Sub'},
2105 {op=>'*',trans=>'Mult'},
2106 {op=>'/',trans=>'Div'},
2107 {op=>'-','type'=>'unary',trans=>'u-'},
2109 {op=>'func','type'=>'unary'}],
2110 'grouping'=>[qw( \( \) )],
2111 'func'=>[qw( sin cos )],
2116 @xt=$I2P->translate($opts{'xexpr'});
2117 @yt=$I2P->translate($opts{'yexpr'});
2119 $numre=$I2P->{'numre'};
2122 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2123 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2124 @{$opts{'parm'}}=@pt;
2127 # print Dumper(\%opts);
2129 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2130 $self->{ERRSTR}='transform: no xopcodes given.';
2134 @op=@{$opts{'xopcodes'}};
2136 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2137 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2140 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2146 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2147 $self->{ERRSTR}='transform: no yopcodes given.';
2151 @op=@{$opts{'yopcodes'}};
2153 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2154 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2157 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2162 if ( !exists $opts{'parm'}) {
2163 $self->{ERRSTR}='transform: no parameter arg given.';
2167 # print Dumper(\@ropx);
2168 # print Dumper(\@ropy);
2169 # print Dumper(\@ropy);
2171 my $img = Imager->new();
2172 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2173 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2179 my ($opts, @imgs) = @_;
2181 require "Imager/Expr.pm";
2183 $opts->{variables} = [ qw(x y) ];
2184 my ($width, $height) = @{$opts}{qw(width height)};
2186 $width ||= $imgs[0]->getwidth();
2187 $height ||= $imgs[0]->getheight();
2189 for my $img (@imgs) {
2190 $opts->{constants}{"w$img_num"} = $img->getwidth();
2191 $opts->{constants}{"h$img_num"} = $img->getheight();
2192 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2193 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2198 $opts->{constants}{w} = $width;
2199 $opts->{constants}{cx} = $width/2;
2202 $Imager::ERRSTR = "No width supplied";
2206 $opts->{constants}{h} = $height;
2207 $opts->{constants}{cy} = $height/2;
2210 $Imager::ERRSTR = "No height supplied";
2213 my $code = Imager::Expr->new($opts);
2215 $Imager::ERRSTR = Imager::Expr::error();
2218 my $channels = $opts->{channels} || 3;
2219 unless ($channels >= 1 && $channels <= 4) {
2220 return Imager->_set_error("channels must be an integer between 1 and 4");
2223 my $img = Imager->new();
2224 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2225 $channels, $code->code(),
2226 $code->nregs(), $code->cregs(),
2227 [ map { $_->{IMG} } @imgs ]);
2228 if (!defined $img->{IMG}) {
2229 $Imager::ERRSTR = Imager->_error_as_msg();
2238 my %opts=(tx => 0,ty => 0, @_);
2240 unless ($self->{IMG}) {
2241 $self->{ERRSTR}='empty input image';
2244 unless ($opts{src} && $opts{src}->{IMG}) {
2245 $self->{ERRSTR}='empty input image for src';
2249 %opts = (src_minx => 0,
2251 src_maxx => $opts{src}->getwidth(),
2252 src_maxy => $opts{src}->getheight(),
2255 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
2256 $opts{src_minx}, $opts{src_miny},
2257 $opts{src_maxx}, $opts{src_maxy})) {
2258 $self->_set_error($self->_error_as_msg());
2268 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2270 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2271 $dir = $xlate{$opts{'dir'}};
2272 return $self if i_flipxy($self->{IMG}, $dir);
2280 unless (defined wantarray) {
2281 my @caller = caller;
2282 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2286 if (defined $opts{right}) {
2287 my $degrees = $opts{right};
2289 $degrees += 360 * int(((-$degrees)+360)/360);
2291 $degrees = $degrees % 360;
2292 if ($degrees == 0) {
2293 return $self->copy();
2295 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2296 my $result = Imager->new();
2297 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2301 $self->{ERRSTR} = $self->_error_as_msg();
2306 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2310 elsif (defined $opts{radians} || defined $opts{degrees}) {
2311 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2313 my $back = $opts{back};
2314 my $result = Imager->new;
2316 $back = _color($back);
2318 $self->_set_error(Imager->errstr);
2322 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2325 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2327 if ($result->{IMG}) {
2331 $self->{ERRSTR} = $self->_error_as_msg();
2336 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2341 sub matrix_transform {
2345 unless (defined wantarray) {
2346 my @caller = caller;
2347 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2351 if ($opts{matrix}) {
2352 my $xsize = $opts{xsize} || $self->getwidth;
2353 my $ysize = $opts{ysize} || $self->getheight;
2355 my $result = Imager->new;
2357 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2358 $opts{matrix}, $opts{back})
2362 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2370 $self->{ERRSTR} = "matrix parameter required";
2376 *yatf = \&matrix_transform;
2378 # These two are supported for legacy code only
2381 return Imager::Color->new(@_);
2385 return Imager::Color::set(@_);
2388 # Draws a box between the specified corner points.
2391 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2392 my $dflcl=i_color_new(255,255,255,255);
2393 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2395 if (exists $opts{'box'}) {
2396 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2397 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2398 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2399 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2402 if ($opts{filled}) {
2403 my $color = _color($opts{'color'});
2405 $self->{ERRSTR} = $Imager::ERRSTR;
2408 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2409 $opts{ymax}, $color);
2411 elsif ($opts{fill}) {
2412 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2413 # assume it's a hash ref
2414 require 'Imager/Fill.pm';
2415 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2416 $self->{ERRSTR} = $Imager::ERRSTR;
2420 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2421 $opts{ymax},$opts{fill}{fill});
2424 my $color = _color($opts{'color'});
2426 $self->{ERRSTR} = $Imager::ERRSTR;
2429 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2437 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2438 my $dflcl=i_color_new(255,255,255,255);
2439 my %opts=(color=>$dflcl,
2440 'r'=>_min($self->getwidth(),$self->getheight())/3,
2441 'x'=>$self->getwidth()/2,
2442 'y'=>$self->getheight()/2,
2443 'd1'=>0, 'd2'=>361, @_);
2446 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2447 # assume it's a hash ref
2448 require 'Imager/Fill.pm';
2449 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2450 $self->{ERRSTR} = $Imager::ERRSTR;
2454 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2455 $opts{'d2'}, $opts{fill}{fill});
2458 my $color = _color($opts{'color'});
2460 $self->{ERRSTR} = $Imager::ERRSTR;
2463 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2464 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2468 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2469 $opts{'d1'}, $opts{'d2'}, $color);
2475 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2476 # assume it's a hash ref
2477 require 'Imager/Fill.pm';
2478 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2479 $self->{ERRSTR} = $Imager::ERRSTR;
2483 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2484 $opts{'d2'}, $opts{fill}{fill});
2487 my $color = _color($opts{'color'});
2489 $self->{ERRSTR} = $Imager::ERRSTR;
2492 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2493 $opts{'d1'}, $opts{'d2'}, $color);
2500 # Draws a line from one point to the other
2501 # the endpoint is set if the endp parameter is set which it is by default.
2502 # to turn of the endpoint being set use endp=>0 when calling line.
2506 my $dflcl=i_color_new(0,0,0,0);
2507 my %opts=(color=>$dflcl,
2510 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2512 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2513 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2515 my $color = _color($opts{'color'});
2517 $self->{ERRSTR} = $Imager::ERRSTR;
2521 $opts{antialias} = $opts{aa} if defined $opts{aa};
2522 if ($opts{antialias}) {
2523 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2524 $color, $opts{endp});
2526 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2527 $color, $opts{endp});
2532 # Draws a line between an ordered set of points - It more or less just transforms this
2533 # into a list of lines.
2537 my ($pt,$ls,@points);
2538 my $dflcl=i_color_new(0,0,0,0);
2539 my %opts=(color=>$dflcl,@_);
2541 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2543 if (exists($opts{points})) { @points=@{$opts{points}}; }
2544 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2545 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2548 # print Dumper(\@points);
2550 my $color = _color($opts{'color'});
2552 $self->{ERRSTR} = $Imager::ERRSTR;
2555 $opts{antialias} = $opts{aa} if defined $opts{aa};
2556 if ($opts{antialias}) {
2559 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2566 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2576 my ($pt,$ls,@points);
2577 my $dflcl = i_color_new(0,0,0,0);
2578 my %opts = (color=>$dflcl, @_);
2580 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2582 if (exists($opts{points})) {
2583 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2584 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2587 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2588 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2591 if ($opts{'fill'}) {
2592 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2593 # assume it's a hash ref
2594 require 'Imager/Fill.pm';
2595 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2596 $self->{ERRSTR} = $Imager::ERRSTR;
2600 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2601 $opts{'fill'}{'fill'});
2604 my $color = _color($opts{'color'});
2606 $self->{ERRSTR} = $Imager::ERRSTR;
2609 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2616 # this the multipoint bezier curve
2617 # this is here more for testing that actual usage since
2618 # this is not a good algorithm. Usually the curve would be
2619 # broken into smaller segments and each done individually.
2623 my ($pt,$ls,@points);
2624 my $dflcl=i_color_new(0,0,0,0);
2625 my %opts=(color=>$dflcl,@_);
2627 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2629 if (exists $opts{points}) {
2630 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2631 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2634 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2635 $self->{ERRSTR}='Missing or invalid points.';
2639 my $color = _color($opts{'color'});
2641 $self->{ERRSTR} = $Imager::ERRSTR;
2644 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2650 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2653 unless (exists $opts{'x'} && exists $opts{'y'}) {
2654 $self->{ERRSTR} = "missing seed x and y parameters";
2658 if ($opts{border}) {
2659 my $border = _color($opts{border});
2661 $self->_set_error($Imager::ERRSTR);
2665 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2666 # assume it's a hash ref
2667 require Imager::Fill;
2668 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2669 $self->{ERRSTR} = $Imager::ERRSTR;
2673 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2674 $opts{fill}{fill}, $border);
2677 my $color = _color($opts{'color'});
2679 $self->{ERRSTR} = $Imager::ERRSTR;
2682 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2689 $self->{ERRSTR} = $self->_error_as_msg();
2695 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2696 # assume it's a hash ref
2697 require 'Imager/Fill.pm';
2698 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2699 $self->{ERRSTR} = $Imager::ERRSTR;
2703 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2706 my $color = _color($opts{'color'});
2708 $self->{ERRSTR} = $Imager::ERRSTR;
2711 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2717 $self->{ERRSTR} = $self->_error_as_msg();
2726 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2728 unless (exists $opts{'x'} && exists $opts{'y'}) {
2729 $self->{ERRSTR} = 'missing x and y parameters';
2735 my $color = _color($opts{color})
2737 if (ref $x && ref $y) {
2738 unless (@$x == @$y) {
2739 $self->{ERRSTR} = 'length of x and y mismatch';
2742 if ($color->isa('Imager::Color')) {
2743 for my $i (0..$#{$opts{'x'}}) {
2744 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2748 for my $i (0..$#{$opts{'x'}}) {
2749 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2754 if ($color->isa('Imager::Color')) {
2755 i_ppix($self->{IMG}, $x, $y, $color);
2758 i_ppixf($self->{IMG}, $x, $y, $color);
2768 my %opts = ( "type"=>'8bit', @_);
2770 unless (exists $opts{'x'} && exists $opts{'y'}) {
2771 $self->{ERRSTR} = 'missing x and y parameters';
2777 if (ref $x && ref $y) {
2778 unless (@$x == @$y) {
2779 $self->{ERRSTR} = 'length of x and y mismatch';
2783 if ($opts{"type"} eq '8bit') {
2784 for my $i (0..$#{$opts{'x'}}) {
2785 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2789 for my $i (0..$#{$opts{'x'}}) {
2790 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2793 return wantarray ? @result : \@result;
2796 if ($opts{"type"} eq '8bit') {
2797 return i_get_pixel($self->{IMG}, $x, $y);
2800 return i_gpixf($self->{IMG}, $x, $y);
2809 my %opts = ( type => '8bit', x=>0, @_);
2811 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2813 unless (defined $opts{'y'}) {
2814 $self->_set_error("missing y parameter");
2818 if ($opts{type} eq '8bit') {
2819 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2822 elsif ($opts{type} eq 'float') {
2823 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2827 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2834 my %opts = ( x=>0, @_);
2836 unless (defined $opts{'y'}) {
2837 $self->_set_error("missing y parameter");
2842 if (ref $opts{pixels} && @{$opts{pixels}}) {
2843 # try to guess the type
2844 if ($opts{pixels}[0]->isa('Imager::Color')) {
2845 $opts{type} = '8bit';
2847 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2848 $opts{type} = 'float';
2851 $self->_set_error("missing type parameter and could not guess from pixels");
2857 $opts{type} = '8bit';
2861 if ($opts{type} eq '8bit') {
2862 if (ref $opts{pixels}) {
2863 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2866 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2869 elsif ($opts{type} eq 'float') {
2870 if (ref $opts{pixels}) {
2871 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2874 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2878 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2885 my %opts = ( type => '8bit', x=>0, @_);
2887 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2889 unless (defined $opts{'y'}) {
2890 $self->_set_error("missing y parameter");
2894 unless ($opts{channels}) {
2895 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2898 if ($opts{type} eq '8bit') {
2899 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2900 $opts{y}, @{$opts{channels}});
2902 elsif ($opts{type} eq 'float') {
2903 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2904 $opts{y}, @{$opts{channels}});
2907 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2912 # make an identity matrix of the given size
2916 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2917 for my $c (0 .. ($size-1)) {
2918 $matrix->[$c][$c] = 1;
2923 # general function to convert an image
2925 my ($self, %opts) = @_;
2928 unless (defined wantarray) {
2929 my @caller = caller;
2930 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2934 # the user can either specify a matrix or preset
2935 # the matrix overrides the preset
2936 if (!exists($opts{matrix})) {
2937 unless (exists($opts{preset})) {
2938 $self->{ERRSTR} = "convert() needs a matrix or preset";
2942 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2943 # convert to greyscale, keeping the alpha channel if any
2944 if ($self->getchannels == 3) {
2945 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2947 elsif ($self->getchannels == 4) {
2948 # preserve the alpha channel
2949 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2954 $matrix = _identity($self->getchannels);
2957 elsif ($opts{preset} eq 'noalpha') {
2958 # strip the alpha channel
2959 if ($self->getchannels == 2 or $self->getchannels == 4) {
2960 $matrix = _identity($self->getchannels);
2961 pop(@$matrix); # lose the alpha entry
2964 $matrix = _identity($self->getchannels);
2967 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2969 $matrix = [ [ 1 ] ];
2971 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2972 $matrix = [ [ 0, 1 ] ];
2974 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2975 $matrix = [ [ 0, 0, 1 ] ];
2977 elsif ($opts{preset} eq 'alpha') {
2978 if ($self->getchannels == 2 or $self->getchannels == 4) {
2979 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2982 # the alpha is just 1 <shrug>
2983 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2986 elsif ($opts{preset} eq 'rgb') {
2987 if ($self->getchannels == 1) {
2988 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2990 elsif ($self->getchannels == 2) {
2991 # preserve the alpha channel
2992 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2995 $matrix = _identity($self->getchannels);
2998 elsif ($opts{preset} eq 'addalpha') {
2999 if ($self->getchannels == 1) {
3000 $matrix = _identity(2);
3002 elsif ($self->getchannels == 3) {
3003 $matrix = _identity(4);
3006 $matrix = _identity($self->getchannels);
3010 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3016 $matrix = $opts{matrix};
3019 my $new = Imager->new();
3020 $new->{IMG} = i_img_new();
3021 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
3022 # most likely a bad matrix
3023 $self->{ERRSTR} = _error_as_msg();
3030 # general function to map an image through lookup tables
3033 my ($self, %opts) = @_;
3034 my @chlist = qw( red green blue alpha );
3036 if (!exists($opts{'maps'})) {
3037 # make maps from channel maps
3039 for $chnum (0..$#chlist) {
3040 if (exists $opts{$chlist[$chnum]}) {
3041 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3042 } elsif (exists $opts{'all'}) {
3043 $opts{'maps'}[$chnum] = $opts{'all'};
3047 if ($opts{'maps'} and $self->{IMG}) {
3048 i_map($self->{IMG}, $opts{'maps'} );
3054 my ($self, %opts) = @_;
3056 defined $opts{mindist} or $opts{mindist} = 0;
3058 defined $opts{other}
3059 or return $self->_set_error("No 'other' parameter supplied");
3060 defined $opts{other}{IMG}
3061 or return $self->_set_error("No image data in 'other' image");
3064 or return $self->_set_error("No image data");
3066 my $result = Imager->new;
3067 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3069 or return $self->_set_error($self->_error_as_msg());
3074 # destructive border - image is shrunk by one pixel all around
3077 my ($self,%opts)=@_;
3078 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3079 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3083 # Get the width of an image
3087 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3088 return (i_img_info($self->{IMG}))[0];
3091 # Get the height of an image
3095 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3096 return (i_img_info($self->{IMG}))[1];
3099 # Get number of channels in an image
3103 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3104 return i_img_getchannels($self->{IMG});
3111 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3112 return i_img_getmask($self->{IMG});
3120 if (!defined($self->{IMG})) {
3121 $self->{ERRSTR} = 'image is empty';
3124 unless (defined $opts{mask}) {
3125 $self->_set_error("mask parameter required");
3128 i_img_setmask( $self->{IMG} , $opts{mask} );
3133 # Get number of colors in an image
3137 my %opts=('maxcolors'=>2**30,@_);
3138 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3139 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3140 return ($rc==-1? undef : $rc);
3143 # draw string to an image
3147 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3149 my %input=('x'=>0, 'y'=>0, @_);
3150 $input{string}||=$input{text};
3152 unless(defined $input{string}) {
3153 $self->{ERRSTR}="missing required parameter 'string'";
3157 unless($input{font}) {
3158 $self->{ERRSTR}="missing required parameter 'font'";
3162 unless ($input{font}->draw(image=>$self, %input)) {
3174 unless ($self->{IMG}) {
3175 $self->{ERRSTR}='empty input image';
3184 my %input=('x'=>0, 'y'=>0, @_);
3185 $input{string}||=$input{text};
3187 unless(exists $input{string}) {
3188 $self->_set_error("missing required parameter 'string'");
3192 unless($input{font}) {
3193 $self->_set_error("missing required parameter 'font'");
3198 unless (@result = $input{font}->align(image=>$img, %input)) {
3202 return wantarray ? @result : $result[0];
3205 my @file_limit_names = qw/width height bytes/;
3207 sub set_file_limits {
3214 @values{@file_limit_names} = (0) x @file_limit_names;
3217 @values{@file_limit_names} = i_get_image_file_limits();
3220 for my $key (keys %values) {
3221 defined $opts{$key} and $values{$key} = $opts{$key};
3224 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3227 sub get_file_limits {
3228 i_get_image_file_limits();
3231 # Shortcuts that can be exported
3233 sub newcolor { Imager::Color->new(@_); }
3234 sub newfont { Imager::Font->new(@_); }
3236 *NC=*newcolour=*newcolor;
3243 #### Utility routines
3246 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3250 my ($self, $msg) = @_;
3253 $self->{ERRSTR} = $msg;
3261 # Default guess for the type of an image from extension
3263 sub def_guess_type {
3266 $ext=($name =~ m/\.([^\.]+)$/)[0];
3267 return 'tiff' if ($ext =~ m/^tiff?$/);
3268 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3269 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3270 return 'png' if ($ext eq "png");
3271 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3272 return 'tga' if ($ext eq "tga");
3273 return 'rgb' if ($ext eq "rgb");
3274 return 'gif' if ($ext eq "gif");
3275 return 'raw' if ($ext eq "raw");
3276 return lc $ext; # best guess
3280 # get the minimum of a list
3284 for(@_) { if ($_<$mx) { $mx=$_; }}
3288 # get the maximum of a list
3292 for(@_) { if ($_>$mx) { $mx=$_; }}
3296 # string stuff for iptc headers
3300 $str = substr($str,3);
3301 $str =~ s/[\n\r]//g;
3308 # A little hack to parse iptc headers.
3313 my($caption,$photogr,$headln,$credit);
3315 my $str=$self->{IPTCRAW};
3320 @ar=split(/8BIM/,$str);
3325 @sar=split(/\034\002/);
3326 foreach $item (@sar) {
3327 if ($item =~ m/^x/) {
3328 $caption = _clean($item);
3331 if ($item =~ m/^P/) {
3332 $photogr = _clean($item);
3335 if ($item =~ m/^i/) {
3336 $headln = _clean($item);
3339 if ($item =~ m/^n/) {
3340 $credit = _clean($item);
3346 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3353 or die "Only C language supported";
3355 require Imager::ExtUtils;
3356 return Imager::ExtUtils->inline_config;
3361 # Below is the stub of documentation for your module. You better edit it!
3365 Imager - Perl extension for Generating 24 bit Images
3375 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3380 my $img = Imager->new();
3381 # see Imager::Files for information on the read() method
3382 $img->read(file=>$file) or die $img->errstr();
3384 $file =~ s/\.[^.]*$//;
3386 # Create smaller version
3387 # documented in Imager::Transformations
3388 my $thumb = $img->scale(scalefactor=>.3);
3390 # Autostretch individual channels
3391 $thumb->filter(type=>'autolevels');
3393 # try to save in one of these formats
3396 for $format ( qw( png gif jpg tiff ppm ) ) {
3397 # Check if given format is supported
3398 if ($Imager::formats{$format}) {
3399 $file.="_low.$format";
3400 print "Storing image as: $file\n";
3401 # documented in Imager::Files
3402 $thumb->write(file=>$file) or
3410 Imager is a module for creating and altering images. It can read and
3411 write various image formats, draw primitive shapes like lines,and
3412 polygons, blend multiple images together in various ways, scale, crop,
3413 render text and more.
3415 =head2 Overview of documentation
3421 Imager - This document - Synopsis Example, Table of Contents and
3426 L<Imager::Tutorial> - a brief introduction to Imager.
3430 L<Imager::Cookbook> - how to do various things with Imager.
3434 L<Imager::ImageTypes> - Basics of constructing image objects with
3435 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3436 8/16/double bits/channel, color maps, channel masks, image tags, color
3437 quantization. Also discusses basic image information methods.
3441 L<Imager::Files> - IO interaction, reading/writing images, format
3446 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3451 L<Imager::Color> - Color specification.
3455 L<Imager::Fill> - Fill pattern specification.
3459 L<Imager::Font> - General font rendering, bounding boxes and font
3464 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3465 blending, pasting, convert and map.
3469 L<Imager::Engines> - Programmable transformations through
3470 C<transform()>, C<transform2()> and C<matrix_transform()>.
3474 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3479 L<Imager::Expr> - Expressions for evaluation engine used by
3484 L<Imager::Matrix2d> - Helper class for affine transformations.
3488 L<Imager::Fountain> - Helper for making gradient profiles.
3492 L<Imager::API> - using Imager's C API
3496 L<Imager::APIRef> - API function reference
3500 L<Imager::Inline> - using Imager's C API from Inline::C
3504 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3508 =head2 Basic Overview
3510 An Image object is created with C<$img = Imager-E<gt>new()>.
3513 $img=Imager->new(); # create empty image
3514 $img->read(file=>'lena.png',type=>'png') or # read image from file
3515 die $img->errstr(); # give an explanation
3516 # if something failed
3518 or if you want to create an empty image:
3520 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3522 This example creates a completely black image of width 400 and height
3525 When an operation fails which can be directly associated with an image
3526 the error message is stored can be retrieved with
3527 C<$img-E<gt>errstr()>.
3529 In cases where no image object is associated with an operation
3530 C<$Imager::ERRSTR> is used to report errors not directly associated
3531 with an image object. You can also call C<Imager->errstr> to get this
3534 The C<Imager-E<gt>new> method is described in detail in
3535 L<Imager::ImageTypes>.
3539 Where to find information on methods for Imager class objects.
3541 addcolors() - L<Imager::ImageTypes/addcolors>
3543 addtag() - L<Imager::ImageTypes/addtag> - add image tags
3545 arc() - L<Imager::Draw/arc>
3547 align_string() - L<Imager::Draw/align_string>
3549 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
3552 box() - L<Imager::Draw/box>
3554 circle() - L<Imager::Draw/circle>
3556 colorcount() - L<Imager::Draw/colorcount>
3558 convert() - L<Imager::Transformations/"Color transformations"> -
3559 transform the color space
3561 copy() - L<Imager::Transformations/copy>
3563 crop() - L<Imager::Transformations/crop> - extract part of an image
3565 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
3567 difference() - L<Imager::Filters/"Image Difference">
3569 errstr() - L<"Basic Overview">
3571 filter() - L<Imager::Filters>
3573 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
3576 flip() - L<Imager::Transformations/flip>
3578 flood_fill() - L<Imager::Draw/flood_fill>
3580 getchannels() - L<Imager::ImageTypes/getchannels>
3582 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
3584 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
3585 palette, if it has one
3587 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3589 getheight() - L<Imager::ImageTypes/getwidth>
3591 getpixel() - L<Imager::Draw/getpixel>
3593 getsamples() - L<Imager::Draw/getsamples>
3595 getscanline() - L<Imager::Draw/getscanline>
3597 getwidth() - L<Imager::ImageTypes/getwidth>
3599 img_set() - L<Imager::ImageTypes/img_set>
3601 line() - L<Imager::Draw/line>
3603 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3606 masked() - L<Imager::ImageTypes/masked> - make a masked image
3608 matrix_transform() - L<Imager::Engines/matrix_transform>
3610 maxcolors() - L<Imager::ImageTypes/maxcolors>
3612 new() - L<Imager::ImageTypes/new>
3614 open() - L<Imager::Files> - an alias for read()
3616 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
3619 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3621 polygon() - L<Imager::Draw/polygon>
3623 polyline() - L<Imager::Draw/polyline>
3625 read() - L<Imager::Files> - read a single image from an image file
3627 read_multi() - L<Imager::Files> - read multiple images from an image
3630 rotate() - L<Imager::Transformations/rotate>
3632 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3633 image and use the alpha channel
3635 scale() - L<Imager::Transformations/scale>
3637 scaleX() - L<Imager::Transformations/scaleX>
3639 scaleY() - L<Imager::Transformations/scaleY>
3641 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
3644 setpixel() - L<Imager::Draw/setpixel>
3646 setscanline() - L<Imager::Draw/setscanline>
3648 settag() - L<Imager::ImageTypes/settag>
3650 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3652 string() - L<Imager::Draw/string> - draw text on an image
3654 tags() - L<Imager::ImageTypes/tags> - fetch image tags
3656 to_paletted() - L<Imager::ImageTypes/to_paletted>
3658 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
3660 transform() - L<Imager::Engines/"transform">
3662 transform2() - L<Imager::Engines/"transform2">
3664 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
3666 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
3669 write() - L<Imager::Files> - write an image to a file
3671 write_multi() - L<Imager::Files> - write multiple image to an image
3674 =head1 CONCEPT INDEX
3676 animated GIF - L<Imager::File/"Writing an animated GIF">
3678 aspect ratio - L<Imager::ImageTypes/i_xres>,
3679 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3681 blend - alpha blending one image onto another
3682 L<Imager::Transformations/rubthrough>
3684 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3686 boxes, drawing - L<Imager::Draw/box>
3688 changes between image - L<Imager::Filter/"Image Difference">
3690 color - L<Imager::Color>
3692 color names - L<Imager::Color>, L<Imager::Color::Table>
3694 combine modes - L<Imager::Fill/combine>
3696 compare images - L<Imager::Filter/"Image Difference">
3698 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3700 convolution - L<Imager::Filter/conv>
3702 cropping - L<Imager::Transformations/crop>
3704 C<diff> images - L<Imager::Filter/"Image Difference">
3706 dpi - L<Imager::ImageTypes/i_xres>
3708 drawing boxes - L<Imager::Draw/box>
3710 drawing lines - L<Imager::Draw/line>
3712 drawing text - L<Imager::Font/string>, L<Imager::Font/align>
3714 error message - L<"Basic Overview">
3716 files, font - L<Imager::Font>
3718 files, image - L<Imager::Files>
3720 filling, types of fill - L<Imager::Fill>
3722 filling, boxes - L<Imager::Draw/box>
3724 filling, flood fill - L<Imager::Draw/flood_fill>
3726 flood fill - L<Imager::Draw/flood_fill>
3728 fonts - L<Imager::Font>
3730 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3731 L<Imager::Font::Wrap>
3733 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3735 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3737 fountain fill - L<Imager::Fill/"Fountain fills">,
3738 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3739 L<Imager::Filters/gradgen>
3741 GIF files - L<Imager::Files/"GIF">
3743 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3745 gradient fill - L<Imager::Fill/"Fountain fills">,
3746 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3747 L<Imager::Filters/gradgen>
3749 guassian blur - L<Imager::Filter/guassian>
3751 hatch fills - L<Imager::Fill/"Hatched fills">
3753 invert image - L<Imager::Filter/hardinvert>
3755 JPEG - L<Imager::Files/"JPEG">
3757 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3759 lines, drawing - L<Imager::Draw/line>
3761 matrix - L<Imager::Matrix2d>,
3762 L<Imager::Transformations/"Matrix Transformations">,
3763 L<Imager::Font/transform>
3765 metadata, image - L<Imager::ImageTypes/"Tags">
3767 mosaic - L<Imager::Filter/mosaic>
3769 noise, filter - L<Imager::Filter/noise>
3771 noise, rendered - L<Imager::Filter/turbnoise>,
3772 L<Imager::Filter/radnoise>
3774 paste - L<Imager::Transformations/paste>,
3775 L<Imager::Transformations/rubthrough>
3777 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
3778 L<Imager::ImageTypes/new>
3780 posterize - L<Imager::Filter/postlevels>
3782 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3784 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3786 rectangles, drawing - L<Imager::Draw/box>
3788 resizing an image - L<Imager::Transformations/scale>,
3789 L<Imager::Transformations/crop>
3791 saving an image - L<Imager::Files>
3793 scaling - L<Imager::Transformations/scale>
3795 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3797 size, image - L<Imager::ImageTypes/getwidth>,
3798 L<Imager::ImageTypes/getheight>
3800 size, text - L<Imager::Font/bounding_box>
3802 tags, image metadata - L<Imager::ImageTypes/"Tags">
3804 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
3805 L<Imager::Font::Wrap>
3807 text, wrapping text in an area - L<Imager::Font::Wrap>
3809 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3811 tiles, color - L<Imager::Filter/mosaic>
3813 unsharp mask - L<Imager::Filter/unsharpmask>
3815 watermark - L<Imager::Filter/watermark>
3817 writing an image to a file - L<Imager::Files>
3821 The best place to get help with Imager is the mailing list.
3823 To subscribe send a message with C<subscribe> in the body to:
3825 imager-devel+request@molar.is
3831 L<http://www.molar.is/en/lists/imager-devel/>
3835 where you can also find the mailing list archive.
3837 You can report bugs by pointing your browser at:
3841 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
3845 Please remember to include the versions of Imager, perl, supporting
3846 libraries, and any relevant code. If you have specific images that
3847 cause the problems, please include those too.
3851 Bugs are listed individually for relevant pod pages.
3855 Arnar M. Hrafnkelsson and Tony Cook (tony@imager.perl.org) among
3856 others. See the README for a complete list.
3860 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
3861 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
3862 L<Imager::Font>(3), L<Imager::Transformations>(3),
3863 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
3864 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
3866 L<http://imager.perl.org/>
3868 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
3870 Other perl imaging modules include:
3872 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).