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
152 XSLoader::load(Imager => $VERSION);
156 push @ISA, 'DynaLoader';
157 bootstrap Imager $VERSION;
162 i_init_fonts(); # Initialize font engines
163 Imager::Font::__init();
164 for(i_list_formats()) { $formats{$_}++; }
166 if ($formats{'t1'}) {
170 if (!$formats{'t1'} and !$formats{'tt'}
171 && !$formats{'ft2'} && !$formats{'w32'}) {
172 $fontstate='no font support';
175 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
179 # the members of the subhashes under %filters are:
180 # callseq - a list of the parameters to the underlying filter in the
181 # order they are passed
182 # callsub - a code ref that takes a named parameter list and calls the
184 # defaults - a hash of default values
185 # names - defines names for value of given parameters so if the names
186 # field is foo=> { bar=>1 }, and the user supplies "bar" as the
187 # foo parameter, the filter will receive 1 for the foo
190 callseq => ['image','intensity'],
191 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
195 callseq => ['image', 'amount', 'subtype'],
196 defaults => { amount=>3,subtype=>0 },
197 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
200 $filters{hardinvert} ={
201 callseq => ['image'],
203 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
206 $filters{autolevels} ={
207 callseq => ['image','lsat','usat','skew'],
208 defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
209 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
212 $filters{turbnoise} ={
213 callseq => ['image'],
214 defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
215 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
218 $filters{radnoise} ={
219 callseq => ['image'],
220 defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
221 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
225 callseq => ['image', 'coef'],
227 callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
232 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
233 defaults => { dist => 0 },
237 my @colors = @{$hsh{colors}};
240 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
244 $filters{nearest_color} ={
245 callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
247 callsub => sub { my %hsh=@_; i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, $hsh{colors}, $hsh{dist}); }
249 $filters{gaussian} = {
250 callseq => [ 'image', 'stddev' ],
252 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
256 callseq => [ qw(image size) ],
257 defaults => { size => 20 },
258 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
262 callseq => [ qw(image bump elevation lightx lighty st) ],
263 defaults => { elevation=>0, st=> 2 },
266 i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
267 $hsh{lightx}, $hsh{lighty}, $hsh{st});
270 $filters{bumpmap_complex} =
272 callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
283 Ia => Imager::Color->new(rgb=>[0,0,0]),
284 Il => Imager::Color->new(rgb=>[255,255,255]),
285 Is => Imager::Color->new(rgb=>[255,255,255]),
289 i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
290 $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
291 $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
295 $filters{postlevels} =
297 callseq => [ qw(image levels) ],
298 defaults => { levels => 10 },
299 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
301 $filters{watermark} =
303 callseq => [ qw(image wmark tx ty pixdiff) ],
304 defaults => { pixdiff=>10, tx=>0, ty=>0 },
308 i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
314 callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
316 ftype => { linear => 0,
322 repeat => { none => 0,
337 multiply => 2, mult => 2,
340 subtract => 5, 'sub' => 5,
350 defaults => { ftype => 0, repeat => 0, combine => 0,
351 super_sample => 0, ssample_param => 4,
354 Imager::Color->new(0,0,0),
355 Imager::Color->new(255, 255, 255),
364 # make sure the segments are specified with colors
366 for my $segment (@{$hsh{segments}}) {
367 my @new_segment = @$segment;
369 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
370 push @segments, \@new_segment;
373 i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
374 $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
375 $hsh{ssample_param}, \@segments);
378 $filters{unsharpmask} =
380 callseq => [ qw(image stddev scale) ],
381 defaults => { stddev=>2.0, scale=>1.0 },
385 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
389 $FORMATGUESS=\&def_guess_type;
399 # NOTE: this might be moved to an import override later on
403 # (look through @_ for special tags, process, and remove them);
405 # print Dumper($pack);
410 m_init_log($_[0],$_[1]);
411 log_entry("Imager $VERSION starting\n", 1);
416 my %parms=(loglevel=>1,@_);
418 init_log($parms{'log'},$parms{'loglevel'});
421 if (exists $parms{'warn_obsolete'}) {
422 $warn_obsolete = $parms{'warn_obsolete'};
425 # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
426 # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
430 if (exists $parms{'t1log'}) {
431 i_init_fonts($parms{'t1log'});
437 print "shutdown code\n";
438 # for(keys %instances) { $instances{$_}->DESTROY(); }
439 malloc_state(); # how do decide if this should be used? -- store something from the import
440 print "Imager exiting\n";
444 # Load a filter plugin
449 my ($DSO_handle,$str)=DSO_open($filename);
450 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
451 my %funcs=DSO_funclist($DSO_handle);
452 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
454 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
456 $DSOs{$filename}=[$DSO_handle,\%funcs];
459 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
460 $DEBUG && print "eval string:\n",$evstr,"\n";
472 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
473 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
474 for(keys %{$funcref}) {
476 $DEBUG && print "unloading: $_\n";
478 my $rc=DSO_close($DSO_handle);
479 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
483 # take the results of i_error() and make a message out of it
485 return join(": ", map $_->[0], i_errors());
488 # this function tries to DWIM for color parameters
489 # color objects are used as is
490 # simple scalars are simply treated as single parameters to Imager::Color->new
491 # hashrefs are treated as named argument lists to Imager::Color->new
492 # arrayrefs are treated as list arguments to Imager::Color->new iff any
494 # other arrayrefs are treated as list arguments to Imager::Color::Float
498 # perl 5.6.0 seems to do weird things to $arg if we don't make an
499 # explicitly stringified copy
500 # I vaguely remember a bug on this on p5p, but couldn't find it
501 # through bugs.perl.org (I had trouble getting it to find any bugs)
502 my $copy = $arg . "";
506 if (UNIVERSAL::isa($arg, "Imager::Color")
507 || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
511 if ($copy =~ /^HASH\(/) {
512 $result = Imager::Color->new(%$arg);
514 elsif ($copy =~ /^ARRAY\(/) {
515 if (grep $_ > 1, @$arg) {
516 $result = Imager::Color->new(@$arg);
519 $result = Imager::Color::Float->new(@$arg);
523 $Imager::ERRSTR = "Not a color";
528 # assume Imager::Color::new knows how to handle it
529 $result = Imager::Color->new($arg);
537 # Methods to be called on objects.
540 # Create a new Imager object takes very few parameters.
541 # usually you call this method and then call open from
542 # the resulting object
549 $self->{IMG}=undef; # Just to indicate what exists
550 $self->{ERRSTR}=undef; #
551 $self->{DEBUG}=$DEBUG;
552 $self->{DEBUG} && print "Initialized Imager\n";
553 if (defined $hsh{xsize} && defined $hsh{ysize}) {
554 unless ($self->img_set(%hsh)) {
555 $Imager::ERRSTR = $self->{ERRSTR};
562 # Copy an entire image with no changes
563 # - if an image has magic the copy of it will not be magical
567 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
569 unless (defined wantarray) {
571 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
575 my $newcopy=Imager->new();
576 $newcopy->{IMG} = i_copy($self->{IMG});
585 unless ($self->{IMG}) {
586 $self->_set_error('empty input image');
589 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
590 my $src = $input{img} || $input{src};
592 $self->_set_error("no source image");
595 $input{left}=0 if $input{left} <= 0;
596 $input{top}=0 if $input{top} <= 0;
598 my($r,$b)=i_img_info($src->{IMG});
599 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
600 my ($src_right, $src_bottom);
601 if ($input{src_coords}) {
602 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
605 if (defined $input{src_maxx}) {
606 $src_right = $input{src_maxx};
608 elsif (defined $input{width}) {
609 if ($input{width} <= 0) {
610 $self->_set_error("paste: width must me positive");
613 $src_right = $src_left + $input{width};
618 if (defined $input{src_maxx}) {
619 $src_bottom = $input{src_maxy};
621 elsif (defined $input{height}) {
622 if ($input{height} < 0) {
623 $self->_set_error("paste: height must be positive");
626 $src_bottom = $src_top + $input{height};
633 $src_right > $r and $src_right = $r;
634 $src_bottom > $r and $src_bottom = $b;
636 if ($src_right <= $src_left
637 || $src_bottom < $src_top) {
638 $self->_set_error("nothing to paste");
642 i_copyto($self->{IMG}, $src->{IMG},
643 $src_left, $src_top, $src_right, $src_bottom,
644 $input{left}, $input{top});
646 return $self; # What should go here??
649 # Crop an image - i.e. return a new image that is smaller
653 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
655 unless (defined wantarray) {
657 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
663 my ($w, $h, $l, $r, $b, $t) =
664 @hsh{qw(width height left right bottom top)};
666 # work through the various possibilities
671 elsif (!defined $r) {
672 $r = $self->getwidth;
684 $l = int(0.5+($self->getwidth()-$w)/2);
689 $r = $self->getwidth;
695 elsif (!defined $b) {
696 $b = $self->getheight;
708 $t=int(0.5+($self->getheight()-$h)/2);
713 $b = $self->getheight;
716 ($l,$r)=($r,$l) if $l>$r;
717 ($t,$b)=($b,$t) if $t>$b;
720 $r > $self->getwidth and $r = $self->getwidth;
722 $b > $self->getheight and $b = $self->getheight;
724 if ($l == $r || $t == $b) {
725 $self->_set_error("resulting image would have no content");
729 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
731 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
736 my ($self, %opts) = @_;
738 $self->{IMG} or return $self->_set_error("Not a valid image");
740 my $x = $opts{xsize} || $self->getwidth;
741 my $y = $opts{ysize} || $self->getheight;
742 my $channels = $opts{channels} || $self->getchannels;
744 my $out = Imager->new;
745 if ($channels == $self->getchannels) {
746 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
749 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
751 unless ($out->{IMG}) {
752 $self->{ERRSTR} = $self->_error_as_msg;
759 # Sets an image to a certain size and channel number
760 # if there was previously data in the image it is discarded
765 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
767 if (defined($self->{IMG})) {
768 # let IIM_DESTROY destroy it, it's possible this image is
769 # referenced from a virtual image (like masked)
770 #i_img_destroy($self->{IMG});
774 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
775 $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
776 $hsh{maxcolors} || 256);
778 elsif ($hsh{bits} eq 'double') {
779 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
781 elsif ($hsh{bits} == 16) {
782 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
785 $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
789 unless ($self->{IMG}) {
790 $self->{ERRSTR} = Imager->_error_as_msg();
797 # created a masked version of the current image
801 $self or return undef;
802 my %opts = (left => 0,
804 right => $self->getwidth,
805 bottom => $self->getheight,
807 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
809 my $result = Imager->new;
810 $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
811 $opts{top}, $opts{right} - $opts{left},
812 $opts{bottom} - $opts{top});
813 # keep references to the mask and base images so they don't
815 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
820 # convert an RGB image into a paletted image
824 if (@_ != 1 && !ref $_[0]) {
831 unless (defined wantarray) {
833 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
837 my $result = Imager->new;
838 $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
840 #print "Type ", i_img_type($result->{IMG}), "\n";
842 if ($result->{IMG}) {
846 $self->{ERRSTR} = $self->_error_as_msg;
851 # convert a paletted (or any image) to an 8-bit/channel RGB images
856 unless (defined wantarray) {
858 warn "to_rgb8() called in void context - to_rgb8() returns the cropped image at $caller[1] line $caller[2]\n";
863 $result = Imager->new;
864 $result->{IMG} = i_img_to_rgb($self->{IMG})
873 my %opts = (colors=>[], @_);
875 @{$opts{colors}} or return undef;
877 $self->{IMG} and i_addcolors($self->{IMG}, @{$opts{colors}});
882 my %opts = (start=>0, colors=>[], @_);
883 @{$opts{colors}} or return undef;
885 $self->{IMG} and i_setcolors($self->{IMG}, $opts{start}, @{$opts{colors}});
891 if (!exists $opts{start} && !exists $opts{count}) {
894 $opts{count} = $self->colorcount;
896 elsif (!exists $opts{count}) {
899 elsif (!exists $opts{start}) {
904 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
908 i_colorcount($_[0]{IMG});
912 i_maxcolors($_[0]{IMG});
918 $opts{color} or return undef;
920 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
925 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
926 if ($bits && $bits == length(pack("d", 1)) * 8) {
935 return i_img_type($self->{IMG}) ? "paletted" : "direct";
941 $self->{IMG} and i_img_virtual($self->{IMG});
945 my ($self, %opts) = @_;
947 $self->{IMG} or return;
949 if (defined $opts{name}) {
953 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
954 push @result, (i_tags_get($self->{IMG}, $found))[1];
957 return wantarray ? @result : $result[0];
959 elsif (defined $opts{code}) {
963 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
964 push @result, (i_tags_get($self->{IMG}, $found))[1];
971 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
974 return i_tags_count($self->{IMG});
983 return -1 unless $self->{IMG};
985 if (defined $opts{value}) {
986 if ($opts{value} =~ /^\d+$/) {
988 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
991 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
994 elsif (defined $opts{data}) {
995 # force addition as a string
996 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
999 $self->{ERRSTR} = "No value supplied";
1003 elsif ($opts{code}) {
1004 if (defined $opts{value}) {
1005 if ($opts{value} =~ /^\d+$/) {
1007 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1010 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1013 elsif (defined $opts{data}) {
1014 # force addition as a string
1015 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1018 $self->{ERRSTR} = "No value supplied";
1031 return 0 unless $self->{IMG};
1033 if (defined $opts{'index'}) {
1034 return i_tags_delete($self->{IMG}, $opts{'index'});
1036 elsif (defined $opts{name}) {
1037 return i_tags_delbyname($self->{IMG}, $opts{name});
1039 elsif (defined $opts{code}) {
1040 return i_tags_delbycode($self->{IMG}, $opts{code});
1043 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1049 my ($self, %opts) = @_;
1052 $self->deltag(name=>$opts{name});
1053 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1055 elsif (defined $opts{code}) {
1056 $self->deltag(code=>$opts{code});
1057 return $self->addtag(code=>$opts{code}, value=>$opts{value});
1065 sub _get_reader_io {
1066 my ($self, $input) = @_;
1069 return $input->{io}, undef;
1071 elsif ($input->{fd}) {
1072 return io_new_fd($input->{fd});
1074 elsif ($input->{fh}) {
1075 my $fd = fileno($input->{fh});
1077 $self->_set_error("Handle in fh option not opened");
1080 return io_new_fd($fd);
1082 elsif ($input->{file}) {
1083 my $file = IO::File->new($input->{file}, "r");
1085 $self->_set_error("Could not open $input->{file}: $!");
1089 return (io_new_fd(fileno($file)), $file);
1091 elsif ($input->{data}) {
1092 return io_new_buffer($input->{data});
1094 elsif ($input->{callback} || $input->{readcb}) {
1095 if (!$input->{seekcb}) {
1096 $self->_set_error("Need a seekcb parameter");
1098 if ($input->{maxbuffer}) {
1099 return io_new_cb($input->{writecb},
1100 $input->{callback} || $input->{readcb},
1101 $input->{seekcb}, $input->{closecb},
1102 $input->{maxbuffer});
1105 return io_new_cb($input->{writecb},
1106 $input->{callback} || $input->{readcb},
1107 $input->{seekcb}, $input->{closecb});
1111 $self->_set_error("file/fd/fh/data/callback parameter missing");
1116 sub _get_writer_io {
1117 my ($self, $input, $type) = @_;
1120 return io_new_fd($input->{fd});
1122 elsif ($input->{fh}) {
1123 my $fd = fileno($input->{fh});
1125 $self->_set_error("Handle in fh option not opened");
1129 my $oldfh = select($input->{fh});
1130 # flush anything that's buffered, and make sure anything else is flushed
1133 return io_new_fd($fd);
1135 elsif ($input->{file}) {
1136 my $fh = new IO::File($input->{file},"w+");
1138 $self->_set_error("Could not open file $input->{file}: $!");
1141 binmode($fh) or die;
1142 return (io_new_fd(fileno($fh)), $fh);
1144 elsif ($input->{data}) {
1145 return io_new_bufchain();
1147 elsif ($input->{callback} || $input->{writecb}) {
1148 if ($input->{maxbuffer}) {
1149 return io_new_cb($input->{callback} || $input->{writecb},
1151 $input->{seekcb}, $input->{closecb},
1152 $input->{maxbuffer});
1155 return io_new_cb($input->{callback} || $input->{writecb},
1157 $input->{seekcb}, $input->{closecb});
1161 $self->_set_error("file/fd/fh/data/callback parameter missing");
1166 # Read an image from file
1172 if (defined($self->{IMG})) {
1173 # let IIM_DESTROY do the destruction, since the image may be
1174 # referenced from elsewhere
1175 #i_img_destroy($self->{IMG});
1176 undef($self->{IMG});
1179 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1181 unless ($input{'type'}) {
1182 $input{'type'} = i_test_format_probe($IO, -1);
1185 unless ($input{'type'}) {
1186 $self->_set_error('type parameter missing and not possible to guess from extension');
1190 unless ($formats{$input{'type'}}) {
1191 $self->_set_error("format '$input{'type'}' not supported");
1196 if ( $input{'type'} eq 'jpeg' ) {
1197 ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
1198 if ( !defined($self->{IMG}) ) {
1199 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1201 $self->{DEBUG} && print "loading a jpeg file\n";
1205 if ( $input{'type'} eq 'tiff' ) {
1206 my $page = $input{'page'};
1207 defined $page or $page = 0;
1208 # Fixme, check if that length parameter is ever needed
1209 $self->{IMG}=i_readtiff_wiol( $IO, -1, $page );
1210 if ( !defined($self->{IMG}) ) {
1211 $self->{ERRSTR}=$self->_error_as_msg(); return undef;
1213 $self->{DEBUG} && print "loading a tiff file\n";
1217 if ( $input{'type'} eq 'pnm' ) {
1218 $self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1219 if ( !defined($self->{IMG}) ) {
1220 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1223 $self->{DEBUG} && print "loading a pnm file\n";
1227 if ( $input{'type'} eq 'png' ) {
1228 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1229 if ( !defined($self->{IMG}) ) {
1230 $self->{ERRSTR} = $self->_error_as_msg();
1233 $self->{DEBUG} && print "loading a png file\n";
1236 if ( $input{'type'} eq 'bmp' ) {
1237 $self->{IMG}=i_readbmp_wiol( $IO );
1238 if ( !defined($self->{IMG}) ) {
1239 $self->{ERRSTR}=$self->_error_as_msg();
1242 $self->{DEBUG} && print "loading a bmp file\n";
1245 if ( $input{'type'} eq 'gif' ) {
1246 if ($input{colors} && !ref($input{colors})) {
1247 # must be a reference to a scalar that accepts the colour map
1248 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1251 if ($input{'gif_consolidate'}) {
1252 if ($input{colors}) {
1254 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1256 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1260 $self->{IMG} =i_readgif_wiol( $IO );
1264 my $page = $input{'page'};
1265 defined $page or $page = 0;
1266 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1267 if ($input{colors}) {
1268 ${ $input{colors} } =
1269 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1273 if ( !defined($self->{IMG}) ) {
1274 $self->{ERRSTR}=$self->_error_as_msg();
1277 $self->{DEBUG} && print "loading a gif file\n";
1280 if ( $input{'type'} eq 'tga' ) {
1281 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1282 if ( !defined($self->{IMG}) ) {
1283 $self->{ERRSTR}=$self->_error_as_msg();
1286 $self->{DEBUG} && print "loading a tga file\n";
1289 if ( $input{'type'} eq 'rgb' ) {
1290 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1291 if ( !defined($self->{IMG}) ) {
1292 $self->{ERRSTR}=$self->_error_as_msg();
1295 $self->{DEBUG} && print "loading a tga file\n";
1299 if ( $input{'type'} eq 'raw' ) {
1300 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1302 if ( !($params{xsize} && $params{ysize}) ) {
1303 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1307 $self->{IMG} = i_readraw_wiol( $IO,
1310 $params{datachannels},
1311 $params{storechannels},
1312 $params{interleave});
1313 if ( !defined($self->{IMG}) ) {
1314 $self->{ERRSTR}=$self->_error_as_msg();
1317 $self->{DEBUG} && print "loading a raw file\n";
1323 sub _fix_gif_positions {
1324 my ($opts, $opt, $msg, @imgs) = @_;
1326 my $positions = $opts->{'gif_positions'};
1328 for my $pos (@$positions) {
1329 my ($x, $y) = @$pos;
1330 my $img = $imgs[$index++];
1331 $img->settag(name=>'gif_left', value=>$x);
1332 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1334 $$msg .= "replaced with the gif_left and gif_top tags";
1339 gif_each_palette=>'gif_local_map',
1340 interlace => 'gif_interlace',
1341 gif_delays => 'gif_delay',
1342 gif_positions => \&_fix_gif_positions,
1343 gif_loop_count => 'gif_loop',
1347 my ($self, $opts, $prefix, @imgs) = @_;
1349 for my $opt (keys %$opts) {
1351 if ($obsolete_opts{$opt}) {
1352 my $new = $obsolete_opts{$opt};
1353 my $msg = "Obsolete option $opt ";
1355 $new->($opts, $opt, \$msg, @imgs);
1358 $msg .= "replaced with the $new tag ";
1361 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1362 warn $msg if $warn_obsolete && $^W;
1364 next unless $tagname =~ /^\Q$prefix/;
1365 my $value = $opts->{$opt};
1367 if (UNIVERSAL::isa($value, "Imager::Color")) {
1368 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1369 for my $img (@imgs) {
1370 $img->settag(name=>$tagname, value=>$tag);
1373 elsif (ref($value) eq 'ARRAY') {
1374 for my $i (0..$#$value) {
1375 my $val = $value->[$i];
1377 if (UNIVERSAL::isa($val, "Imager::Color")) {
1378 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1380 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1383 $self->_set_error("Unknown reference type " . ref($value) .
1384 " supplied in array for $opt");
1390 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1395 $self->_set_error("Unknown reference type " . ref($value) .
1396 " supplied for $opt");
1401 # set it as a tag for every image
1402 for my $img (@imgs) {
1403 $img->settag(name=>$tagname, value=>$value);
1411 # Write an image to file
1414 my %input=(jpegquality=>75,
1424 $self->_set_opts(\%input, "i_", $self)
1427 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1429 if (!$input{'type'} and $input{file}) {
1430 $input{'type'}=$FORMATGUESS->($input{file});
1432 if (!$input{'type'}) {
1433 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1437 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1439 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1442 if ($input{'type'} eq 'tiff') {
1443 $self->_set_opts(\%input, "tiff_", $self)
1445 $self->_set_opts(\%input, "exif_", $self)
1448 if (defined $input{class} && $input{class} eq 'fax') {
1449 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1450 $self->{ERRSTR} = $self->_error_as_msg();
1454 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1455 $self->{ERRSTR} = $self->_error_as_msg();
1459 } elsif ( $input{'type'} eq 'pnm' ) {
1460 $self->_set_opts(\%input, "pnm_", $self)
1462 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1463 $self->{ERRSTR} = $self->_error_as_msg();
1466 $self->{DEBUG} && print "writing a pnm file\n";
1467 } elsif ( $input{'type'} eq 'raw' ) {
1468 $self->_set_opts(\%input, "raw_", $self)
1470 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1471 $self->{ERRSTR} = $self->_error_as_msg();
1474 $self->{DEBUG} && print "writing a raw file\n";
1475 } elsif ( $input{'type'} eq 'png' ) {
1476 $self->_set_opts(\%input, "png_", $self)
1478 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1479 $self->{ERRSTR}='unable to write png image';
1482 $self->{DEBUG} && print "writing a png file\n";
1483 } elsif ( $input{'type'} eq 'jpeg' ) {
1484 $self->_set_opts(\%input, "jpeg_", $self)
1486 $self->_set_opts(\%input, "exif_", $self)
1488 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1489 $self->{ERRSTR} = $self->_error_as_msg();
1492 $self->{DEBUG} && print "writing a jpeg file\n";
1493 } elsif ( $input{'type'} eq 'bmp' ) {
1494 $self->_set_opts(\%input, "bmp_", $self)
1496 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1497 $self->{ERRSTR}='unable to write bmp image';
1500 $self->{DEBUG} && print "writing a bmp file\n";
1501 } elsif ( $input{'type'} eq 'tga' ) {
1502 $self->_set_opts(\%input, "tga_", $self)
1505 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1506 $self->{ERRSTR}=$self->_error_as_msg();
1509 $self->{DEBUG} && print "writing a tga file\n";
1510 } elsif ( $input{'type'} eq 'gif' ) {
1511 $self->_set_opts(\%input, "gif_", $self)
1513 # compatibility with the old interfaces
1514 if ($input{gifquant} eq 'lm') {
1515 $input{make_colors} = 'addi';
1516 $input{translate} = 'perturb';
1517 $input{perturb} = $input{lmdither};
1518 } elsif ($input{gifquant} eq 'gen') {
1519 # just pass options through
1521 $input{make_colors} = 'webmap'; # ignored
1522 $input{translate} = 'giflib';
1524 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1525 $self->{ERRSTR} = $self->_error_as_msg;
1530 if (exists $input{'data'}) {
1531 my $data = io_slurp($IO);
1533 $self->{ERRSTR}='Could not slurp from buffer';
1536 ${$input{data}} = $data;
1542 my ($class, $opts, @images) = @_;
1544 if (!$opts->{'type'} && $opts->{'file'}) {
1545 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1547 unless ($opts->{'type'}) {
1548 $class->_set_error('type parameter missing and not possible to guess from extension');
1551 # translate to ImgRaw
1552 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1553 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1556 $class->_set_opts($opts, "i_", @images)
1558 my @work = map $_->{IMG}, @images;
1559 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1561 if ($opts->{'type'} eq 'gif') {
1562 $class->_set_opts($opts, "gif_", @images)
1564 my $gif_delays = $opts->{gif_delays};
1565 local $opts->{gif_delays} = $gif_delays;
1566 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1567 # assume the caller wants the same delay for each frame
1568 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1570 my $res = i_writegif_wiol($IO, $opts, @work);
1571 $res or $class->_set_error($class->_error_as_msg());
1574 elsif ($opts->{'type'} eq 'tiff') {
1575 $class->_set_opts($opts, "tiff_", @images)
1577 $class->_set_opts($opts, "exif_", @images)
1580 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1581 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1582 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1585 $res = i_writetiff_multi_wiol($IO, @work);
1587 $res or $class->_set_error($class->_error_as_msg());
1591 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1596 # read multiple images from a file
1598 my ($class, %opts) = @_;
1600 if ($opts{file} && !exists $opts{'type'}) {
1602 my $type = $FORMATGUESS->($opts{file});
1603 $opts{'type'} = $type;
1605 unless ($opts{'type'}) {
1606 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1610 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1612 if ($opts{'type'} eq 'gif') {
1614 @imgs = i_readgif_multi_wiol($IO);
1617 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1621 $ERRSTR = _error_as_msg();
1625 elsif ($opts{'type'} eq 'tiff') {
1626 my @imgs = i_readtiff_multi_wiol($IO, -1);
1629 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1633 $ERRSTR = _error_as_msg();
1638 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1642 # Destroy an Imager object
1646 # delete $instances{$self};
1647 if (defined($self->{IMG})) {
1648 # the following is now handled by the XS DESTROY method for
1649 # Imager::ImgRaw object
1650 # Re-enabling this will break virtual images
1651 # tested for in t/t020masked.t
1652 # i_img_destroy($self->{IMG});
1653 undef($self->{IMG});
1655 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1659 # Perform an inplace filter of an image
1660 # that is the image will be overwritten with the data
1666 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1668 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1670 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1671 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1674 if ($filters{$input{'type'}}{names}) {
1675 my $names = $filters{$input{'type'}}{names};
1676 for my $name (keys %$names) {
1677 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1678 $input{$name} = $names->{$name}{$input{$name}};
1682 if (defined($filters{$input{'type'}}{defaults})) {
1683 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1685 %hsh=('image',$self->{IMG},%input);
1688 my @cs=@{$filters{$input{'type'}}{callseq}};
1691 if (!defined($hsh{$_})) {
1692 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1697 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1698 &{$filters{$input{'type'}}{callsub}}(%hsh);
1701 chomp($self->{ERRSTR} = $@);
1707 $self->{DEBUG} && print "callseq is: @cs\n";
1708 $self->{DEBUG} && print "matching callseq is: @b\n";
1713 sub register_filter {
1715 my %hsh = ( defaults => {}, @_ );
1718 or die "register_filter() with no type\n";
1719 defined $hsh{callsub}
1720 or die "register_filter() with no callsub\n";
1721 defined $hsh{callseq}
1722 or die "register_filter() with no callseq\n";
1724 exists $filters{$hsh{type}}
1727 $filters{$hsh{type}} = \%hsh;
1732 # Scale an image to requested size and return the scaled version
1736 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1737 my $img = Imager->new();
1738 my $tmp = Imager->new();
1740 unless (defined wantarray) {
1741 my @caller = caller;
1742 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1746 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1748 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1749 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1750 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1751 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1752 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1753 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1755 if ($opts{qtype} eq 'normal') {
1756 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1757 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1758 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1759 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1762 if ($opts{'qtype'} eq 'preview') {
1763 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1764 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1767 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1770 # Scales only along the X axis
1774 my %opts=(scalefactor=>0.5,@_);
1776 unless (defined wantarray) {
1777 my @caller = caller;
1778 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1782 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1784 my $img = Imager->new();
1786 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1788 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1789 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1791 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1795 # Scales only along the Y axis
1799 my %opts=(scalefactor=>0.5,@_);
1801 unless (defined wantarray) {
1802 my @caller = caller;
1803 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1807 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1809 my $img = Imager->new();
1811 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1813 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1814 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1816 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1821 # Transform returns a spatial transformation of the input image
1822 # this moves pixels to a new location in the returned image.
1823 # NOTE - should make a utility function to check transforms for
1828 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1830 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1832 # print Dumper(\%opts);
1835 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1837 eval ("use Affix::Infix2Postfix;");
1840 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1843 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1844 {op=>'-',trans=>'Sub'},
1845 {op=>'*',trans=>'Mult'},
1846 {op=>'/',trans=>'Div'},
1847 {op=>'-','type'=>'unary',trans=>'u-'},
1849 {op=>'func','type'=>'unary'}],
1850 'grouping'=>[qw( \( \) )],
1851 'func'=>[qw( sin cos )],
1856 @xt=$I2P->translate($opts{'xexpr'});
1857 @yt=$I2P->translate($opts{'yexpr'});
1859 $numre=$I2P->{'numre'};
1862 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1863 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1864 @{$opts{'parm'}}=@pt;
1867 # print Dumper(\%opts);
1869 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1870 $self->{ERRSTR}='transform: no xopcodes given.';
1874 @op=@{$opts{'xopcodes'}};
1876 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1877 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1880 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1886 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1887 $self->{ERRSTR}='transform: no yopcodes given.';
1891 @op=@{$opts{'yopcodes'}};
1893 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1894 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1897 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1902 if ( !exists $opts{'parm'}) {
1903 $self->{ERRSTR}='transform: no parameter arg given.';
1907 # print Dumper(\@ropx);
1908 # print Dumper(\@ropy);
1909 # print Dumper(\@ropy);
1911 my $img = Imager->new();
1912 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1913 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1919 my ($opts, @imgs) = @_;
1921 require "Imager/Expr.pm";
1923 $opts->{variables} = [ qw(x y) ];
1924 my ($width, $height) = @{$opts}{qw(width height)};
1926 $width ||= $imgs[0]->getwidth();
1927 $height ||= $imgs[0]->getheight();
1929 for my $img (@imgs) {
1930 $opts->{constants}{"w$img_num"} = $img->getwidth();
1931 $opts->{constants}{"h$img_num"} = $img->getheight();
1932 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1933 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1938 $opts->{constants}{w} = $width;
1939 $opts->{constants}{cx} = $width/2;
1942 $Imager::ERRSTR = "No width supplied";
1946 $opts->{constants}{h} = $height;
1947 $opts->{constants}{cy} = $height/2;
1950 $Imager::ERRSTR = "No height supplied";
1953 my $code = Imager::Expr->new($opts);
1955 $Imager::ERRSTR = Imager::Expr::error();
1958 my $channels = $opts->{channels} || 3;
1959 unless ($channels >= 1 && $channels <= 4) {
1960 return Imager->_set_error("channels must be an integer between 1 and 4");
1963 my $img = Imager->new();
1964 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1965 $channels, $code->code(),
1966 $code->nregs(), $code->cregs(),
1967 [ map { $_->{IMG} } @imgs ]);
1968 if (!defined $img->{IMG}) {
1969 $Imager::ERRSTR = Imager->_error_as_msg();
1978 my %opts=(tx => 0,ty => 0, @_);
1980 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1981 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1983 %opts = (src_minx => 0,
1985 src_maxx => $opts{src}->getwidth(),
1986 src_maxy => $opts{src}->getheight(),
1989 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1990 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1991 $self->{ERRSTR} = $self->_error_as_msg();
2001 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2003 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2004 $dir = $xlate{$opts{'dir'}};
2005 return $self if i_flipxy($self->{IMG}, $dir);
2013 unless (defined wantarray) {
2014 my @caller = caller;
2015 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2019 if (defined $opts{right}) {
2020 my $degrees = $opts{right};
2022 $degrees += 360 * int(((-$degrees)+360)/360);
2024 $degrees = $degrees % 360;
2025 if ($degrees == 0) {
2026 return $self->copy();
2028 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2029 my $result = Imager->new();
2030 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2034 $self->{ERRSTR} = $self->_error_as_msg();
2039 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2043 elsif (defined $opts{radians} || defined $opts{degrees}) {
2044 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2046 my $result = Imager->new;
2048 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
2051 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2053 if ($result->{IMG}) {
2057 $self->{ERRSTR} = $self->_error_as_msg();
2062 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2067 sub matrix_transform {
2071 unless (defined wantarray) {
2072 my @caller = caller;
2073 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2077 if ($opts{matrix}) {
2078 my $xsize = $opts{xsize} || $self->getwidth;
2079 my $ysize = $opts{ysize} || $self->getheight;
2081 my $result = Imager->new;
2083 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2084 $opts{matrix}, $opts{back})
2088 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2096 $self->{ERRSTR} = "matrix parameter required";
2102 *yatf = \&matrix_transform;
2104 # These two are supported for legacy code only
2107 return Imager::Color->new(@_);
2111 return Imager::Color::set(@_);
2114 # Draws a box between the specified corner points.
2117 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2118 my $dflcl=i_color_new(255,255,255,255);
2119 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2121 if (exists $opts{'box'}) {
2122 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
2123 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
2124 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
2125 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
2128 if ($opts{filled}) {
2129 my $color = _color($opts{'color'});
2131 $self->{ERRSTR} = $Imager::ERRSTR;
2134 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2135 $opts{ymax}, $color);
2137 elsif ($opts{fill}) {
2138 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2139 # assume it's a hash ref
2140 require 'Imager/Fill.pm';
2141 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2142 $self->{ERRSTR} = $Imager::ERRSTR;
2146 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2147 $opts{ymax},$opts{fill}{fill});
2150 my $color = _color($opts{'color'});
2152 $self->{ERRSTR} = $Imager::ERRSTR;
2155 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2163 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2164 my $dflcl=i_color_new(255,255,255,255);
2165 my %opts=(color=>$dflcl,
2166 'r'=>min($self->getwidth(),$self->getheight())/3,
2167 'x'=>$self->getwidth()/2,
2168 'y'=>$self->getheight()/2,
2169 'd1'=>0, 'd2'=>361, @_);
2172 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2173 # assume it's a hash ref
2174 require 'Imager/Fill.pm';
2175 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2176 $self->{ERRSTR} = $Imager::ERRSTR;
2180 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2181 $opts{'d2'}, $opts{fill}{fill});
2184 my $color = _color($opts{'color'});
2186 $self->{ERRSTR} = $Imager::ERRSTR;
2189 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2190 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2194 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2195 $opts{'d1'}, $opts{'d2'}, $color);
2201 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2202 # assume it's a hash ref
2203 require 'Imager/Fill.pm';
2204 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2205 $self->{ERRSTR} = $Imager::ERRSTR;
2209 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2210 $opts{'d2'}, $opts{fill}{fill});
2213 my $color = _color($opts{'color'});
2215 $self->{ERRSTR} = $Imager::ERRSTR;
2218 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2219 $opts{'d1'}, $opts{'d2'}, $color);
2226 # Draws a line from one point to the other
2227 # the endpoint is set if the endp parameter is set which it is by default.
2228 # to turn of the endpoint being set use endp=>0 when calling line.
2232 my $dflcl=i_color_new(0,0,0,0);
2233 my %opts=(color=>$dflcl,
2236 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2238 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2239 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2241 my $color = _color($opts{'color'});
2243 $self->{ERRSTR} = $Imager::ERRSTR;
2247 $opts{antialias} = $opts{aa} if defined $opts{aa};
2248 if ($opts{antialias}) {
2249 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2250 $color, $opts{endp});
2252 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2253 $color, $opts{endp});
2258 # Draws a line between an ordered set of points - It more or less just transforms this
2259 # into a list of lines.
2263 my ($pt,$ls,@points);
2264 my $dflcl=i_color_new(0,0,0,0);
2265 my %opts=(color=>$dflcl,@_);
2267 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2269 if (exists($opts{points})) { @points=@{$opts{points}}; }
2270 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2271 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2274 # print Dumper(\@points);
2276 my $color = _color($opts{'color'});
2278 $self->{ERRSTR} = $Imager::ERRSTR;
2281 $opts{antialias} = $opts{aa} if defined $opts{aa};
2282 if ($opts{antialias}) {
2285 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2292 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2302 my ($pt,$ls,@points);
2303 my $dflcl = i_color_new(0,0,0,0);
2304 my %opts = (color=>$dflcl, @_);
2306 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2308 if (exists($opts{points})) {
2309 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2310 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2313 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2314 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2317 if ($opts{'fill'}) {
2318 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2319 # assume it's a hash ref
2320 require 'Imager/Fill.pm';
2321 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2322 $self->{ERRSTR} = $Imager::ERRSTR;
2326 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2327 $opts{'fill'}{'fill'});
2330 my $color = _color($opts{'color'});
2332 $self->{ERRSTR} = $Imager::ERRSTR;
2335 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2342 # this the multipoint bezier curve
2343 # this is here more for testing that actual usage since
2344 # this is not a good algorithm. Usually the curve would be
2345 # broken into smaller segments and each done individually.
2349 my ($pt,$ls,@points);
2350 my $dflcl=i_color_new(0,0,0,0);
2351 my %opts=(color=>$dflcl,@_);
2353 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2355 if (exists $opts{points}) {
2356 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2357 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2360 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2361 $self->{ERRSTR}='Missing or invalid points.';
2365 my $color = _color($opts{'color'});
2367 $self->{ERRSTR} = $Imager::ERRSTR;
2370 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2376 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2379 unless (exists $opts{'x'} && exists $opts{'y'}) {
2380 $self->{ERRSTR} = "missing seed x and y parameters";
2385 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2386 # assume it's a hash ref
2387 require 'Imager/Fill.pm';
2388 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2389 $self->{ERRSTR} = $Imager::ERRSTR;
2393 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2396 my $color = _color($opts{'color'});
2398 $self->{ERRSTR} = $Imager::ERRSTR;
2401 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2403 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2409 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2411 unless (exists $opts{'x'} && exists $opts{'y'}) {
2412 $self->{ERRSTR} = 'missing x and y parameters';
2418 my $color = _color($opts{color})
2420 if (ref $x && ref $y) {
2421 unless (@$x == @$y) {
2422 $self->{ERRSTR} = 'length of x and y mismatch';
2425 if ($color->isa('Imager::Color')) {
2426 for my $i (0..$#{$opts{'x'}}) {
2427 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2431 for my $i (0..$#{$opts{'x'}}) {
2432 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2437 if ($color->isa('Imager::Color')) {
2438 i_ppix($self->{IMG}, $x, $y, $color);
2441 i_ppixf($self->{IMG}, $x, $y, $color);
2451 my %opts = ( "type"=>'8bit', @_);
2453 unless (exists $opts{'x'} && exists $opts{'y'}) {
2454 $self->{ERRSTR} = 'missing x and y parameters';
2460 if (ref $x && ref $y) {
2461 unless (@$x == @$y) {
2462 $self->{ERRSTR} = 'length of x and y mismatch';
2466 if ($opts{"type"} eq '8bit') {
2467 for my $i (0..$#{$opts{'x'}}) {
2468 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2472 for my $i (0..$#{$opts{'x'}}) {
2473 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2476 return wantarray ? @result : \@result;
2479 if ($opts{"type"} eq '8bit') {
2480 return i_get_pixel($self->{IMG}, $x, $y);
2483 return i_gpixf($self->{IMG}, $x, $y);
2492 my %opts = ( type => '8bit', x=>0, @_);
2494 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2496 unless (defined $opts{'y'}) {
2497 $self->_set_error("missing y parameter");
2501 if ($opts{type} eq '8bit') {
2502 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2505 elsif ($opts{type} eq 'float') {
2506 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2510 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2517 my %opts = ( x=>0, @_);
2519 unless (defined $opts{'y'}) {
2520 $self->_set_error("missing y parameter");
2525 if (ref $opts{pixels} && @{$opts{pixels}}) {
2526 # try to guess the type
2527 if ($opts{pixels}[0]->isa('Imager::Color')) {
2528 $opts{type} = '8bit';
2530 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2531 $opts{type} = 'float';
2534 $self->_set_error("missing type parameter and could not guess from pixels");
2540 $opts{type} = '8bit';
2544 if ($opts{type} eq '8bit') {
2545 if (ref $opts{pixels}) {
2546 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2549 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2552 elsif ($opts{type} eq 'float') {
2553 if (ref $opts{pixels}) {
2554 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2557 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2561 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2568 my %opts = ( type => '8bit', x=>0, @_);
2570 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2572 unless (defined $opts{'y'}) {
2573 $self->_set_error("missing y parameter");
2577 unless ($opts{channels}) {
2578 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2581 if ($opts{type} eq '8bit') {
2582 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2583 $opts{y}, @{$opts{channels}});
2585 elsif ($opts{type} eq 'float') {
2586 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2587 $opts{y}, @{$opts{channels}});
2590 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2595 # make an identity matrix of the given size
2599 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2600 for my $c (0 .. ($size-1)) {
2601 $matrix->[$c][$c] = 1;
2606 # general function to convert an image
2608 my ($self, %opts) = @_;
2611 unless (defined wantarray) {
2612 my @caller = caller;
2613 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2617 # the user can either specify a matrix or preset
2618 # the matrix overrides the preset
2619 if (!exists($opts{matrix})) {
2620 unless (exists($opts{preset})) {
2621 $self->{ERRSTR} = "convert() needs a matrix or preset";
2625 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2626 # convert to greyscale, keeping the alpha channel if any
2627 if ($self->getchannels == 3) {
2628 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2630 elsif ($self->getchannels == 4) {
2631 # preserve the alpha channel
2632 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2637 $matrix = _identity($self->getchannels);
2640 elsif ($opts{preset} eq 'noalpha') {
2641 # strip the alpha channel
2642 if ($self->getchannels == 2 or $self->getchannels == 4) {
2643 $matrix = _identity($self->getchannels);
2644 pop(@$matrix); # lose the alpha entry
2647 $matrix = _identity($self->getchannels);
2650 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2652 $matrix = [ [ 1 ] ];
2654 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2655 $matrix = [ [ 0, 1 ] ];
2657 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2658 $matrix = [ [ 0, 0, 1 ] ];
2660 elsif ($opts{preset} eq 'alpha') {
2661 if ($self->getchannels == 2 or $self->getchannels == 4) {
2662 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2665 # the alpha is just 1 <shrug>
2666 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2669 elsif ($opts{preset} eq 'rgb') {
2670 if ($self->getchannels == 1) {
2671 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2673 elsif ($self->getchannels == 2) {
2674 # preserve the alpha channel
2675 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2678 $matrix = _identity($self->getchannels);
2681 elsif ($opts{preset} eq 'addalpha') {
2682 if ($self->getchannels == 1) {
2683 $matrix = _identity(2);
2685 elsif ($self->getchannels == 3) {
2686 $matrix = _identity(4);
2689 $matrix = _identity($self->getchannels);
2693 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2699 $matrix = $opts{matrix};
2702 my $new = Imager->new();
2703 $new->{IMG} = i_img_new();
2704 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2705 # most likely a bad matrix
2706 $self->{ERRSTR} = _error_as_msg();
2713 # general function to map an image through lookup tables
2716 my ($self, %opts) = @_;
2717 my @chlist = qw( red green blue alpha );
2719 if (!exists($opts{'maps'})) {
2720 # make maps from channel maps
2722 for $chnum (0..$#chlist) {
2723 if (exists $opts{$chlist[$chnum]}) {
2724 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2725 } elsif (exists $opts{'all'}) {
2726 $opts{'maps'}[$chnum] = $opts{'all'};
2730 if ($opts{'maps'} and $self->{IMG}) {
2731 i_map($self->{IMG}, $opts{'maps'} );
2737 my ($self, %opts) = @_;
2739 defined $opts{mindist} or $opts{mindist} = 0;
2741 defined $opts{other}
2742 or return $self->_set_error("No 'other' parameter supplied");
2743 defined $opts{other}{IMG}
2744 or return $self->_set_error("No image data in 'other' image");
2747 or return $self->_set_error("No image data");
2749 my $result = Imager->new;
2750 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2752 or return $self->_set_error($self->_error_as_msg());
2757 # destructive border - image is shrunk by one pixel all around
2760 my ($self,%opts)=@_;
2761 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2762 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2766 # Get the width of an image
2770 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2771 return (i_img_info($self->{IMG}))[0];
2774 # Get the height of an image
2778 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2779 return (i_img_info($self->{IMG}))[1];
2782 # Get number of channels in an image
2786 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2787 return i_img_getchannels($self->{IMG});
2794 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2795 return i_img_getmask($self->{IMG});
2803 if (!defined($self->{IMG})) {
2804 $self->{ERRSTR} = 'image is empty';
2807 unless (defined $opts{mask}) {
2808 $self->_set_error("mask parameter required");
2811 i_img_setmask( $self->{IMG} , $opts{mask} );
2816 # Get number of colors in an image
2820 my %opts=('maxcolors'=>2**30,@_);
2821 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2822 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2823 return ($rc==-1? undef : $rc);
2826 # draw string to an image
2830 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2832 my %input=('x'=>0, 'y'=>0, @_);
2833 $input{string}||=$input{text};
2835 unless(defined $input{string}) {
2836 $self->{ERRSTR}="missing required parameter 'string'";
2840 unless($input{font}) {
2841 $self->{ERRSTR}="missing required parameter 'font'";
2845 unless ($input{font}->draw(image=>$self, %input)) {
2857 unless ($self->{IMG}) {
2858 $self->{ERRSTR}='empty input image';
2867 my %input=('x'=>0, 'y'=>0, @_);
2868 $input{string}||=$input{text};
2870 unless(exists $input{string}) {
2871 $self->_set_error("missing required parameter 'string'");
2875 unless($input{font}) {
2876 $self->_set_error("missing required parameter 'font'");
2881 unless (@result = $input{font}->align(image=>$img, %input)) {
2885 return wantarray ? @result : $result[0];
2888 my @file_limit_names = qw/width height bytes/;
2890 sub set_file_limits {
2897 @values{@file_limit_names} = (0) x @file_limit_names;
2900 @values{@file_limit_names} = i_get_image_file_limits();
2903 for my $key (keys %values) {
2904 defined $opts{$key} and $values{$key} = $opts{$key};
2907 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
2910 sub get_file_limits {
2911 i_get_image_file_limits();
2914 # Shortcuts that can be exported
2916 sub newcolor { Imager::Color->new(@_); }
2917 sub newfont { Imager::Font->new(@_); }
2919 *NC=*newcolour=*newcolor;
2926 #### Utility routines
2929 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2933 my ($self, $msg) = @_;
2936 $self->{ERRSTR} = $msg;
2944 # Default guess for the type of an image from extension
2946 sub def_guess_type {
2949 $ext=($name =~ m/\.([^\.]+)$/)[0];
2950 return 'tiff' if ($ext =~ m/^tiff?$/);
2951 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2952 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2953 return 'png' if ($ext eq "png");
2954 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2955 return 'tga' if ($ext eq "tga");
2956 return 'rgb' if ($ext eq "rgb");
2957 return 'gif' if ($ext eq "gif");
2958 return 'raw' if ($ext eq "raw");
2962 # get the minimum of a list
2966 for(@_) { if ($_<$mx) { $mx=$_; }}
2970 # get the maximum of a list
2974 for(@_) { if ($_>$mx) { $mx=$_; }}
2978 # string stuff for iptc headers
2982 $str = substr($str,3);
2983 $str =~ s/[\n\r]//g;
2990 # A little hack to parse iptc headers.
2995 my($caption,$photogr,$headln,$credit);
2997 my $str=$self->{IPTCRAW};
3001 @ar=split(/8BIM/,$str);
3006 @sar=split(/\034\002/);
3007 foreach $item (@sar) {
3008 if ($item =~ m/^x/) {
3009 $caption=&clean($item);
3012 if ($item =~ m/^P/) {
3013 $photogr=&clean($item);
3016 if ($item =~ m/^i/) {
3017 $headln=&clean($item);
3020 if ($item =~ m/^n/) {
3021 $credit=&clean($item);
3027 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3034 or die "Only C language supported";
3036 require Imager::ExtUtils;
3037 return Imager::ExtUtils->inline_config;
3042 # Below is the stub of documentation for your module. You better edit it!
3046 Imager - Perl extension for Generating 24 bit Images
3056 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3061 my $img = Imager->new();
3062 # see Imager::Files for information on the read() method
3063 $img->read(file=>$file) or die $img->errstr();
3065 $file =~ s/\.[^.]*$//;
3067 # Create smaller version
3068 # documented in Imager::Transformations
3069 my $thumb = $img->scale(scalefactor=>.3);
3071 # Autostretch individual channels
3072 $thumb->filter(type=>'autolevels');
3074 # try to save in one of these formats
3077 for $format ( qw( png gif jpg tiff ppm ) ) {
3078 # Check if given format is supported
3079 if ($Imager::formats{$format}) {
3080 $file.="_low.$format";
3081 print "Storing image as: $file\n";
3082 # documented in Imager::Files
3083 $thumb->write(file=>$file) or
3091 Imager is a module for creating and altering images. It can read and
3092 write various image formats, draw primitive shapes like lines,and
3093 polygons, blend multiple images together in various ways, scale, crop,
3094 render text and more.
3096 =head2 Overview of documentation
3102 Imager - This document - Synopsis Example, Table of Contents and
3107 L<Imager::Tutorial> - a brief introduction to Imager.
3111 L<Imager::Cookbook> - how to do various things with Imager.
3115 L<Imager::ImageTypes> - Basics of constructing image objects with
3116 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3117 8/16/double bits/channel, color maps, channel masks, image tags, color
3118 quantization. Also discusses basic image information methods.
3122 L<Imager::Files> - IO interaction, reading/writing images, format
3127 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3132 L<Imager::Color> - Color specification.
3136 L<Imager::Fill> - Fill pattern specification.
3140 L<Imager::Font> - General font rendering, bounding boxes and font
3145 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3146 blending, pasting, convert and map.
3150 L<Imager::Engines> - Programmable transformations through
3151 C<transform()>, C<transform2()> and C<matrix_transform()>.
3155 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3160 L<Imager::Expr> - Expressions for evaluation engine used by
3165 L<Imager::Matrix2d> - Helper class for affine transformations.
3169 L<Imager::Fountain> - Helper for making gradient profiles.
3173 L<Imager::API> - using Imager's C API
3177 L<Imager::APIRef> - API function reference
3181 L<Imager::Inline> - using Imager's C API from Inline::C
3185 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3189 =head2 Basic Overview
3191 An Image object is created with C<$img = Imager-E<gt>new()>.
3194 $img=Imager->new(); # create empty image
3195 $img->read(file=>'lena.png',type=>'png') or # read image from file
3196 die $img->errstr(); # give an explanation
3197 # if something failed
3199 or if you want to create an empty image:
3201 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3203 This example creates a completely black image of width 400 and height
3206 When an operation fails which can be directly associated with an image
3207 the error message is stored can be retrieved with
3208 C<$img-E<gt>errstr()>.
3210 In cases where no image object is associated with an operation
3211 C<$Imager::ERRSTR> is used to report errors not directly associated
3212 with an image object. You can also call C<Imager->errstr> to get this
3215 The C<Imager-E<gt>new> method is described in detail in
3216 L<Imager::ImageTypes>.
3220 Where to find information on methods for Imager class objects.
3222 addcolors() - L<Imager::ImageTypes/addcolors>
3224 addtag() - L<Imager::ImageTypes/addtag> - add image tags
3226 arc() - L<Imager::Draw/arc>
3228 align_string() - L<Imager::Draw/align_string>
3230 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
3233 box() - L<Imager::Draw/box>
3235 circle() - L<Imager::Draw/circle>
3237 colorcount() - L<Imager::Draw/colorcount>
3239 convert() - L<Imager::Transformations/"Color transformations"> -
3240 transform the color space
3242 copy() - L<Imager::Transformations/copy>
3244 crop() - L<Imager::Transformations/crop> - extract part of an image
3246 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
3248 difference() - L<Imager::Filters/"Image Difference">
3250 errstr() - L<"Basic Overview">
3252 filter() - L<Imager::Filters>
3254 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
3257 flip() - L<Imager::Transformations/flip>
3259 flood_fill() - L<Imager::Draw/flood_fill>
3261 getchannels() - L<Imager::ImageTypes/getchannels>
3263 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
3265 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
3266 palette, if it has one
3268 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3270 getheight() - L<Imager::ImageTypes/getwidth>
3272 getpixel() - L<Imager::Draw/getpixel>
3274 getsamples() - L<Imager::Draw/getsamples>
3276 getscanline() - L<Imager::Draw/getscanline>
3278 getwidth() - L<Imager::ImageTypes/getwidth>
3280 img_set() - L<Imager::ImageTypes/img_set>
3282 line() - L<Imager::Draw/line>
3284 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3287 masked() - L<Imager::ImageTypes/masked> - make a masked image
3289 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
3291 maxcolors() - L<Imager::ImageTypes/maxcolors>
3293 new() - L<Imager::ImageTypes/new>
3295 open() - L<Imager::Files> - an alias for read()
3297 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3299 polygon() - L<Imager::Draw/polygon>
3301 polyline() - L<Imager::Draw/polyline>
3303 read() - L<Imager::Files> - read a single image from an image file
3305 read_multi() - L<Imager::Files> - read multiple images from an image
3308 rotate() - L<Imager::Transformations/rotate>
3310 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3311 image and use the alpha channel
3313 scale() - L<Imager::Transformations/scale>
3315 setscanline() - L<Imager::Draw/setscanline>
3317 scaleX() - L<Imager::Transformations/scaleX>
3319 scaleY() - L<Imager::Transformations/scaleY>
3321 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
3324 setpixel() - L<Imager::Draw/setpixel>
3326 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3328 string() - L<Imager::Draw/string> - draw text on an image
3330 tags() - L<Imager::ImageTypes/tags> - fetch image tags
3332 to_paletted() - L<Imager::ImageTypes/to_paletted>
3334 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
3336 transform() - L<Imager::Engines/"transform">
3338 transform2() - L<Imager::Engines/"transform2">
3340 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
3342 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
3345 write() - L<Imager::Files> - write an image to a file
3347 write_multi() - L<Imager::Files> - write multiple image to an image
3350 =head1 CONCEPT INDEX
3352 animated GIF - L<Imager::File/"Writing an animated GIF">
3354 aspect ratio - L<Imager::ImageTypes/i_xres>,
3355 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3357 blend - alpha blending one image onto another
3358 L<Imager::Transformations/rubthrough>
3360 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3362 boxes, drawing - L<Imager::Draw/box>
3364 changes between image - L<Imager::Filter/"Image Difference">
3366 color - L<Imager::Color>
3368 color names - L<Imager::Color>, L<Imager::Color::Table>
3370 combine modes - L<Imager::Fill/combine>
3372 compare images - L<Imager::Filter/"Image Difference">
3374 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3376 convolution - L<Imager::Filter/conv>
3378 cropping - L<Imager::Transformations/crop>
3380 C<diff> images - L<Imager::Filter/"Image Difference">
3382 dpi - L<Imager::ImageTypes/i_xres>
3384 drawing boxes - L<Imager::Draw/box>
3386 drawing lines - L<Imager::Draw/line>
3388 drawing text - L<Imager::Font/string>, L<Imager::Font/align>
3390 error message - L<"Basic Overview">
3392 files, font - L<Imager::Font>
3394 files, image - L<Imager::Files>
3396 filling, types of fill - L<Imager::Fill>
3398 filling, boxes - L<Imager::Draw/box>
3400 filling, flood fill - L<Imager::Draw/flood_fill>
3402 flood fill - L<Imager::Draw/flood_fill>
3404 fonts - L<Imager::Font>
3406 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3407 L<Imager::Font::Wrap>
3409 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3411 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3413 fountain fill - L<Imager::Fill/"Fountain fills">,
3414 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3415 L<Imager::Filters/gradgen>
3417 GIF files - L<Imager::Files/"GIF">
3419 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3421 gradient fill - L<Imager::Fill/"Fountain fills">,
3422 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3423 L<Imager::Filters/gradgen>
3425 guassian blur - L<Imager::Filter/guassian>
3427 hatch fills - L<Imager::Fill/"Hatched fills">
3429 invert image - L<Imager::Filter/hardinvert>
3431 JPEG - L<Imager::Files/"JPEG">
3433 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3435 lines, drawing - L<Imager::Draw/line>
3437 matrix - L<Imager::Matrix2d>,
3438 L<Imager::Transformations/"Matrix Transformations">,
3439 L<Imager::Font/transform>
3441 metadata, image - L<Imager::ImageTypes/"Tags">
3443 mosaic - L<Imager::Filter/mosaic>
3445 noise, filter - L<Imager::Filter/noise>
3447 noise, rendered - L<Imager::Filter/turbnoise>,
3448 L<Imager::Filter/radnoise>
3450 paste - L<Imager::Transformations/paste>,
3451 L<Imager::Transformations/rubthrough>
3453 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
3454 L<Imager::ImageTypes/new>
3456 posterize - L<Imager::Filter/postlevels>
3458 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3460 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3462 rectangles, drawing - L<Imager::Draw/box>
3464 resizing an image - L<Imager::Transformations/scale>,
3465 L<Imager::Transformations/crop>
3467 saving an image - L<Imager::Files>
3469 scaling - L<Imager::Transformations/scale>
3471 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3473 size, image - L<Imager::ImageTypes/getwidth>,
3474 L<Imager::ImageTypes/getheight>
3476 size, text - L<Imager::Font/bounding_box>
3478 tags, image metadata - L<Imager::ImageTypes/"Tags">
3480 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
3481 L<Imager::Font::Wrap>
3483 text, wrapping text in an area - L<Imager::Font::Wrap>
3485 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3487 tiles, color - L<Imager::Filter/mosaic>
3489 unsharp mask - L<Imager::Filter/unsharpmask>
3491 watermark - L<Imager::Filter/watermark>
3493 writing an image to a file - L<Imager::Files>
3497 You can ask for help, report bugs or express your undying love for
3498 Imager on the Imager-devel mailing list.
3500 To subscribe send a message with C<subscribe> in the body to:
3502 imager-devel+request@molar.is
3508 L<http://www.molar.is/en/lists/imager-devel/>
3512 where you can also find the mailing list archive.
3514 If you're into IRC, you can typically find the developers in #Imager
3515 on irc.perl.org. As with any IRC channel, the participants could be
3516 occupied or asleep, so please be patient.
3518 You can report bugs by pointing your browser at:
3522 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
3526 Please remember to include the versions of Imager, perl, supporting
3527 libraries, and any relevant code. If you have specific images that
3528 cause the problems, please include those too.
3532 Bugs are listed individually for relevant pod pages.
3536 Arnar M. Hrafnkelsson and Tony Cook (tony@imager.perl.org) among
3537 others. See the README for a complete list.
3541 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
3542 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
3543 L<Imager::Font>(3), L<Imager::Transformations>(3),
3544 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
3545 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
3547 L<http://imager.perl.org/>
3549 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
3551 Other perl imaging modules include:
3553 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).