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(); return undef;
1222 $self->{DEBUG} && print "loading a pnm file\n";
1226 if ( $input{'type'} eq 'png' ) {
1227 $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1228 if ( !defined($self->{IMG}) ) {
1229 $self->{ERRSTR} = $self->_error_as_msg();
1232 $self->{DEBUG} && print "loading a png file\n";
1235 if ( $input{'type'} eq 'bmp' ) {
1236 $self->{IMG}=i_readbmp_wiol( $IO );
1237 if ( !defined($self->{IMG}) ) {
1238 $self->{ERRSTR}=$self->_error_as_msg();
1241 $self->{DEBUG} && print "loading a bmp file\n";
1244 if ( $input{'type'} eq 'gif' ) {
1245 if ($input{colors} && !ref($input{colors})) {
1246 # must be a reference to a scalar that accepts the colour map
1247 $self->{ERRSTR} = "option 'colors' must be a scalar reference";
1250 if ($input{'gif_consolidate'}) {
1251 if ($input{colors}) {
1253 ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
1255 ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
1259 $self->{IMG} =i_readgif_wiol( $IO );
1263 my $page = $input{'page'};
1264 defined $page or $page = 0;
1265 $self->{IMG} = i_readgif_single_wiol( $IO, $page );
1266 if ($input{colors}) {
1267 ${ $input{colors} } =
1268 [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
1272 if ( !defined($self->{IMG}) ) {
1273 $self->{ERRSTR}=$self->_error_as_msg();
1276 $self->{DEBUG} && print "loading a gif file\n";
1279 if ( $input{'type'} eq 'tga' ) {
1280 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1281 if ( !defined($self->{IMG}) ) {
1282 $self->{ERRSTR}=$self->_error_as_msg();
1285 $self->{DEBUG} && print "loading a tga file\n";
1288 if ( $input{'type'} eq 'rgb' ) {
1289 $self->{IMG}=i_readrgb_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1290 if ( !defined($self->{IMG}) ) {
1291 $self->{ERRSTR}=$self->_error_as_msg();
1294 $self->{DEBUG} && print "loading a tga file\n";
1298 if ( $input{'type'} eq 'raw' ) {
1299 my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
1301 if ( !($params{xsize} && $params{ysize}) ) {
1302 $self->{ERRSTR}='missing xsize or ysize parameter for raw';
1306 $self->{IMG} = i_readraw_wiol( $IO,
1309 $params{datachannels},
1310 $params{storechannels},
1311 $params{interleave});
1312 if ( !defined($self->{IMG}) ) {
1313 $self->{ERRSTR}='unable to read raw image';
1316 $self->{DEBUG} && print "loading a raw file\n";
1322 sub _fix_gif_positions {
1323 my ($opts, $opt, $msg, @imgs) = @_;
1325 my $positions = $opts->{'gif_positions'};
1327 for my $pos (@$positions) {
1328 my ($x, $y) = @$pos;
1329 my $img = $imgs[$index++];
1330 $img->settag(name=>'gif_left', value=>$x);
1331 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1333 $$msg .= "replaced with the gif_left and gif_top tags";
1338 gif_each_palette=>'gif_local_map',
1339 interlace => 'gif_interlace',
1340 gif_delays => 'gif_delay',
1341 gif_positions => \&_fix_gif_positions,
1342 gif_loop_count => 'gif_loop',
1346 my ($self, $opts, $prefix, @imgs) = @_;
1348 for my $opt (keys %$opts) {
1350 if ($obsolete_opts{$opt}) {
1351 my $new = $obsolete_opts{$opt};
1352 my $msg = "Obsolete option $opt ";
1354 $new->($opts, $opt, \$msg, @imgs);
1357 $msg .= "replaced with the $new tag ";
1360 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1361 warn $msg if $warn_obsolete && $^W;
1363 next unless $tagname =~ /^\Q$prefix/;
1364 my $value = $opts->{$opt};
1366 if (UNIVERSAL::isa($value, "Imager::Color")) {
1367 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1368 for my $img (@imgs) {
1369 $img->settag(name=>$tagname, value=>$tag);
1372 elsif (ref($value) eq 'ARRAY') {
1373 for my $i (0..$#$value) {
1374 my $val = $value->[$i];
1376 if (UNIVERSAL::isa($val, "Imager::Color")) {
1377 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1379 $imgs[$i]->settag(name=>$tagname, value=>$tag);
1382 $self->_set_error("Unknown reference type " . ref($value) .
1383 " supplied in array for $opt");
1389 and $imgs[$i]->settag(name=>$tagname, value=>$val);
1394 $self->_set_error("Unknown reference type " . ref($value) .
1395 " supplied for $opt");
1400 # set it as a tag for every image
1401 for my $img (@imgs) {
1402 $img->settag(name=>$tagname, value=>$value);
1410 # Write an image to file
1413 my %input=(jpegquality=>75,
1423 $self->_set_opts(\%input, "i_", $self)
1426 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1428 if (!$input{'type'} and $input{file}) {
1429 $input{'type'}=$FORMATGUESS->($input{file});
1431 if (!$input{'type'}) {
1432 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
1436 if (!$formats{$input{'type'}}) { $self->{ERRSTR}='format not supported'; return undef; }
1438 my ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
1441 if ($input{'type'} eq 'tiff') {
1442 $self->_set_opts(\%input, "tiff_", $self)
1444 $self->_set_opts(\%input, "exif_", $self)
1447 if (defined $input{class} && $input{class} eq 'fax') {
1448 if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
1449 $self->{ERRSTR}='Could not write to buffer';
1453 if (!i_writetiff_wiol($self->{IMG}, $IO)) {
1454 $self->{ERRSTR}='Could not write to buffer';
1458 } elsif ( $input{'type'} eq 'pnm' ) {
1459 $self->_set_opts(\%input, "pnm_", $self)
1461 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
1462 $self->{ERRSTR}='unable to write pnm image';
1465 $self->{DEBUG} && print "writing a pnm file\n";
1466 } elsif ( $input{'type'} eq 'raw' ) {
1467 $self->_set_opts(\%input, "raw_", $self)
1469 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
1470 $self->{ERRSTR}='unable to write raw image';
1473 $self->{DEBUG} && print "writing a raw file\n";
1474 } elsif ( $input{'type'} eq 'png' ) {
1475 $self->_set_opts(\%input, "png_", $self)
1477 if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
1478 $self->{ERRSTR}='unable to write png image';
1481 $self->{DEBUG} && print "writing a png file\n";
1482 } elsif ( $input{'type'} eq 'jpeg' ) {
1483 $self->_set_opts(\%input, "jpeg_", $self)
1485 $self->_set_opts(\%input, "exif_", $self)
1487 if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
1488 $self->{ERRSTR} = $self->_error_as_msg();
1491 $self->{DEBUG} && print "writing a jpeg file\n";
1492 } elsif ( $input{'type'} eq 'bmp' ) {
1493 $self->_set_opts(\%input, "bmp_", $self)
1495 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
1496 $self->{ERRSTR}='unable to write bmp image';
1499 $self->{DEBUG} && print "writing a bmp file\n";
1500 } elsif ( $input{'type'} eq 'tga' ) {
1501 $self->_set_opts(\%input, "tga_", $self)
1504 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
1505 $self->{ERRSTR}=$self->_error_as_msg();
1508 $self->{DEBUG} && print "writing a tga file\n";
1509 } elsif ( $input{'type'} eq 'gif' ) {
1510 $self->_set_opts(\%input, "gif_", $self)
1512 # compatibility with the old interfaces
1513 if ($input{gifquant} eq 'lm') {
1514 $input{make_colors} = 'addi';
1515 $input{translate} = 'perturb';
1516 $input{perturb} = $input{lmdither};
1517 } elsif ($input{gifquant} eq 'gen') {
1518 # just pass options through
1520 $input{make_colors} = 'webmap'; # ignored
1521 $input{translate} = 'giflib';
1523 if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
1524 $self->{ERRSTR} = $self->_error_as_msg;
1529 if (exists $input{'data'}) {
1530 my $data = io_slurp($IO);
1532 $self->{ERRSTR}='Could not slurp from buffer';
1535 ${$input{data}} = $data;
1541 my ($class, $opts, @images) = @_;
1543 if (!$opts->{'type'} && $opts->{'file'}) {
1544 $opts->{'type'} = $FORMATGUESS->($opts->{'file'});
1546 unless ($opts->{'type'}) {
1547 $class->_set_error('type parameter missing and not possible to guess from extension');
1550 # translate to ImgRaw
1551 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1552 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1555 $class->_set_opts($opts, "i_", @images)
1557 my @work = map $_->{IMG}, @images;
1558 my ($IO, $file) = $class->_get_writer_io($opts, $opts->{'type'})
1560 if ($opts->{'type'} eq 'gif') {
1561 $class->_set_opts($opts, "gif_", @images)
1563 my $gif_delays = $opts->{gif_delays};
1564 local $opts->{gif_delays} = $gif_delays;
1565 if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
1566 # assume the caller wants the same delay for each frame
1567 $opts->{gif_delays} = [ ($gif_delays) x @images ];
1569 my $res = i_writegif_wiol($IO, $opts, @work);
1570 $res or $class->_set_error($class->_error_as_msg());
1573 elsif ($opts->{'type'} eq 'tiff') {
1574 $class->_set_opts($opts, "tiff_", @images)
1576 $class->_set_opts($opts, "exif_", @images)
1579 $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
1580 if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
1581 $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
1584 $res = i_writetiff_multi_wiol($IO, @work);
1586 $res or $class->_set_error($class->_error_as_msg());
1590 $ERRSTR = "Sorry, write_multi doesn't support $opts->{'type'} yet";
1595 # read multiple images from a file
1597 my ($class, %opts) = @_;
1599 if ($opts{file} && !exists $opts{'type'}) {
1601 my $type = $FORMATGUESS->($opts{file});
1602 $opts{'type'} = $type;
1604 unless ($opts{'type'}) {
1605 $ERRSTR = "No type parameter supplied and it couldn't be guessed";
1609 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
1611 if ($opts{'type'} eq 'gif') {
1613 @imgs = i_readgif_multi_wiol($IO);
1616 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1620 $ERRSTR = _error_as_msg();
1624 elsif ($opts{'type'} eq 'tiff') {
1625 my @imgs = i_readtiff_multi_wiol($IO, -1);
1628 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
1632 $ERRSTR = _error_as_msg();
1637 $ERRSTR = "Cannot read multiple images from $opts{'type'} files";
1641 # Destroy an Imager object
1645 # delete $instances{$self};
1646 if (defined($self->{IMG})) {
1647 # the following is now handled by the XS DESTROY method for
1648 # Imager::ImgRaw object
1649 # Re-enabling this will break virtual images
1650 # tested for in t/t020masked.t
1651 # i_img_destroy($self->{IMG});
1652 undef($self->{IMG});
1654 # print "Destroy Called on an empty image!\n"; # why did I put this here??
1658 # Perform an inplace filter of an image
1659 # that is the image will be overwritten with the data
1665 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1667 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
1669 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
1670 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
1673 if ($filters{$input{'type'}}{names}) {
1674 my $names = $filters{$input{'type'}}{names};
1675 for my $name (keys %$names) {
1676 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
1677 $input{$name} = $names->{$name}{$input{$name}};
1681 if (defined($filters{$input{'type'}}{defaults})) {
1682 %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
1684 %hsh=('image',$self->{IMG},%input);
1687 my @cs=@{$filters{$input{'type'}}{callseq}};
1690 if (!defined($hsh{$_})) {
1691 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1696 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1697 &{$filters{$input{'type'}}{callsub}}(%hsh);
1700 chomp($self->{ERRSTR} = $@);
1706 $self->{DEBUG} && print "callseq is: @cs\n";
1707 $self->{DEBUG} && print "matching callseq is: @b\n";
1712 sub register_filter {
1714 my %hsh = ( defaults => {}, @_ );
1717 or die "register_filter() with no type\n";
1718 defined $hsh{callsub}
1719 or die "register_filter() with no callsub\n";
1720 defined $hsh{callseq}
1721 or die "register_filter() with no callseq\n";
1723 exists $filters{$hsh{type}}
1726 $filters{$hsh{type}} = \%hsh;
1731 # Scale an image to requested size and return the scaled version
1735 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1736 my $img = Imager->new();
1737 my $tmp = Imager->new();
1739 unless (defined wantarray) {
1740 my @caller = caller;
1741 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1745 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1747 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1748 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1749 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1750 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1751 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1752 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1754 if ($opts{qtype} eq 'normal') {
1755 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1756 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1757 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1758 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1761 if ($opts{'qtype'} eq 'preview') {
1762 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1763 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1766 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1769 # Scales only along the X axis
1773 my %opts=(scalefactor=>0.5,@_);
1775 unless (defined wantarray) {
1776 my @caller = caller;
1777 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1781 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1783 my $img = Imager->new();
1785 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1787 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1788 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1790 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1794 # Scales only along the Y axis
1798 my %opts=(scalefactor=>0.5,@_);
1800 unless (defined wantarray) {
1801 my @caller = caller;
1802 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1806 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1808 my $img = Imager->new();
1810 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1812 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1813 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1815 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1820 # Transform returns a spatial transformation of the input image
1821 # this moves pixels to a new location in the returned image.
1822 # NOTE - should make a utility function to check transforms for
1827 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1829 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1831 # print Dumper(\%opts);
1834 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1836 eval ("use Affix::Infix2Postfix;");
1839 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1842 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1843 {op=>'-',trans=>'Sub'},
1844 {op=>'*',trans=>'Mult'},
1845 {op=>'/',trans=>'Div'},
1846 {op=>'-','type'=>'unary',trans=>'u-'},
1848 {op=>'func','type'=>'unary'}],
1849 'grouping'=>[qw( \( \) )],
1850 'func'=>[qw( sin cos )],
1855 @xt=$I2P->translate($opts{'xexpr'});
1856 @yt=$I2P->translate($opts{'yexpr'});
1858 $numre=$I2P->{'numre'};
1861 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1862 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1863 @{$opts{'parm'}}=@pt;
1866 # print Dumper(\%opts);
1868 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1869 $self->{ERRSTR}='transform: no xopcodes given.';
1873 @op=@{$opts{'xopcodes'}};
1875 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1876 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1879 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1885 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1886 $self->{ERRSTR}='transform: no yopcodes given.';
1890 @op=@{$opts{'yopcodes'}};
1892 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1893 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1896 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1901 if ( !exists $opts{'parm'}) {
1902 $self->{ERRSTR}='transform: no parameter arg given.';
1906 # print Dumper(\@ropx);
1907 # print Dumper(\@ropy);
1908 # print Dumper(\@ropy);
1910 my $img = Imager->new();
1911 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1912 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1918 my ($opts, @imgs) = @_;
1920 require "Imager/Expr.pm";
1922 $opts->{variables} = [ qw(x y) ];
1923 my ($width, $height) = @{$opts}{qw(width height)};
1925 $width ||= $imgs[0]->getwidth();
1926 $height ||= $imgs[0]->getheight();
1928 for my $img (@imgs) {
1929 $opts->{constants}{"w$img_num"} = $img->getwidth();
1930 $opts->{constants}{"h$img_num"} = $img->getheight();
1931 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1932 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1937 $opts->{constants}{w} = $width;
1938 $opts->{constants}{cx} = $width/2;
1941 $Imager::ERRSTR = "No width supplied";
1945 $opts->{constants}{h} = $height;
1946 $opts->{constants}{cy} = $height/2;
1949 $Imager::ERRSTR = "No height supplied";
1952 my $code = Imager::Expr->new($opts);
1954 $Imager::ERRSTR = Imager::Expr::error();
1957 my $channels = $opts->{channels} || 3;
1958 unless ($channels >= 1 && $channels <= 4) {
1959 return Imager->_set_error("channels must be an integer between 1 and 4");
1962 my $img = Imager->new();
1963 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1964 $channels, $code->code(),
1965 $code->nregs(), $code->cregs(),
1966 [ map { $_->{IMG} } @imgs ]);
1967 if (!defined $img->{IMG}) {
1968 $Imager::ERRSTR = Imager->_error_as_msg();
1977 my %opts=(tx => 0,ty => 0, @_);
1979 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1980 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1982 %opts = (src_minx => 0,
1984 src_maxx => $opts{src}->getwidth(),
1985 src_maxy => $opts{src}->getheight(),
1988 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1989 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1990 $self->{ERRSTR} = $self->_error_as_msg();
2000 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2002 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2003 $dir = $xlate{$opts{'dir'}};
2004 return $self if i_flipxy($self->{IMG}, $dir);
2012 unless (defined wantarray) {
2013 my @caller = caller;
2014 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2018 if (defined $opts{right}) {
2019 my $degrees = $opts{right};
2021 $degrees += 360 * int(((-$degrees)+360)/360);
2023 $degrees = $degrees % 360;
2024 if ($degrees == 0) {
2025 return $self->copy();
2027 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2028 my $result = Imager->new();
2029 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2033 $self->{ERRSTR} = $self->_error_as_msg();
2038 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2042 elsif (defined $opts{radians} || defined $opts{degrees}) {
2043 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2045 my $result = Imager->new;
2047 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
2050 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2052 if ($result->{IMG}) {
2056 $self->{ERRSTR} = $self->_error_as_msg();
2061 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2066 sub matrix_transform {
2070 unless (defined wantarray) {
2071 my @caller = caller;
2072 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2076 if ($opts{matrix}) {
2077 my $xsize = $opts{xsize} || $self->getwidth;
2078 my $ysize = $opts{ysize} || $self->getheight;
2080 my $result = Imager->new;
2082 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2083 $opts{matrix}, $opts{back})
2087 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2095 $self->{ERRSTR} = "matrix parameter required";
2101 *yatf = \&matrix_transform;
2103 # These two are supported for legacy code only
2106 return Imager::Color->new(@_);
2110 return Imager::Color::set(@_);
2113 # Draws a box between the specified corner points.
2116 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2117 my $dflcl=i_color_new(255,255,255,255);
2118 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2120 if (exists $opts{'box'}) {
2121 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
2122 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
2123 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
2124 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
2127 if ($opts{filled}) {
2128 my $color = _color($opts{'color'});
2130 $self->{ERRSTR} = $Imager::ERRSTR;
2133 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2134 $opts{ymax}, $color);
2136 elsif ($opts{fill}) {
2137 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2138 # assume it's a hash ref
2139 require 'Imager/Fill.pm';
2140 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2141 $self->{ERRSTR} = $Imager::ERRSTR;
2145 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2146 $opts{ymax},$opts{fill}{fill});
2149 my $color = _color($opts{'color'});
2151 $self->{ERRSTR} = $Imager::ERRSTR;
2154 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2162 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2163 my $dflcl=i_color_new(255,255,255,255);
2164 my %opts=(color=>$dflcl,
2165 'r'=>min($self->getwidth(),$self->getheight())/3,
2166 'x'=>$self->getwidth()/2,
2167 'y'=>$self->getheight()/2,
2168 'd1'=>0, 'd2'=>361, @_);
2171 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2172 # assume it's a hash ref
2173 require 'Imager/Fill.pm';
2174 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2175 $self->{ERRSTR} = $Imager::ERRSTR;
2179 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2180 $opts{'d2'}, $opts{fill}{fill});
2183 my $color = _color($opts{'color'});
2185 $self->{ERRSTR} = $Imager::ERRSTR;
2188 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2189 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2193 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2194 $opts{'d1'}, $opts{'d2'}, $color);
2200 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2201 # assume it's a hash ref
2202 require 'Imager/Fill.pm';
2203 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2204 $self->{ERRSTR} = $Imager::ERRSTR;
2208 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2209 $opts{'d2'}, $opts{fill}{fill});
2212 my $color = _color($opts{'color'});
2214 $self->{ERRSTR} = $Imager::ERRSTR;
2217 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2218 $opts{'d1'}, $opts{'d2'}, $color);
2225 # Draws a line from one point to the other
2226 # the endpoint is set if the endp parameter is set which it is by default.
2227 # to turn of the endpoint being set use endp=>0 when calling line.
2231 my $dflcl=i_color_new(0,0,0,0);
2232 my %opts=(color=>$dflcl,
2235 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2237 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2238 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2240 my $color = _color($opts{'color'});
2242 $self->{ERRSTR} = $Imager::ERRSTR;
2246 $opts{antialias} = $opts{aa} if defined $opts{aa};
2247 if ($opts{antialias}) {
2248 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2249 $color, $opts{endp});
2251 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2252 $color, $opts{endp});
2257 # Draws a line between an ordered set of points - It more or less just transforms this
2258 # into a list of lines.
2262 my ($pt,$ls,@points);
2263 my $dflcl=i_color_new(0,0,0,0);
2264 my %opts=(color=>$dflcl,@_);
2266 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2268 if (exists($opts{points})) { @points=@{$opts{points}}; }
2269 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2270 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2273 # print Dumper(\@points);
2275 my $color = _color($opts{'color'});
2277 $self->{ERRSTR} = $Imager::ERRSTR;
2280 $opts{antialias} = $opts{aa} if defined $opts{aa};
2281 if ($opts{antialias}) {
2284 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2291 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2301 my ($pt,$ls,@points);
2302 my $dflcl = i_color_new(0,0,0,0);
2303 my %opts = (color=>$dflcl, @_);
2305 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2307 if (exists($opts{points})) {
2308 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2309 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2312 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2313 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2316 if ($opts{'fill'}) {
2317 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2318 # assume it's a hash ref
2319 require 'Imager/Fill.pm';
2320 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2321 $self->{ERRSTR} = $Imager::ERRSTR;
2325 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2326 $opts{'fill'}{'fill'});
2329 my $color = _color($opts{'color'});
2331 $self->{ERRSTR} = $Imager::ERRSTR;
2334 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2341 # this the multipoint bezier curve
2342 # this is here more for testing that actual usage since
2343 # this is not a good algorithm. Usually the curve would be
2344 # broken into smaller segments and each done individually.
2348 my ($pt,$ls,@points);
2349 my $dflcl=i_color_new(0,0,0,0);
2350 my %opts=(color=>$dflcl,@_);
2352 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2354 if (exists $opts{points}) {
2355 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2356 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2359 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2360 $self->{ERRSTR}='Missing or invalid points.';
2364 my $color = _color($opts{'color'});
2366 $self->{ERRSTR} = $Imager::ERRSTR;
2369 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2375 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2378 unless (exists $opts{'x'} && exists $opts{'y'}) {
2379 $self->{ERRSTR} = "missing seed x and y parameters";
2384 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2385 # assume it's a hash ref
2386 require 'Imager/Fill.pm';
2387 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2388 $self->{ERRSTR} = $Imager::ERRSTR;
2392 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2395 my $color = _color($opts{'color'});
2397 $self->{ERRSTR} = $Imager::ERRSTR;
2400 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2402 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2408 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2410 unless (exists $opts{'x'} && exists $opts{'y'}) {
2411 $self->{ERRSTR} = 'missing x and y parameters';
2417 my $color = _color($opts{color})
2419 if (ref $x && ref $y) {
2420 unless (@$x == @$y) {
2421 $self->{ERRSTR} = 'length of x and y mismatch';
2424 if ($color->isa('Imager::Color')) {
2425 for my $i (0..$#{$opts{'x'}}) {
2426 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2430 for my $i (0..$#{$opts{'x'}}) {
2431 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2436 if ($color->isa('Imager::Color')) {
2437 i_ppix($self->{IMG}, $x, $y, $color);
2440 i_ppixf($self->{IMG}, $x, $y, $color);
2450 my %opts = ( "type"=>'8bit', @_);
2452 unless (exists $opts{'x'} && exists $opts{'y'}) {
2453 $self->{ERRSTR} = 'missing x and y parameters';
2459 if (ref $x && ref $y) {
2460 unless (@$x == @$y) {
2461 $self->{ERRSTR} = 'length of x and y mismatch';
2465 if ($opts{"type"} eq '8bit') {
2466 for my $i (0..$#{$opts{'x'}}) {
2467 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2471 for my $i (0..$#{$opts{'x'}}) {
2472 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2475 return wantarray ? @result : \@result;
2478 if ($opts{"type"} eq '8bit') {
2479 return i_get_pixel($self->{IMG}, $x, $y);
2482 return i_gpixf($self->{IMG}, $x, $y);
2491 my %opts = ( type => '8bit', x=>0, @_);
2493 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2495 unless (defined $opts{'y'}) {
2496 $self->_set_error("missing y parameter");
2500 if ($opts{type} eq '8bit') {
2501 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2504 elsif ($opts{type} eq 'float') {
2505 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2509 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2516 my %opts = ( x=>0, @_);
2518 unless (defined $opts{'y'}) {
2519 $self->_set_error("missing y parameter");
2524 if (ref $opts{pixels} && @{$opts{pixels}}) {
2525 # try to guess the type
2526 if ($opts{pixels}[0]->isa('Imager::Color')) {
2527 $opts{type} = '8bit';
2529 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2530 $opts{type} = 'float';
2533 $self->_set_error("missing type parameter and could not guess from pixels");
2539 $opts{type} = '8bit';
2543 if ($opts{type} eq '8bit') {
2544 if (ref $opts{pixels}) {
2545 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2548 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2551 elsif ($opts{type} eq 'float') {
2552 if (ref $opts{pixels}) {
2553 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2556 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2560 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2567 my %opts = ( type => '8bit', x=>0, @_);
2569 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2571 unless (defined $opts{'y'}) {
2572 $self->_set_error("missing y parameter");
2576 unless ($opts{channels}) {
2577 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2580 if ($opts{type} eq '8bit') {
2581 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2582 $opts{y}, @{$opts{channels}});
2584 elsif ($opts{type} eq 'float') {
2585 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2586 $opts{y}, @{$opts{channels}});
2589 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2594 # make an identity matrix of the given size
2598 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2599 for my $c (0 .. ($size-1)) {
2600 $matrix->[$c][$c] = 1;
2605 # general function to convert an image
2607 my ($self, %opts) = @_;
2610 unless (defined wantarray) {
2611 my @caller = caller;
2612 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2616 # the user can either specify a matrix or preset
2617 # the matrix overrides the preset
2618 if (!exists($opts{matrix})) {
2619 unless (exists($opts{preset})) {
2620 $self->{ERRSTR} = "convert() needs a matrix or preset";
2624 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2625 # convert to greyscale, keeping the alpha channel if any
2626 if ($self->getchannels == 3) {
2627 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2629 elsif ($self->getchannels == 4) {
2630 # preserve the alpha channel
2631 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2636 $matrix = _identity($self->getchannels);
2639 elsif ($opts{preset} eq 'noalpha') {
2640 # strip the alpha channel
2641 if ($self->getchannels == 2 or $self->getchannels == 4) {
2642 $matrix = _identity($self->getchannels);
2643 pop(@$matrix); # lose the alpha entry
2646 $matrix = _identity($self->getchannels);
2649 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2651 $matrix = [ [ 1 ] ];
2653 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2654 $matrix = [ [ 0, 1 ] ];
2656 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2657 $matrix = [ [ 0, 0, 1 ] ];
2659 elsif ($opts{preset} eq 'alpha') {
2660 if ($self->getchannels == 2 or $self->getchannels == 4) {
2661 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2664 # the alpha is just 1 <shrug>
2665 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2668 elsif ($opts{preset} eq 'rgb') {
2669 if ($self->getchannels == 1) {
2670 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2672 elsif ($self->getchannels == 2) {
2673 # preserve the alpha channel
2674 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2677 $matrix = _identity($self->getchannels);
2680 elsif ($opts{preset} eq 'addalpha') {
2681 if ($self->getchannels == 1) {
2682 $matrix = _identity(2);
2684 elsif ($self->getchannels == 3) {
2685 $matrix = _identity(4);
2688 $matrix = _identity($self->getchannels);
2692 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2698 $matrix = $opts{matrix};
2701 my $new = Imager->new();
2702 $new->{IMG} = i_img_new();
2703 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2704 # most likely a bad matrix
2705 $self->{ERRSTR} = _error_as_msg();
2712 # general function to map an image through lookup tables
2715 my ($self, %opts) = @_;
2716 my @chlist = qw( red green blue alpha );
2718 if (!exists($opts{'maps'})) {
2719 # make maps from channel maps
2721 for $chnum (0..$#chlist) {
2722 if (exists $opts{$chlist[$chnum]}) {
2723 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2724 } elsif (exists $opts{'all'}) {
2725 $opts{'maps'}[$chnum] = $opts{'all'};
2729 if ($opts{'maps'} and $self->{IMG}) {
2730 i_map($self->{IMG}, $opts{'maps'} );
2736 my ($self, %opts) = @_;
2738 defined $opts{mindist} or $opts{mindist} = 0;
2740 defined $opts{other}
2741 or return $self->_set_error("No 'other' parameter supplied");
2742 defined $opts{other}{IMG}
2743 or return $self->_set_error("No image data in 'other' image");
2746 or return $self->_set_error("No image data");
2748 my $result = Imager->new;
2749 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2751 or return $self->_set_error($self->_error_as_msg());
2756 # destructive border - image is shrunk by one pixel all around
2759 my ($self,%opts)=@_;
2760 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2761 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2765 # Get the width of an image
2769 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2770 return (i_img_info($self->{IMG}))[0];
2773 # Get the height of an image
2777 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2778 return (i_img_info($self->{IMG}))[1];
2781 # Get number of channels in an image
2785 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2786 return i_img_getchannels($self->{IMG});
2793 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2794 return i_img_getmask($self->{IMG});
2802 if (!defined($self->{IMG})) {
2803 $self->{ERRSTR} = 'image is empty';
2806 unless (defined $opts{mask}) {
2807 $self->_set_error("mask parameter required");
2810 i_img_setmask( $self->{IMG} , $opts{mask} );
2815 # Get number of colors in an image
2819 my %opts=('maxcolors'=>2**30,@_);
2820 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2821 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2822 return ($rc==-1? undef : $rc);
2825 # draw string to an image
2829 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2831 my %input=('x'=>0, 'y'=>0, @_);
2832 $input{string}||=$input{text};
2834 unless(defined $input{string}) {
2835 $self->{ERRSTR}="missing required parameter 'string'";
2839 unless($input{font}) {
2840 $self->{ERRSTR}="missing required parameter 'font'";
2844 unless ($input{font}->draw(image=>$self, %input)) {
2856 unless ($self->{IMG}) {
2857 $self->{ERRSTR}='empty input image';
2866 my %input=('x'=>0, 'y'=>0, @_);
2867 $input{string}||=$input{text};
2869 unless(exists $input{string}) {
2870 $self->_set_error("missing required parameter 'string'");
2874 unless($input{font}) {
2875 $self->_set_error("missing required parameter 'font'");
2880 unless (@result = $input{font}->align(image=>$img, %input)) {
2884 return wantarray ? @result : $result[0];
2887 my @file_limit_names = qw/width height bytes/;
2889 sub set_file_limits {
2896 @values{@file_limit_names} = (0) x @file_limit_names;
2899 @values{@file_limit_names} = i_get_image_file_limits();
2902 for my $key (keys %values) {
2903 defined $opts{$key} and $values{$key} = $opts{$key};
2906 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
2909 sub get_file_limits {
2910 i_get_image_file_limits();
2913 # Shortcuts that can be exported
2915 sub newcolor { Imager::Color->new(@_); }
2916 sub newfont { Imager::Font->new(@_); }
2918 *NC=*newcolour=*newcolor;
2925 #### Utility routines
2928 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2932 my ($self, $msg) = @_;
2935 $self->{ERRSTR} = $msg;
2943 # Default guess for the type of an image from extension
2945 sub def_guess_type {
2948 $ext=($name =~ m/\.([^\.]+)$/)[0];
2949 return 'tiff' if ($ext =~ m/^tiff?$/);
2950 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2951 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2952 return 'png' if ($ext eq "png");
2953 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2954 return 'tga' if ($ext eq "tga");
2955 return 'rgb' if ($ext eq "rgb");
2956 return 'gif' if ($ext eq "gif");
2957 return 'raw' if ($ext eq "raw");
2961 # get the minimum of a list
2965 for(@_) { if ($_<$mx) { $mx=$_; }}
2969 # get the maximum of a list
2973 for(@_) { if ($_>$mx) { $mx=$_; }}
2977 # string stuff for iptc headers
2981 $str = substr($str,3);
2982 $str =~ s/[\n\r]//g;
2989 # A little hack to parse iptc headers.
2994 my($caption,$photogr,$headln,$credit);
2996 my $str=$self->{IPTCRAW};
3000 @ar=split(/8BIM/,$str);
3005 @sar=split(/\034\002/);
3006 foreach $item (@sar) {
3007 if ($item =~ m/^x/) {
3008 $caption=&clean($item);
3011 if ($item =~ m/^P/) {
3012 $photogr=&clean($item);
3015 if ($item =~ m/^i/) {
3016 $headln=&clean($item);
3019 if ($item =~ m/^n/) {
3020 $credit=&clean($item);
3026 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3033 or die "Only C language supported";
3035 require Imager::ExtUtils;
3036 return Imager::ExtUtils->inline_config;
3041 # Below is the stub of documentation for your module. You better edit it!
3045 Imager - Perl extension for Generating 24 bit Images
3055 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3060 my $img = Imager->new();
3061 # see Imager::Files for information on the read() method
3062 $img->read(file=>$file) or die $img->errstr();
3064 $file =~ s/\.[^.]*$//;
3066 # Create smaller version
3067 # documented in Imager::Transformations
3068 my $thumb = $img->scale(scalefactor=>.3);
3070 # Autostretch individual channels
3071 $thumb->filter(type=>'autolevels');
3073 # try to save in one of these formats
3076 for $format ( qw( png gif jpg tiff ppm ) ) {
3077 # Check if given format is supported
3078 if ($Imager::formats{$format}) {
3079 $file.="_low.$format";
3080 print "Storing image as: $file\n";
3081 # documented in Imager::Files
3082 $thumb->write(file=>$file) or
3090 Imager is a module for creating and altering images. It can read and
3091 write various image formats, draw primitive shapes like lines,and
3092 polygons, blend multiple images together in various ways, scale, crop,
3093 render text and more.
3095 =head2 Overview of documentation
3101 Imager - This document - Synopsis Example, Table of Contents and
3106 L<Imager::Tutorial> - a brief introduction to Imager.
3110 L<Imager::Cookbook> - how to do various things with Imager.
3114 L<Imager::ImageTypes> - Basics of constructing image objects with
3115 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3116 8/16/double bits/channel, color maps, channel masks, image tags, color
3117 quantization. Also discusses basic image information methods.
3121 L<Imager::Files> - IO interaction, reading/writing images, format
3126 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3131 L<Imager::Color> - Color specification.
3135 L<Imager::Fill> - Fill pattern specification.
3139 L<Imager::Font> - General font rendering, bounding boxes and font
3144 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3145 blending, pasting, convert and map.
3149 L<Imager::Engines> - Programmable transformations through
3150 C<transform()>, C<transform2()> and C<matrix_transform()>.
3154 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3159 L<Imager::Expr> - Expressions for evaluation engine used by
3164 L<Imager::Matrix2d> - Helper class for affine transformations.
3168 L<Imager::Fountain> - Helper for making gradient profiles.
3172 L<Imager::API> - using Imager's C API
3176 L<Imager::APIRef> - API function reference
3180 L<Imager::Inline> - using Imager's C API from Inline::C
3184 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3188 =head2 Basic Overview
3190 An Image object is created with C<$img = Imager-E<gt>new()>.
3193 $img=Imager->new(); # create empty image
3194 $img->read(file=>'lena.png',type=>'png') or # read image from file
3195 die $img->errstr(); # give an explanation
3196 # if something failed
3198 or if you want to create an empty image:
3200 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3202 This example creates a completely black image of width 400 and height
3205 When an operation fails which can be directly associated with an image
3206 the error message is stored can be retrieved with
3207 C<$img-E<gt>errstr()>.
3209 In cases where no image object is associated with an operation
3210 C<$Imager::ERRSTR> is used to report errors not directly associated
3211 with an image object. You can also call C<Imager->errstr> to get this
3214 The C<Imager-E<gt>new> method is described in detail in
3215 L<Imager::ImageTypes>.
3219 Where to find information on methods for Imager class objects.
3221 addcolors() - L<Imager::ImageTypes/addcolors>
3223 addtag() - L<Imager::ImageTypes/addtag> - add image tags
3225 arc() - L<Imager::Draw/arc>
3227 align_string() - L<Imager::Draw/align_string>
3229 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
3232 box() - L<Imager::Draw/box>
3234 circle() - L<Imager::Draw/circle>
3236 colorcount() - L<Imager::Draw/colorcount>
3238 convert() - L<Imager::Transformations/"Color transformations"> -
3239 transform the color space
3241 copy() - L<Imager::Transformations/copy>
3243 crop() - L<Imager::Transformations/crop> - extract part of an image
3245 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
3247 difference() - L<Imager::Filters/"Image Difference">
3249 errstr() - L<"Basic Overview">
3251 filter() - L<Imager::Filters>
3253 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
3256 flip() - L<Imager::Transformations/flip>
3258 flood_fill() - L<Imager::Draw/flood_fill>
3260 getchannels() - L<Imager::ImageTypes/getchannels>
3262 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
3264 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
3265 palette, if it has one
3267 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3269 getheight() - L<Imager::ImageTypes/getwidth>
3271 getpixel() - L<Imager::Draw/getpixel>
3273 getsamples() - L<Imager::Draw/getsamples>
3275 getscanline() - L<Imager::Draw/getscanline>
3277 getwidth() - L<Imager::ImageTypes/getwidth>
3279 img_set() - L<Imager::ImageTypes/img_set>
3281 line() - L<Imager::Draw/line>
3283 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3286 masked() - L<Imager::ImageTypes/masked> - make a masked image
3288 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
3290 maxcolors() - L<Imager::ImageTypes/maxcolors>
3292 new() - L<Imager::ImageTypes/new>
3294 open() - L<Imager::Files> - an alias for read()
3296 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3298 polygon() - L<Imager::Draw/polygon>
3300 polyline() - L<Imager::Draw/polyline>
3302 read() - L<Imager::Files> - read a single image from an image file
3304 read_multi() - L<Imager::Files> - read multiple images from an image
3307 rotate() - L<Imager::Transformations/rotate>
3309 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3310 image and use the alpha channel
3312 scale() - L<Imager::Transformations/scale>
3314 setscanline() - L<Imager::Draw/setscanline>
3316 scaleX() - L<Imager::Transformations/scaleX>
3318 scaleY() - L<Imager::Transformations/scaleY>
3320 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
3323 setpixel() - L<Imager::Draw/setpixel>
3325 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3327 string() - L<Imager::Draw/string> - draw text on an image
3329 tags() - L<Imager::ImageTypes/tags> - fetch image tags
3331 to_paletted() - L<Imager::ImageTypes/to_paletted>
3333 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
3335 transform() - L<Imager::Engines/"transform">
3337 transform2() - L<Imager::Engines/"transform2">
3339 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
3341 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
3344 write() - L<Imager::Files> - write an image to a file
3346 write_multi() - L<Imager::Files> - write multiple image to an image
3349 =head1 CONCEPT INDEX
3351 animated GIF - L<Imager::File/"Writing an animated GIF">
3353 aspect ratio - L<Imager::ImageTypes/i_xres>,
3354 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3356 blend - alpha blending one image onto another
3357 L<Imager::Transformations/rubthrough>
3359 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3361 boxes, drawing - L<Imager::Draw/box>
3363 changes between image - L<Imager::Filter/"Image Difference">
3365 color - L<Imager::Color>
3367 color names - L<Imager::Color>, L<Imager::Color::Table>
3369 combine modes - L<Imager::Fill/combine>
3371 compare images - L<Imager::Filter/"Image Difference">
3373 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3375 convolution - L<Imager::Filter/conv>
3377 cropping - L<Imager::Transformations/crop>
3379 C<diff> images - L<Imager::Filter/"Image Difference">
3381 dpi - L<Imager::ImageTypes/i_xres>
3383 drawing boxes - L<Imager::Draw/box>
3385 drawing lines - L<Imager::Draw/line>
3387 drawing text - L<Imager::Font/string>, L<Imager::Font/align>
3389 error message - L<"Basic Overview">
3391 files, font - L<Imager::Font>
3393 files, image - L<Imager::Files>
3395 filling, types of fill - L<Imager::Fill>
3397 filling, boxes - L<Imager::Draw/box>
3399 filling, flood fill - L<Imager::Draw/flood_fill>
3401 flood fill - L<Imager::Draw/flood_fill>
3403 fonts - L<Imager::Font>
3405 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3406 L<Imager::Font::Wrap>
3408 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3410 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3412 fountain fill - L<Imager::Fill/"Fountain fills">,
3413 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3414 L<Imager::Filters/gradgen>
3416 GIF files - L<Imager::Files/"GIF">
3418 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3420 gradient fill - L<Imager::Fill/"Fountain fills">,
3421 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3422 L<Imager::Filters/gradgen>
3424 guassian blur - L<Imager::Filter/guassian>
3426 hatch fills - L<Imager::Fill/"Hatched fills">
3428 invert image - L<Imager::Filter/hardinvert>
3430 JPEG - L<Imager::Files/"JPEG">
3432 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3434 lines, drawing - L<Imager::Draw/line>
3436 matrix - L<Imager::Matrix2d>,
3437 L<Imager::Transformations/"Matrix Transformations">,
3438 L<Imager::Font/transform>
3440 metadata, image - L<Imager::ImageTypes/"Tags">
3442 mosaic - L<Imager::Filter/mosaic>
3444 noise, filter - L<Imager::Filter/noise>
3446 noise, rendered - L<Imager::Filter/turbnoise>,
3447 L<Imager::Filter/radnoise>
3449 paste - L<Imager::Transformations/paste>,
3450 L<Imager::Transformations/rubthrough>
3452 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
3453 L<Imager::ImageTypes/new>
3455 posterize - L<Imager::Filter/postlevels>
3457 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3459 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3461 rectangles, drawing - L<Imager::Draw/box>
3463 resizing an image - L<Imager::Transformations/scale>,
3464 L<Imager::Transformations/crop>
3466 saving an image - L<Imager::Files>
3468 scaling - L<Imager::Transformations/scale>
3470 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3472 size, image - L<Imager::ImageTypes/getwidth>,
3473 L<Imager::ImageTypes/getheight>
3475 size, text - L<Imager::Font/bounding_box>
3477 tags, image metadata - L<Imager::ImageTypes/"Tags">
3479 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
3480 L<Imager::Font::Wrap>
3482 text, wrapping text in an area - L<Imager::Font::Wrap>
3484 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3486 tiles, color - L<Imager::Filter/mosaic>
3488 unsharp mask - L<Imager::Filter/unsharpmask>
3490 watermark - L<Imager::Filter/watermark>
3492 writing an image to a file - L<Imager::Files>
3496 You can ask for help, report bugs or express your undying love for
3497 Imager on the Imager-devel mailing list.
3499 To subscribe send a message with C<subscribe> in the body to:
3501 imager-devel+request@molar.is
3507 L<http://www.molar.is/en/lists/imager-devel/>
3511 where you can also find the mailing list archive.
3513 If you're into IRC, you can typically find the developers in #Imager
3514 on irc.perl.org. As with any IRC channel, the participants could be
3515 occupied or asleep, so please be patient.
3517 You can report bugs by pointing your browser at:
3521 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
3525 Please remember to include the versions of Imager, perl, supporting
3526 libraries, and any relevant code. If you have specific images that
3527 cause the problems, please include those too.
3531 Bugs are listed individually for relevant pod pages.
3535 Arnar M. Hrafnkelsson and Tony Cook (tony@imager.perl.org) among
3536 others. See the README for a complete list.
3540 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
3541 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
3542 L<Imager::Font>(3), L<Imager::Transformations>(3),
3543 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
3544 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
3546 L<http://imager.perl.org/>
3548 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
3550 Other perl imaging modules include:
3552 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).