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_02';
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 unless ($self->{IMG}) {
896 $self->_set_error("empty input image");
900 my @colors = @{$opts{colors}}
903 for my $color (@colors) {
904 $color = _color($color);
906 $self->_set_error($Imager::ERRSTR);
911 return i_addcolors($self->{IMG}, @colors);
916 my %opts = (start=>0, colors=>[], @_);
918 unless ($self->{IMG}) {
919 $self->_set_error("empty input image");
923 my @colors = @{$opts{colors}}
926 for my $color (@colors) {
927 $color = _color($color);
929 $self->_set_error($Imager::ERRSTR);
934 return i_setcolors($self->{IMG}, $opts{start}, @colors);
940 if (!exists $opts{start} && !exists $opts{count}) {
943 $opts{count} = $self->colorcount;
945 elsif (!exists $opts{count}) {
948 elsif (!exists $opts{start}) {
953 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
957 i_colorcount($_[0]{IMG});
961 i_maxcolors($_[0]{IMG});
967 $opts{color} or return undef;
969 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
974 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
975 if ($bits && $bits == length(pack("d", 1)) * 8) {
984 return i_img_type($self->{IMG}) ? "paletted" : "direct";
990 $self->{IMG} and i_img_virtual($self->{IMG});
994 my ($self, %opts) = @_;
996 $self->{IMG} or return;
998 if (defined $opts{name}) {
1002 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1003 push @result, (i_tags_get($self->{IMG}, $found))[1];
1006 return wantarray ? @result : $result[0];
1008 elsif (defined $opts{code}) {
1012 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1013 push @result, (i_tags_get($self->{IMG}, $found))[1];
1020 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
1023 return i_tags_count($self->{IMG});
1032 return -1 unless $self->{IMG};
1034 if (defined $opts{value}) {
1035 if ($opts{value} =~ /^\d+$/) {
1037 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1040 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1043 elsif (defined $opts{data}) {
1044 # force addition as a string
1045 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1048 $self->{ERRSTR} = "No value supplied";
1052 elsif ($opts{code}) {
1053 if (defined $opts{value}) {
1054 if ($opts{value} =~ /^\d+$/) {
1056 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1059 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1062 elsif (defined $opts{data}) {
1063 # force addition as a string
1064 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1067 $self->{ERRSTR} = "No value supplied";
1080 return 0 unless $self->{IMG};
1082 if (defined $opts{'index'}) {
1083 return i_tags_delete($self->{IMG}, $opts{'index'});
1085 elsif (defined $opts{name}) {
1086 return i_tags_delbyname($self->{IMG}, $opts{name});
1088 elsif (defined $opts{code}) {
1089 return i_tags_delbycode($self->{IMG}, $opts{code});
1092 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1098 my ($self, %opts) = @_;
1101 $self->deltag(name=>$opts{name});
1102 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1104 elsif (defined $opts{code}) {
1105 $self->deltag(code=>$opts{code});
1106 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1114 sub _get_reader_io {
1115 my ($self, $input) = @_;
1118 return $input->{io}, undef;
1120 elsif ($input->{fd}) {
1121 return io_new_fd($input->{fd});
1123 elsif ($input->{fh}) {
1124 my $fd = fileno($input->{fh});
1126 $self->_set_error("Handle in fh option not opened");
1129 return io_new_fd($fd);
1131 elsif ($input->{file}) {
1132 my $file = IO::File->new($input->{file}, "r");
1134 $self->_set_error("Could not open $input->{file}: $!");
1138 return (io_new_fd(fileno($file)), $file);
1140 elsif ($input->{data}) {
1141 return io_new_buffer($input->{data});
1143 elsif ($input->{callback} || $input->{readcb}) {
1144 if (!$input->{seekcb}) {
1145 $self->_set_error("Need a seekcb parameter");
1147 if ($input->{maxbuffer}) {
1148 return io_new_cb($input->{writecb},
1149 $input->{callback} || $input->{readcb},
1150 $input->{seekcb}, $input->{closecb},
1151 $input->{maxbuffer});
1154 return io_new_cb($input->{writecb},
1155 $input->{callback} || $input->{readcb},
1156 $input->{seekcb}, $input->{closecb});
1160 $self->_set_error("file/fd/fh/data/callback parameter missing");
1165 sub _get_writer_io {
1166 my ($self, $input, $type) = @_;
1169 return io_new_fd($input->{fd});
1171 elsif ($input->{fh}) {
1172 my $fd = fileno($input->{fh});
1174 $self->_set_error("Handle in fh option not opened");
1178 my $oldfh = select($input->{fh});
1179 # flush anything that's buffered, and make sure anything else is flushed
1182 return io_new_fd($fd);
1184 elsif ($input->{file}) {
1185 my $fh = new IO::File($input->{file},"w+");
1187 $self->_set_error("Could not open file $input->{file}: $!");
1190 binmode($fh) or die;
1191 return (io_new_fd(fileno($fh)), $fh);
1193 elsif ($input->{data}) {
1194 return io_new_bufchain();
1196 elsif ($input->{callback} || $input->{writecb}) {
1197 if ($input->{maxbuffer}) {
1198 return io_new_cb($input->{callback} || $input->{writecb},
1200 $input->{seekcb}, $input->{closecb},
1201 $input->{maxbuffer});
1204 return io_new_cb($input->{callback} || $input->{writecb},
1206 $input->{seekcb}, $input->{closecb});
1210 $self->_set_error("file/fd/fh/data/callback parameter missing");
1215 # Read an image from file
1221 if (defined($self->{IMG})) {
1222 # let IIM_DESTROY do the destruction, since the image may be
1223 # referenced from elsewhere
1224 #i_img_destroy($self->{IMG});
1225 undef($self->{IMG});
1228 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1230 unless ($input{'type'}) {
1231 $input{'type'} = i_test_format_probe($IO, -1);
1234 unless ($input{'type'}) {
1235 $self->_set_error('type parameter missing and not possible to guess from extension');
1239 _reader_autoload($input{type});
1241 if ($readers{$input{type}} && $readers{$input{type}}{single}) {
1242 return $readers{$input{type}}{single}->($self, $IO, %input);
1245 unless ($formats{$input{'type'}}) {
1246 $self->_set_error("format '$input{'type'}' not supported");
1251 if ( $input{'type'} eq 'jpeg' ) {
1252 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1253 if ( !defined($self->{IMG}) ) {
1254 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1256 $self->{DEBUG} && print "loading a jpeg file\n";
1260 if ( $input{'type'} eq 'tiff' ) {
1261 my $page = $input{'page'};
1262 defined $page or $page = 0;
1263 # Fixme, check if that length parameter is ever needed
1264 $self->{IMG}=i_readtiff_wiol( $IO, -1, $page );
1265 if ( !defined($self->{IMG}) ) {
1266 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1268 $self->{DEBUG} && print "loading a tiff file\n";
1272 if ( $input{'type'} eq 'pnm' ) {
1273 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1274 if ( !defined($self->{IMG}) ) {
1275 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1278 $self->{DEBUG} && print "loading a pnm file\n";
1282 if ( $input{'type'} eq 'png' ) {
1283 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1284 if ( !defined($self->{IMG}) ) {
1285 $self->{ERRSTR} = $self->_error_as_msg();
1288 $self->{DEBUG} && print "loading a png file\n";
1291 if ( $input{'type'} eq 'bmp' ) {
1292 $self->{IMG}=i_readbmp_wiol( $IO );
1293 if ( !defined($self->{IMG}) ) {
1294 $self->{ERRSTR}=$self->_error_as_msg();
1297 $self->{DEBUG} && print "loading a bmp file\n";
1300 if ( $input{'type'} eq 'gif' ) {
1301 if ($input{colors} && !ref($input{colors})) {
1302 # must be a reference to a scalar that accepts the colour map
1303 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1306 if ($input{'gif_consolidate'}) {
1307 if ($input{colors}) {
1309 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1311 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1315 $self->{IMG} =i_readgif_wiol( $IO );
1319 my $page = $input{'page'};
1320 defined $page or $page = 0;
1321 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1322 if ($input{colors}) {
1323 ${ $input{colors} } =
1324 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1328 if ( !defined($self->{IMG}) ) {
1329 $self->{ERRSTR}=$self->_error_as_msg();
1332 $self->{DEBUG} && print "loading a gif file\n";
1335 if ( $input{'type'} eq 'tga' ) {
1336 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1337 if ( !defined($self->{IMG}) ) {
1338 $self->{ERRSTR}=$self->_error_as_msg();
1341 $self->{DEBUG} && print "loading a tga file\n";
1344 if ( $input{'type'} eq 'rgb' ) {
1345 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1346 if ( !defined($self->{IMG}) ) {
1347 $self->{ERRSTR}=$self->_error_as_msg();
1350 $self->{DEBUG} && print "loading a tga file\n";
1354 if ( $input{'type'} eq 'raw' ) {
1355 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1357 if ( !($params{xsize} && $params{ysize}) ) {
1358 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1362 $self->{IMG} = i_readraw_wiol( $IO,
1365 $params{datachannels},
1366 $params{storechannels},
1367 $params{interleave});
1368 if ( !defined($self->{IMG}) ) {
1369 $self->{ERRSTR}=$self->_error_as_msg();
1372 $self->{DEBUG} && print "loading a raw file\n";
1378 sub register_reader {
1379 my ($class, %opts) = @_;
1382 or die "register_reader called with no type parameter\n";
1384 my $type = $opts{type};
1386 defined $opts{single} || defined $opts{multiple}
1387 or die "register_reader called with no single or multiple parameter\n";
1389 $readers{$type} = { };
1390 if ($opts{single}) {
1391 $readers{$type}{single} = $opts{single};
1393 if ($opts{multiple}) {
1394 $readers{$type}{multiple} = $opts{multiple};
1400 sub register_writer {
1401 my ($class, %opts) = @_;
1404 or die "register_writer called with no type parameter\n";
1406 my $type = $opts{type};
1408 defined $opts{single} || defined $opts{multiple}
1409 or die "register_writer called with no single or multiple parameter\n";
1411 $writers{$type} = { };
1412 if ($opts{single}) {
1413 $writers{$type}{single} = $opts{single};
1415 if ($opts{multiple}) {
1416 $writers{$type}{multiple} = $opts{multiple};
1422 # probes for an Imager::File::whatever module
1423 sub _reader_autoload {
1426 return if $formats{$type} || $readers{$type};
1428 return unless $type =~ /^\w+$/;
1430 my $file = "Imager/File/\U$type\E.pm";
1432 unless ($attempted_to_load{$file}) {
1434 ++$attempted_to_load{$file};
1438 # try to get a reader specific module
1439 my $file = "Imager/File/\U$type\EReader.pm";
1440 unless ($attempted_to_load{$file}) {
1442 ++$attempted_to_load{$file};
1450 # probes for an Imager::File::whatever module
1451 sub _writer_autoload {
1454 return if $formats{$type} || $readers{$type};
1456 return unless $type =~ /^\w+$/;
1458 my $file = "Imager/File/\U$type\E.pm";
1460 unless ($attempted_to_load{$file}) {
1462 ++$attempted_to_load{$file};
1466 # try to get a writer specific module
1467 my $file = "Imager/File/\U$type\EWriter.pm";
1468 unless ($attempted_to_load{$file}) {
1470 ++$attempted_to_load{$file};
1478 sub _fix_gif_positions {
1479 my ($opts, $opt, $msg, @imgs) = @_;
1481 my $positions = $opts->{'gif_positions'};
1483 for my $pos (@$positions) {
1484 my ($x, $y) = @$pos;
1485 my $img = $imgs[$index++];
1486 $img->settag(name=>'gif_left', value=>$x);
1487 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1489 $$msg .= "replaced with the gif_left and gif_top tags";
1494 gif_each_palette=>'gif_local_map',
1495 interlace => 'gif_interlace',
1496 gif_delays => 'gif_delay',
1497 gif_positions => \&_fix_gif_positions,
1498 gif_loop_count => 'gif_loop',
1502 my ($self, $opts, $prefix, @imgs) = @_;
1504 for my $opt (keys %$opts) {
1506 if ($obsolete_opts{$opt}) {
1507 my $new = $obsolete_opts{$opt};
1508 my $msg = "Obsolete option $opt ";
1510 $new->($opts, $opt, \$msg, @imgs);
1513 $msg .= "replaced with the $new tag ";
1516 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1517 warn $msg if $warn_obsolete && $^W;
1519 next unless $tagname =~ /^\Q$prefix/;
1520 my $value = $opts->{$opt};
1522 if (UNIVERSAL::isa($value, "Imager::Color")) {
1523 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1524 for my $img (@imgs) {
1525 $img->settag(name=>$tagname, value=>$tag);
1528 elsif (ref($value) eq 'ARRAY') {
1529 for my $i (0..$#$value) {
1530 my $val = $value->[$i];
1532 if (UNIVERSAL::isa($val, "Imager::Color")) {
1533 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1535 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1538 $self->_set_error("Unknown reference type " . ref($value) .
1539 " supplied in array for $opt");
1545 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1550 $self->_set_error("Unknown reference type " . ref($value) .
1551 " supplied for $opt");
1556 # set it as a tag for every image
1557 for my $img (@imgs) {
1558 $img->settag(name=>$tagname, value=>$value);
1566 # Write an image to file
1569 my %input=(jpegquality=>75,
1579 $self->_set_opts(\%input, "i_", $self)
1582 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1584 if (!$input{'type'} and $input{file}) {
1585 $input{'type'}=$FORMATGUESS->($input{file});
1587 if (!$input{'type'}) {
1588 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1592 _writer_autoload($input{type});
1595 if ($writers{$input{type}} && $writers{$input{type}}{single}) {
1596 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1599 $writers{$input{type}}{single}->($self, $IO, %input)
1603 if (!$formats{$input{'type'}}) {
1604 $self->{ERRSTR}='format not supported';
1608 ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1611 if ($input{'type'} eq 'tiff') {
1612 $self->_set_opts(\%input, "tiff_", $self)
1614 $self->_set_opts(\%input, "exif_", $self)
1617 if (defined $input{class} && $input{class} eq 'fax') {
1618 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1619 $self->{ERRSTR} = $self->_error_as_msg();
1623 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1624 $self->{ERRSTR} = $self->_error_as_msg();
1628 } elsif ( $input{'type'} eq 'pnm' ) {
1629 $self->_set_opts(\%input, "pnm_", $self)
1631 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1632 $self->{ERRSTR} = $self->_error_as_msg();
1635 $self->{DEBUG} && print "writing a pnm file\n";
1636 } elsif ( $input{'type'} eq 'raw' ) {
1637 $self->_set_opts(\%input, "raw_", $self)
1639 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1640 $self->{ERRSTR} = $self->_error_as_msg();
1643 $self->{DEBUG} && print "writing a raw file\n";
1644 } elsif ( $input{'type'} eq 'png' ) {
1645 $self->_set_opts(\%input, "png_", $self)
1647 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1648 $self->{ERRSTR}='unable to write png image';
1651 $self->{DEBUG} && print "writing a png file\n";
1652 } elsif ( $input{'type'} eq 'jpeg' ) {
1653 $self->_set_opts(\%input, "jpeg_", $self)
1655 $self->_set_opts(\%input, "exif_", $self)
1657 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1658 $self->{ERRSTR} = $self->_error_as_msg();
1661 $self->{DEBUG} && print "writing a jpeg file\n";
1662 } elsif ( $input{'type'} eq 'bmp' ) {
1663 $self->_set_opts(\%input, "bmp_", $self)
1665 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1666 $self->{ERRSTR}='unable to write bmp image';
1669 $self->{DEBUG} && print "writing a bmp file\n";
1670 } elsif ( $input{'type'} eq 'tga' ) {
1671 $self->_set_opts(\%input, "tga_", $self)
1674 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1675 $self->{ERRSTR}=$self->_error_as_msg();
1678 $self->{DEBUG} && print "writing a tga file\n";
1679 } elsif ( $input{'type'} eq 'gif' ) {
1680 $self->_set_opts(\%input, "gif_", $self)
1682 # compatibility with the old interfaces
1683 if ($input{gifquant} eq 'lm') {
1684 $input{make_colors} = 'addi';
1685 $input{translate} = 'perturb';
1686 $input{perturb} = $input{lmdither};
1687 } elsif ($input{gifquant} eq 'gen') {
1688 # just pass options through
1690 $input{make_colors} = 'webmap'; # ignored
1691 $input{translate} = 'giflib';
1693 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1694 $self->{ERRSTR} = $self->_error_as_msg;
1700 if (exists $input{'data'}) {
1701 my $data = io_slurp($IO);
1703 $self->{ERRSTR}='Could not slurp from buffer';
1706 ${$input{data}} = $data;
1712 my ($class, $opts, @images) = @_;
1714 my $type = $opts->{type};
1716 if (!$type && $opts->{'file'}) {
1717 $type = $FORMATGUESS->($opts->{'file'});
1720 $class->_set_error('type parameter missing and not possible to guess from extension');
1723 # translate to ImgRaw
1724 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1725 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1728 $class->_set_opts($opts, "i_", @images)
1730 my @work = map $_->{IMG}, @images;
1732 _writer_autoload($type);
1735 if ($writers{$type} && $writers{$type}{multiple}) {
1736 ($IO, $file) = $class->_get_writer_io($opts, $type)
1739 $writers{$type}{multiple}->($class, $IO, $opts, @images)
1743 if (!$formats{$type}) {
1744 $class->_set_error("format $type not supported");
1748 ($IO, $file) = $class->_get_writer_io($opts, $type)
1751 if ($type eq 'gif') {
1752 $class->_set_opts($opts, "gif_", @images)
1754 my $gif_delays = $opts->{gif_delays};
1755 local $opts->{gif_delays} = $gif_delays;
1756 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1757 # assume the caller wants the same delay for each frame
1758 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1760 unless (i_writegif_wiol($IO, $opts, @work)) {
1761 $class->_set_error($class->_error_as_msg());
1765 elsif ($type eq 'tiff') {
1766 $class->_set_opts($opts, "tiff_", @images)
1768 $class->_set_opts($opts, "exif_", @images)
1771 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1772 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1773 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1776 $res = i_writetiff_multi_wiol($IO, @work);
1779 $class->_set_error($class->_error_as_msg());
1784 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
1789 if (exists $opts->{'data'}) {
1790 my $data = io_slurp($IO);
1792 Imager->_set_error('Could not slurp from buffer');
1795 ${$opts->{data}} = $data;
1800 # read multiple images from a file
1802 my ($class, %opts) = @_;
1804 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1807 my $type = $opts{'type'};
1809 $type = i_test_format_probe($IO, -1);
1812 if ($opts{file} && !$type) {
1814 $type = $FORMATGUESS->($opts{file});
1818 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1822 _reader_autoload($type);
1824 if ($readers{$type} && $readers{$type}{multiple}) {
1825 return $readers{$type}{multiple}->($IO, %opts);
1828 if ($type eq 'gif') {
1830 @imgs = i_readgif_multi_wiol($IO);
1833 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1837 $ERRSTR = _error_as_msg();
1841 elsif ($type eq 'tiff') {
1842 my @imgs = i_readtiff_multi_wiol($IO, -1);
1845 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1849 $ERRSTR = _error_as_msg();
1854 $ERRSTR = "Cannot read multiple images from $type files";
1858 # Destroy an Imager object
1862 # delete $instances{$self};
1863 if (defined($self->{IMG})) {
1864 # the following is now handled by the XS DESTROY method for
1865 # Imager::ImgRaw object
1866 # Re-enabling this will break virtual images
1867 # tested for in t/t020masked.t
1868 # i_img_destroy($self->{IMG});
1869 undef($self->{IMG});
1871 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1875 # Perform an inplace filter of an image
1876 # that is the image will be overwritten with the data
1882 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1884 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1886 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1887 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1890 if ($filters{$input{'type'}}{names}) {
1891 my $names = $filters{$input{'type'}}{names};
1892 for my $name (keys %$names) {
1893 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1894 $input{$name} = $names->{$name}{$input{$name}};
1898 if (defined($filters{$input{'type'}}{defaults})) {
1899 %hsh=( image => $self->{IMG},
1901 %{$filters{$input{'type'}}{defaults}},
1904 %hsh=( image => $self->{IMG},
1909 my @cs=@{$filters{$input{'type'}}{callseq}};
1912 if (!defined($hsh{$_})) {
1913 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1918 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1919 &{$filters{$input{'type'}}{callsub}}(%hsh);
1922 chomp($self->{ERRSTR} = $@);
1928 $self->{DEBUG} && print "callseq is: @cs\n";
1929 $self->{DEBUG} && print "matching callseq is: @b\n";
1934 sub register_filter {
1936 my %hsh = ( defaults => {}, @_ );
1939 or die "register_filter() with no type\n";
1940 defined $hsh{callsub}
1941 or die "register_filter() with no callsub\n";
1942 defined $hsh{callseq}
1943 or die "register_filter() with no callseq\n";
1945 exists $filters{$hsh{type}}
1948 $filters{$hsh{type}} = \%hsh;
1953 # Scale an image to requested size and return the scaled version
1957 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1958 my $img = Imager->new();
1959 my $tmp = Imager->new();
1961 my $scalefactor = $opts{scalefactor};
1963 unless (defined wantarray) {
1964 my @caller = caller;
1965 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1969 unless ($self->{IMG}) {
1970 $self->_set_error('empty input image');
1974 # work out the scaling
1975 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1976 my ($xpix, $ypix)=( $opts{xpixels} / $self->getwidth() ,
1977 $opts{ypixels} / $self->getheight() );
1978 if ($opts{'type'} eq 'min') {
1979 $scalefactor = _min($xpix,$ypix);
1981 elsif ($opts{'type'} eq 'max') {
1982 $scalefactor = _max($xpix,$ypix);
1985 $self->_set_error('invalid value for type parameter');
1988 } elsif ($opts{xpixels}) {
1989 $scalefactor = $opts{xpixels} / $self->getwidth();
1991 elsif ($opts{ypixels}) {
1992 $scalefactor = $opts{ypixels}/$self->getheight();
1994 elsif ($opts{constrain} && ref $opts{constrain}
1995 && $opts{constrain}->can('constrain')) {
1996 # we've been passed an Image::Math::Constrain object or something
1997 # that looks like one
1998 (undef, undef, $scalefactor)
1999 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2000 unless ($scalefactor) {
2001 $self->_set_error('constrain method failed on constrain parameter');
2006 if ($opts{qtype} eq 'normal') {
2007 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2008 if ( !defined($tmp->{IMG}) ) {
2009 $self->{ERRSTR} = 'unable to scale image';
2012 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $scalefactor, 1);
2013 if ( !defined($img->{IMG}) ) {
2014 $self->{ERRSTR}='unable to scale image';
2020 elsif ($opts{'qtype'} eq 'preview') {
2021 $img->{IMG} = i_scale_nn($self->{IMG}, $scalefactor, $scalefactor);
2022 if ( !defined($img->{IMG}) ) {
2023 $self->{ERRSTR}='unable to scale image';
2029 $self->_set_error('invalid value for qtype parameter');
2034 # Scales only along the X axis
2038 my %opts = ( scalefactor=>0.5, @_ );
2040 unless (defined wantarray) {
2041 my @caller = caller;
2042 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2046 unless ($self->{IMG}) {
2047 $self->{ERRSTR} = 'empty input image';
2051 my $img = Imager->new();
2053 my $scalefactor = $opts{scalefactor};
2055 if ($opts{pixels}) {
2056 $scalefactor = $opts{pixels} / $self->getwidth();
2059 unless ($self->{IMG}) {
2060 $self->{ERRSTR}='empty input image';
2064 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2066 if ( !defined($img->{IMG}) ) {
2067 $self->{ERRSTR} = 'unable to scale image';
2074 # Scales only along the Y axis
2078 my %opts = ( scalefactor => 0.5, @_ );
2080 unless (defined wantarray) {
2081 my @caller = caller;
2082 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2086 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2088 my $img = Imager->new();
2090 my $scalefactor = $opts{scalefactor};
2092 if ($opts{pixels}) {
2093 $scalefactor = $opts{pixels} / $self->getheight();
2096 unless ($self->{IMG}) {
2097 $self->{ERRSTR} = 'empty input image';
2100 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2102 if ( !defined($img->{IMG}) ) {
2103 $self->{ERRSTR} = 'unable to scale image';
2110 # Transform returns a spatial transformation of the input image
2111 # this moves pixels to a new location in the returned image.
2112 # NOTE - should make a utility function to check transforms for
2117 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2119 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2121 # print Dumper(\%opts);
2124 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2126 eval ("use Affix::Infix2Postfix;");
2129 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2132 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2133 {op=>'-',trans=>'Sub'},
2134 {op=>'*',trans=>'Mult'},
2135 {op=>'/',trans=>'Div'},
2136 {op=>'-','type'=>'unary',trans=>'u-'},
2138 {op=>'func','type'=>'unary'}],
2139 'grouping'=>[qw( \( \) )],
2140 'func'=>[qw( sin cos )],
2145 @xt=$I2P->translate($opts{'xexpr'});
2146 @yt=$I2P->translate($opts{'yexpr'});
2148 $numre=$I2P->{'numre'};
2151 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
2152 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
2153 @{$opts{'parm'}}=@pt;
2156 # print Dumper(\%opts);
2158 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
2159 $self->{ERRSTR}='transform: no xopcodes given.';
2163 @op=@{$opts{'xopcodes'}};
2165 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2166 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2169 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2175 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
2176 $self->{ERRSTR}='transform: no yopcodes given.';
2180 @op=@{$opts{'yopcodes'}};
2182 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2183 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2186 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
2191 if ( !exists $opts{'parm'}) {
2192 $self->{ERRSTR}='transform: no parameter arg given.';
2196 # print Dumper(\@ropx);
2197 # print Dumper(\@ropy);
2198 # print Dumper(\@ropy);
2200 my $img = Imager->new();
2201 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2202 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
2208 my ($opts, @imgs) = @_;
2210 require "Imager/Expr.pm";
2212 $opts->{variables} = [ qw(x y) ];
2213 my ($width, $height) = @{$opts}{qw(width height)};
2215 $width ||= $imgs[0]->getwidth();
2216 $height ||= $imgs[0]->getheight();
2218 for my $img (@imgs) {
2219 $opts->{constants}{"w$img_num"} = $img->getwidth();
2220 $opts->{constants}{"h$img_num"} = $img->getheight();
2221 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2222 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2227 $opts->{constants}{w} = $width;
2228 $opts->{constants}{cx} = $width/2;
2231 $Imager::ERRSTR = "No width supplied";
2235 $opts->{constants}{h} = $height;
2236 $opts->{constants}{cy} = $height/2;
2239 $Imager::ERRSTR = "No height supplied";
2242 my $code = Imager::Expr->new($opts);
2244 $Imager::ERRSTR = Imager::Expr::error();
2247 my $channels = $opts->{channels} || 3;
2248 unless ($channels >= 1 && $channels <= 4) {
2249 return Imager->_set_error("channels must be an integer between 1 and 4");
2252 my $img = Imager->new();
2253 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2254 $channels, $code->code(),
2255 $code->nregs(), $code->cregs(),
2256 [ map { $_->{IMG} } @imgs ]);
2257 if (!defined $img->{IMG}) {
2258 $Imager::ERRSTR = Imager->_error_as_msg();
2267 my %opts=(tx => 0,ty => 0, @_);
2269 unless ($self->{IMG}) {
2270 $self->{ERRSTR}='empty input image';
2273 unless ($opts{src} && $opts{src}->{IMG}) {
2274 $self->{ERRSTR}='empty input image for src';
2278 %opts = (src_minx => 0,
2280 src_maxx => $opts{src}->getwidth(),
2281 src_maxy => $opts{src}->getheight(),
2284 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
2285 $opts{src_minx}, $opts{src_miny},
2286 $opts{src_maxx}, $opts{src_maxy})) {
2287 $self->_set_error($self->_error_as_msg());
2297 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2299 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2300 $dir = $xlate{$opts{'dir'}};
2301 return $self if i_flipxy($self->{IMG}, $dir);
2309 unless (defined wantarray) {
2310 my @caller = caller;
2311 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2315 if (defined $opts{right}) {
2316 my $degrees = $opts{right};
2318 $degrees += 360 * int(((-$degrees)+360)/360);
2320 $degrees = $degrees % 360;
2321 if ($degrees == 0) {
2322 return $self->copy();
2324 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2325 my $result = Imager->new();
2326 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2330 $self->{ERRSTR} = $self->_error_as_msg();
2335 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2339 elsif (defined $opts{radians} || defined $opts{degrees}) {
2340 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2342 my $back = $opts{back};
2343 my $result = Imager->new;
2345 $back = _color($back);
2347 $self->_set_error(Imager->errstr);
2351 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2354 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2356 if ($result->{IMG}) {
2360 $self->{ERRSTR} = $self->_error_as_msg();
2365 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2370 sub matrix_transform {
2374 unless (defined wantarray) {
2375 my @caller = caller;
2376 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2380 if ($opts{matrix}) {
2381 my $xsize = $opts{xsize} || $self->getwidth;
2382 my $ysize = $opts{ysize} || $self->getheight;
2384 my $result = Imager->new;
2386 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2387 $opts{matrix}, $opts{back})
2391 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2399 $self->{ERRSTR} = "matrix parameter required";
2405 *yatf = \&matrix_transform;
2407 # These two are supported for legacy code only
2410 return Imager::Color->new(@_);
2414 return Imager::Color::set(@_);
2417 # Draws a box between the specified corner points.
2420 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2421 my $dflcl=i_color_new(255,255,255,255);
2422 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2424 if (exists $opts{'box'}) {
2425 $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2426 $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2427 $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2428 $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2431 if ($opts{filled}) {
2432 my $color = _color($opts{'color'});
2434 $self->{ERRSTR} = $Imager::ERRSTR;
2437 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2438 $opts{ymax}, $color);
2440 elsif ($opts{fill}) {
2441 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2442 # assume it's a hash ref
2443 require 'Imager/Fill.pm';
2444 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2445 $self->{ERRSTR} = $Imager::ERRSTR;
2449 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2450 $opts{ymax},$opts{fill}{fill});
2453 my $color = _color($opts{'color'});
2455 $self->{ERRSTR} = $Imager::ERRSTR;
2458 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2466 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2467 my $dflcl=i_color_new(255,255,255,255);
2468 my %opts=(color=>$dflcl,
2469 'r'=>_min($self->getwidth(),$self->getheight())/3,
2470 'x'=>$self->getwidth()/2,
2471 'y'=>$self->getheight()/2,
2472 'd1'=>0, 'd2'=>361, @_);
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_aa_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 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2493 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2497 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2498 $opts{'d1'}, $opts{'d2'}, $color);
2504 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2505 # assume it's a hash ref
2506 require 'Imager/Fill.pm';
2507 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2508 $self->{ERRSTR} = $Imager::ERRSTR;
2512 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2513 $opts{'d2'}, $opts{fill}{fill});
2516 my $color = _color($opts{'color'});
2518 $self->{ERRSTR} = $Imager::ERRSTR;
2521 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2522 $opts{'d1'}, $opts{'d2'}, $color);
2529 # Draws a line from one point to the other
2530 # the endpoint is set if the endp parameter is set which it is by default.
2531 # to turn of the endpoint being set use endp=>0 when calling line.
2535 my $dflcl=i_color_new(0,0,0,0);
2536 my %opts=(color=>$dflcl,
2539 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2541 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2542 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2544 my $color = _color($opts{'color'});
2546 $self->{ERRSTR} = $Imager::ERRSTR;
2550 $opts{antialias} = $opts{aa} if defined $opts{aa};
2551 if ($opts{antialias}) {
2552 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2553 $color, $opts{endp});
2555 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2556 $color, $opts{endp});
2561 # Draws a line between an ordered set of points - It more or less just transforms this
2562 # into a list of lines.
2566 my ($pt,$ls,@points);
2567 my $dflcl=i_color_new(0,0,0,0);
2568 my %opts=(color=>$dflcl,@_);
2570 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2572 if (exists($opts{points})) { @points=@{$opts{points}}; }
2573 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2574 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2577 # print Dumper(\@points);
2579 my $color = _color($opts{'color'});
2581 $self->{ERRSTR} = $Imager::ERRSTR;
2584 $opts{antialias} = $opts{aa} if defined $opts{aa};
2585 if ($opts{antialias}) {
2588 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2595 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2605 my ($pt,$ls,@points);
2606 my $dflcl = i_color_new(0,0,0,0);
2607 my %opts = (color=>$dflcl, @_);
2609 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2611 if (exists($opts{points})) {
2612 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2613 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2616 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2617 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2620 if ($opts{'fill'}) {
2621 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2622 # assume it's a hash ref
2623 require 'Imager/Fill.pm';
2624 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2625 $self->{ERRSTR} = $Imager::ERRSTR;
2629 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2630 $opts{'fill'}{'fill'});
2633 my $color = _color($opts{'color'});
2635 $self->{ERRSTR} = $Imager::ERRSTR;
2638 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2645 # this the multipoint bezier curve
2646 # this is here more for testing that actual usage since
2647 # this is not a good algorithm. Usually the curve would be
2648 # broken into smaller segments and each done individually.
2652 my ($pt,$ls,@points);
2653 my $dflcl=i_color_new(0,0,0,0);
2654 my %opts=(color=>$dflcl,@_);
2656 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2658 if (exists $opts{points}) {
2659 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2660 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2663 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2664 $self->{ERRSTR}='Missing or invalid points.';
2668 my $color = _color($opts{'color'});
2670 $self->{ERRSTR} = $Imager::ERRSTR;
2673 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2679 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2682 unless (exists $opts{'x'} && exists $opts{'y'}) {
2683 $self->{ERRSTR} = "missing seed x and y parameters";
2687 if ($opts{border}) {
2688 my $border = _color($opts{border});
2690 $self->_set_error($Imager::ERRSTR);
2694 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2695 # assume it's a hash ref
2696 require Imager::Fill;
2697 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2698 $self->{ERRSTR} = $Imager::ERRSTR;
2702 $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2703 $opts{fill}{fill}, $border);
2706 my $color = _color($opts{'color'});
2708 $self->{ERRSTR} = $Imager::ERRSTR;
2711 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
2718 $self->{ERRSTR} = $self->_error_as_msg();
2724 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2725 # assume it's a hash ref
2726 require 'Imager/Fill.pm';
2727 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2728 $self->{ERRSTR} = $Imager::ERRSTR;
2732 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2735 my $color = _color($opts{'color'});
2737 $self->{ERRSTR} = $Imager::ERRSTR;
2740 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2746 $self->{ERRSTR} = $self->_error_as_msg();
2755 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2757 unless (exists $opts{'x'} && exists $opts{'y'}) {
2758 $self->{ERRSTR} = 'missing x and y parameters';
2764 my $color = _color($opts{color})
2766 if (ref $x && ref $y) {
2767 unless (@$x == @$y) {
2768 $self->{ERRSTR} = 'length of x and y mismatch';
2771 if ($color->isa('Imager::Color')) {
2772 for my $i (0..$#{$opts{'x'}}) {
2773 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2777 for my $i (0..$#{$opts{'x'}}) {
2778 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2783 if ($color->isa('Imager::Color')) {
2784 i_ppix($self->{IMG}, $x, $y, $color);
2787 i_ppixf($self->{IMG}, $x, $y, $color);
2797 my %opts = ( "type"=>'8bit', @_);
2799 unless (exists $opts{'x'} && exists $opts{'y'}) {
2800 $self->{ERRSTR} = 'missing x and y parameters';
2806 if (ref $x && ref $y) {
2807 unless (@$x == @$y) {
2808 $self->{ERRSTR} = 'length of x and y mismatch';
2812 if ($opts{"type"} eq '8bit') {
2813 for my $i (0..$#{$opts{'x'}}) {
2814 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2818 for my $i (0..$#{$opts{'x'}}) {
2819 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2822 return wantarray ? @result : \@result;
2825 if ($opts{"type"} eq '8bit') {
2826 return i_get_pixel($self->{IMG}, $x, $y);
2829 return i_gpixf($self->{IMG}, $x, $y);
2838 my %opts = ( type => '8bit', x=>0, @_);
2840 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2842 unless (defined $opts{'y'}) {
2843 $self->_set_error("missing y parameter");
2847 if ($opts{type} eq '8bit') {
2848 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2851 elsif ($opts{type} eq 'float') {
2852 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2856 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2863 my %opts = ( x=>0, @_);
2865 unless (defined $opts{'y'}) {
2866 $self->_set_error("missing y parameter");
2871 if (ref $opts{pixels} && @{$opts{pixels}}) {
2872 # try to guess the type
2873 if ($opts{pixels}[0]->isa('Imager::Color')) {
2874 $opts{type} = '8bit';
2876 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2877 $opts{type} = 'float';
2880 $self->_set_error("missing type parameter and could not guess from pixels");
2886 $opts{type} = '8bit';
2890 if ($opts{type} eq '8bit') {
2891 if (ref $opts{pixels}) {
2892 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2895 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2898 elsif ($opts{type} eq 'float') {
2899 if (ref $opts{pixels}) {
2900 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2903 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2907 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2914 my %opts = ( type => '8bit', x=>0, @_);
2916 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2918 unless (defined $opts{'y'}) {
2919 $self->_set_error("missing y parameter");
2923 unless ($opts{channels}) {
2924 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2927 if ($opts{type} eq '8bit') {
2928 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2929 $opts{y}, @{$opts{channels}});
2931 elsif ($opts{type} eq 'float') {
2932 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2933 $opts{y}, @{$opts{channels}});
2936 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2941 # make an identity matrix of the given size
2945 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2946 for my $c (0 .. ($size-1)) {
2947 $matrix->[$c][$c] = 1;
2952 # general function to convert an image
2954 my ($self, %opts) = @_;
2957 unless (defined wantarray) {
2958 my @caller = caller;
2959 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2963 # the user can either specify a matrix or preset
2964 # the matrix overrides the preset
2965 if (!exists($opts{matrix})) {
2966 unless (exists($opts{preset})) {
2967 $self->{ERRSTR} = "convert() needs a matrix or preset";
2971 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2972 # convert to greyscale, keeping the alpha channel if any
2973 if ($self->getchannels == 3) {
2974 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2976 elsif ($self->getchannels == 4) {
2977 # preserve the alpha channel
2978 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2983 $matrix = _identity($self->getchannels);
2986 elsif ($opts{preset} eq 'noalpha') {
2987 # strip the alpha channel
2988 if ($self->getchannels == 2 or $self->getchannels == 4) {
2989 $matrix = _identity($self->getchannels);
2990 pop(@$matrix); # lose the alpha entry
2993 $matrix = _identity($self->getchannels);
2996 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2998 $matrix = [ [ 1 ] ];
3000 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3001 $matrix = [ [ 0, 1 ] ];
3003 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3004 $matrix = [ [ 0, 0, 1 ] ];
3006 elsif ($opts{preset} eq 'alpha') {
3007 if ($self->getchannels == 2 or $self->getchannels == 4) {
3008 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3011 # the alpha is just 1 <shrug>
3012 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3015 elsif ($opts{preset} eq 'rgb') {
3016 if ($self->getchannels == 1) {
3017 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3019 elsif ($self->getchannels == 2) {
3020 # preserve the alpha channel
3021 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3024 $matrix = _identity($self->getchannels);
3027 elsif ($opts{preset} eq 'addalpha') {
3028 if ($self->getchannels == 1) {
3029 $matrix = _identity(2);
3031 elsif ($self->getchannels == 3) {
3032 $matrix = _identity(4);
3035 $matrix = _identity($self->getchannels);
3039 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3045 $matrix = $opts{matrix};
3048 my $new = Imager->new();
3049 $new->{IMG} = i_img_new();
3050 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
3051 # most likely a bad matrix
3052 $self->{ERRSTR} = _error_as_msg();
3059 # general function to map an image through lookup tables
3062 my ($self, %opts) = @_;
3063 my @chlist = qw( red green blue alpha );
3065 if (!exists($opts{'maps'})) {
3066 # make maps from channel maps
3068 for $chnum (0..$#chlist) {
3069 if (exists $opts{$chlist[$chnum]}) {
3070 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
3071 } elsif (exists $opts{'all'}) {
3072 $opts{'maps'}[$chnum] = $opts{'all'};
3076 if ($opts{'maps'} and $self->{IMG}) {
3077 i_map($self->{IMG}, $opts{'maps'} );
3083 my ($self, %opts) = @_;
3085 defined $opts{mindist} or $opts{mindist} = 0;
3087 defined $opts{other}
3088 or return $self->_set_error("No 'other' parameter supplied");
3089 defined $opts{other}{IMG}
3090 or return $self->_set_error("No image data in 'other' image");
3093 or return $self->_set_error("No image data");
3095 my $result = Imager->new;
3096 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
3098 or return $self->_set_error($self->_error_as_msg());
3103 # destructive border - image is shrunk by one pixel all around
3106 my ($self,%opts)=@_;
3107 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
3108 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
3112 # Get the width of an image
3116 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3117 return (i_img_info($self->{IMG}))[0];
3120 # Get the height of an image
3124 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3125 return (i_img_info($self->{IMG}))[1];
3128 # Get number of channels in an image
3132 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3133 return i_img_getchannels($self->{IMG});
3140 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3141 return i_img_getmask($self->{IMG});
3149 if (!defined($self->{IMG})) {
3150 $self->{ERRSTR} = 'image is empty';
3153 unless (defined $opts{mask}) {
3154 $self->_set_error("mask parameter required");
3157 i_img_setmask( $self->{IMG} , $opts{mask} );
3162 # Get number of colors in an image
3166 my %opts=('maxcolors'=>2**30,@_);
3167 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3168 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
3169 return ($rc==-1? undef : $rc);
3172 # draw string to an image
3176 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3178 my %input=('x'=>0, 'y'=>0, @_);
3179 $input{string}||=$input{text};
3181 unless(defined $input{string}) {
3182 $self->{ERRSTR}="missing required parameter 'string'";
3186 unless($input{font}) {
3187 $self->{ERRSTR}="missing required parameter 'font'";
3191 unless ($input{font}->draw(image=>$self, %input)) {
3203 unless ($self->{IMG}) {
3204 $self->{ERRSTR}='empty input image';
3213 my %input=('x'=>0, 'y'=>0, @_);
3214 $input{string}||=$input{text};
3216 unless(exists $input{string}) {
3217 $self->_set_error("missing required parameter 'string'");
3221 unless($input{font}) {
3222 $self->_set_error("missing required parameter 'font'");
3227 unless (@result = $input{font}->align(image=>$img, %input)) {
3231 return wantarray ? @result : $result[0];
3234 my @file_limit_names = qw/width height bytes/;
3236 sub set_file_limits {
3243 @values{@file_limit_names} = (0) x @file_limit_names;
3246 @values{@file_limit_names} = i_get_image_file_limits();
3249 for my $key (keys %values) {
3250 defined $opts{$key} and $values{$key} = $opts{$key};
3253 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
3256 sub get_file_limits {
3257 i_get_image_file_limits();
3260 # Shortcuts that can be exported
3262 sub newcolor { Imager::Color->new(@_); }
3263 sub newfont { Imager::Font->new(@_); }
3265 *NC=*newcolour=*newcolor;
3272 #### Utility routines
3275 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
3279 my ($self, $msg) = @_;
3282 $self->{ERRSTR} = $msg;
3290 # Default guess for the type of an image from extension
3292 sub def_guess_type {
3295 $ext=($name =~ m/\.([^\.]+)$/)[0];
3296 return 'tiff' if ($ext =~ m/^tiff?$/);
3297 return 'jpeg' if ($ext =~ m/^jpe?g$/);
3298 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
3299 return 'png' if ($ext eq "png");
3300 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
3301 return 'tga' if ($ext eq "tga");
3302 return 'rgb' if ($ext eq "rgb");
3303 return 'gif' if ($ext eq "gif");
3304 return 'raw' if ($ext eq "raw");
3305 return lc $ext; # best guess
3309 # get the minimum of a list
3313 for(@_) { if ($_<$mx) { $mx=$_; }}
3317 # get the maximum of a list
3321 for(@_) { if ($_>$mx) { $mx=$_; }}
3325 # string stuff for iptc headers
3329 $str = substr($str,3);
3330 $str =~ s/[\n\r]//g;
3337 # A little hack to parse iptc headers.
3342 my($caption,$photogr,$headln,$credit);
3344 my $str=$self->{IPTCRAW};
3349 @ar=split(/8BIM/,$str);
3354 @sar=split(/\034\002/);
3355 foreach $item (@sar) {
3356 if ($item =~ m/^x/) {
3357 $caption = _clean($item);
3360 if ($item =~ m/^P/) {
3361 $photogr = _clean($item);
3364 if ($item =~ m/^i/) {
3365 $headln = _clean($item);
3368 if ($item =~ m/^n/) {
3369 $credit = _clean($item);
3375 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3382 or die "Only C language supported";
3384 require Imager::ExtUtils;
3385 return Imager::ExtUtils->inline_config;
3390 # Below is the stub of documentation for your module. You better edit it!
3394 Imager - Perl extension for Generating 24 bit Images
3404 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3409 my $img = Imager->new();
3410 # see Imager::Files for information on the read() method
3411 $img->read(file=>$file) or die $img->errstr();
3413 $file =~ s/\.[^.]*$//;
3415 # Create smaller version
3416 # documented in Imager::Transformations
3417 my $thumb = $img->scale(scalefactor=>.3);
3419 # Autostretch individual channels
3420 $thumb->filter(type=>'autolevels');
3422 # try to save in one of these formats
3425 for $format ( qw( png gif jpg tiff ppm ) ) {
3426 # Check if given format is supported
3427 if ($Imager::formats{$format}) {
3428 $file.="_low.$format";
3429 print "Storing image as: $file\n";
3430 # documented in Imager::Files
3431 $thumb->write(file=>$file) or
3439 Imager is a module for creating and altering images. It can read and
3440 write various image formats, draw primitive shapes like lines,and
3441 polygons, blend multiple images together in various ways, scale, crop,
3442 render text and more.
3444 =head2 Overview of documentation
3450 Imager - This document - Synopsis, Example, Table of Contents and
3455 L<Imager::Tutorial> - a brief introduction to Imager.
3459 L<Imager::Cookbook> - how to do various things with Imager.
3463 L<Imager::ImageTypes> - Basics of constructing image objects with
3464 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3465 8/16/double bits/channel, color maps, channel masks, image tags, color
3466 quantization. Also discusses basic image information methods.
3470 L<Imager::Files> - IO interaction, reading/writing images, format
3475 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3480 L<Imager::Color> - Color specification.
3484 L<Imager::Fill> - Fill pattern specification.
3488 L<Imager::Font> - General font rendering, bounding boxes and font
3493 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3494 blending, pasting, convert and map.
3498 L<Imager::Engines> - Programmable transformations through
3499 C<transform()>, C<transform2()> and C<matrix_transform()>.
3503 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3508 L<Imager::Expr> - Expressions for evaluation engine used by
3513 L<Imager::Matrix2d> - Helper class for affine transformations.
3517 L<Imager::Fountain> - Helper for making gradient profiles.
3521 L<Imager::API> - using Imager's C API
3525 L<Imager::APIRef> - API function reference
3529 L<Imager::Inline> - using Imager's C API from Inline::C
3533 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3537 =head2 Basic Overview
3539 An Image object is created with C<$img = Imager-E<gt>new()>.
3542 $img=Imager->new(); # create empty image
3543 $img->read(file=>'lena.png',type=>'png') or # read image from file
3544 die $img->errstr(); # give an explanation
3545 # if something failed
3547 or if you want to create an empty image:
3549 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3551 This example creates a completely black image of width 400 and height
3554 =head1 ERROR HANDLING
3556 In general a method will return false when it fails, if it does use the errstr() method to find out why:
3562 Returns the last error message in that context.
3564 If the last error you received was from calling an object method, such
3565 as read, call errstr() as an object method to find out why:
3567 my $image = Imager->new;
3568 $image->read(file => 'somefile.gif')
3569 or die $image->errstr;
3571 If it was a class method then call errstr() as a class method:
3573 my @imgs = Imager->read_multi(file => 'somefile.gif')
3574 or die Imager->errstr;
3576 Note that in some cases object methods are implemented in terms of
3577 class methods so a failing object method may set both.
3581 The C<Imager-E<gt>new> method is described in detail in
3582 L<Imager::ImageTypes>.
3586 Where to find information on methods for Imager class objects.
3588 addcolors() - L<Imager::ImageTypes/addcolors>
3590 addtag() - L<Imager::ImageTypes/addtag> - add image tags
3592 align_string() - L<Imager::Draw/align_string>
3594 arc() - L<Imager::Draw/arc>
3596 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
3599 box() - L<Imager::Draw/box>
3601 circle() - L<Imager::Draw/circle>
3603 colorcount() - L<Imager::Draw/colorcount>
3605 convert() - L<Imager::Transformations/"Color transformations"> -
3606 transform the color space
3608 copy() - L<Imager::Transformations/copy>
3610 crop() - L<Imager::Transformations/crop> - extract part of an image
3612 def_guess_type() - L<Imager::Files/def_guess_type>
3614 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
3616 difference() - L<Imager::Filters/"Image Difference">
3618 errstr() - L<"Basic Overview">
3620 filter() - L<Imager::Filters>
3622 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
3625 flip() - L<Imager::Transformations/flip>
3627 flood_fill() - L<Imager::Draw/flood_fill>
3629 getchannels() - L<Imager::ImageTypes/getchannels>
3631 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
3633 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
3634 palette, if it has one
3636 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3638 getheight() - L<Imager::ImageTypes/getwidth>
3640 getmask() - L<Imager::ImageTypes/getmask>
3642 getpixel() - L<Imager::Draw/getpixel>
3644 getsamples() - L<Imager::Draw/getsamples>
3646 getscanline() - L<Imager::Draw/getscanline>
3648 getwidth() - L<Imager::ImageTypes/getwidth>
3650 img_set() - L<Imager::ImageTypes/img_set>
3652 init() - L<Imager::ImageTypes/init>
3654 line() - L<Imager::Draw/line>
3656 load_plugin() - L<Imager::Filters/load_plugin>
3658 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3661 masked() - L<Imager::ImageTypes/masked> - make a masked image
3663 matrix_transform() - L<Imager::Engines/matrix_transform>
3665 maxcolors() - L<Imager::ImageTypes/maxcolors>
3667 NC() - L<Imager::Handy/NC>
3669 new() - L<Imager::ImageTypes/new>
3671 newcolor() - L<Imager::Handy/newcolor>
3673 newcolour() - L<Imager::Handy/newcolour>
3675 newfont() - L<Imager::Handy/newfont>
3677 NF() - L<Imager::Handy/NF>
3679 open() - L<Imager::Files> - an alias for read()
3681 parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
3684 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3686 polygon() - L<Imager::Draw/polygon>
3688 polyline() - L<Imager::Draw/polyline>
3690 read() - L<Imager::Files> - read a single image from an image file
3692 read_multi() - L<Imager::Files> - read multiple images from an image
3695 register_filter() - L<Imager::Filters/register_filter>
3697 register_reader() - L<Imager::Filters/register_reader>
3699 register_writer() - L<Imager::Filters/register_writer>
3701 rotate() - L<Imager::Transformations/rotate>
3703 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3704 image and use the alpha channel
3706 scale() - L<Imager::Transformations/scale>
3708 scaleX() - L<Imager::Transformations/scaleX>
3710 scaleY() - L<Imager::Transformations/scaleY>
3712 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
3715 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3717 setmask() - L<Imager::ImageTypes/setmask>
3719 setpixel() - L<Imager::Draw/setpixel>
3721 setscanline() - L<Imager::Draw/setscanline>
3723 settag() - L<Imager::ImageTypes/settag>
3725 string() - L<Imager::Draw/string> - draw text on an image
3727 tags() - L<Imager::ImageTypes/tags> - fetch image tags
3729 to_paletted() - L<Imager::ImageTypes/to_paletted>
3731 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
3733 transform() - L<Imager::Engines/"transform">
3735 transform2() - L<Imager::Engines/"transform2">
3737 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
3739 unload_plugin() - L<Imager::Filters/unload_plugin>
3741 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
3744 write() - L<Imager::Files> - write an image to a file
3746 write_multi() - L<Imager::Files> - write multiple image to an image
3749 =head1 CONCEPT INDEX
3751 animated GIF - L<Imager::File/"Writing an animated GIF">
3753 aspect ratio - L<Imager::ImageTypes/i_xres>,
3754 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3756 blend - alpha blending one image onto another
3757 L<Imager::Transformations/rubthrough>
3759 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3761 boxes, drawing - L<Imager::Draw/box>
3763 changes between image - L<Imager::Filter/"Image Difference">
3765 color - L<Imager::Color>
3767 color names - L<Imager::Color>, L<Imager::Color::Table>
3769 combine modes - L<Imager::Fill/combine>
3771 compare images - L<Imager::Filter/"Image Difference">
3773 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3775 convolution - L<Imager::Filter/conv>
3777 cropping - L<Imager::Transformations/crop>
3779 C<diff> images - L<Imager::Filter/"Image Difference">
3781 dpi - L<Imager::ImageTypes/i_xres>,
3782 L<Imager::Cookbook/"Image spatial resolution">
3784 drawing boxes - L<Imager::Draw/box>
3786 drawing lines - L<Imager::Draw/line>
3788 drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
3790 error message - L<"Basic Overview">
3792 files, font - L<Imager::Font>
3794 files, image - L<Imager::Files>
3796 filling, types of fill - L<Imager::Fill>
3798 filling, boxes - L<Imager::Draw/box>
3800 filling, flood fill - L<Imager::Draw/flood_fill>
3802 flood fill - L<Imager::Draw/flood_fill>
3804 fonts - L<Imager::Font>
3806 fonts, drawing with - L<Imager::Draw/string>,
3807 L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
3809 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3811 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3813 fountain fill - L<Imager::Fill/"Fountain fills">,
3814 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3815 L<Imager::Filters/gradgen>
3817 GIF files - L<Imager::Files/"GIF">
3819 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3821 gradient fill - L<Imager::Fill/"Fountain fills">,
3822 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3823 L<Imager::Filters/gradgen>
3825 guassian blur - L<Imager::Filter/guassian>
3827 hatch fills - L<Imager::Fill/"Hatched fills">
3829 invert image - L<Imager::Filter/hardinvert>
3831 JPEG - L<Imager::Files/"JPEG">
3833 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3835 lines, drawing - L<Imager::Draw/line>
3837 matrix - L<Imager::Matrix2d>,
3838 L<Imager::Transformations/"Matrix Transformations">,
3839 L<Imager::Font/transform>
3841 metadata, image - L<Imager::ImageTypes/"Tags">
3843 mosaic - L<Imager::Filter/mosaic>
3845 noise, filter - L<Imager::Filter/noise>
3847 noise, rendered - L<Imager::Filter/turbnoise>,
3848 L<Imager::Filter/radnoise>
3850 paste - L<Imager::Transformations/paste>,
3851 L<Imager::Transformations/rubthrough>
3853 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
3854 L<Imager::ImageTypes/new>
3856 posterize - L<Imager::Filter/postlevels>
3858 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3860 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3862 rectangles, drawing - L<Imager::Draw/box>
3864 resizing an image - L<Imager::Transformations/scale>,
3865 L<Imager::Transformations/crop>
3867 saving an image - L<Imager::Files>
3869 scaling - L<Imager::Transformations/scale>
3871 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3873 size, image - L<Imager::ImageTypes/getwidth>,
3874 L<Imager::ImageTypes/getheight>
3876 size, text - L<Imager::Font/bounding_box>
3878 tags, image metadata - L<Imager::ImageTypes/"Tags">
3880 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
3881 L<Imager::Font::Wrap>
3883 text, wrapping text in an area - L<Imager::Font::Wrap>
3885 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3887 tiles, color - L<Imager::Filter/mosaic>
3889 unsharp mask - L<Imager::Filter/unsharpmask>
3891 watermark - L<Imager::Filter/watermark>
3893 writing an image to a file - L<Imager::Files>
3897 The best place to get help with Imager is the mailing list.
3899 To subscribe send a message with C<subscribe> in the body to:
3901 imager-devel+request@molar.is
3907 L<http://www.molar.is/en/lists/imager-devel/>
3911 where you can also find the mailing list archive.
3913 You can report bugs by pointing your browser at:
3917 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
3921 Please remember to include the versions of Imager, perl, supporting
3922 libraries, and any relevant code. If you have specific images that
3923 cause the problems, please include those too.
3927 Bugs are listed individually for relevant pod pages.
3931 Arnar M. Hrafnkelsson and Tony Cook (tony@imager.perl.org) among
3932 others. See the README for a complete list.
3936 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
3937 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
3938 L<Imager::Font>(3), L<Imager::Transformations>(3),
3939 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
3940 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
3942 L<http://imager.perl.org/>
3944 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
3946 Other perl imaging modules include:
3948 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).