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},
1685 %{$filters{$input{'type'}}{defaults}},
1688 %hsh=( image => $self->{IMG},
1693 my @cs=@{$filters{$input{'type'}}{callseq}};
1696 if (!defined($hsh{$_})) {
1697 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
1702 local $SIG{__DIE__}; # we don't want this processed by confess, etc
1703 &{$filters{$input{'type'}}{callsub}}(%hsh);
1706 chomp($self->{ERRSTR} = $@);
1712 $self->{DEBUG} && print "callseq is: @cs\n";
1713 $self->{DEBUG} && print "matching callseq is: @b\n";
1718 sub register_filter {
1720 my %hsh = ( defaults => {}, @_ );
1723 or die "register_filter() with no type\n";
1724 defined $hsh{callsub}
1725 or die "register_filter() with no callsub\n";
1726 defined $hsh{callseq}
1727 or die "register_filter() with no callseq\n";
1729 exists $filters{$hsh{type}}
1732 $filters{$hsh{type}} = \%hsh;
1737 # Scale an image to requested size and return the scaled version
1741 my %opts=(scalefactor=>0.5,'type'=>'max',qtype=>'normal',@_);
1742 my $img = Imager->new();
1743 my $tmp = Imager->new();
1745 unless (defined wantarray) {
1746 my @caller = caller;
1747 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
1751 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1753 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
1754 my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
1755 if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
1756 if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
1757 } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
1758 elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
1760 if ($opts{qtype} eq 'normal') {
1761 $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1762 if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1763 $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
1764 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1767 if ($opts{'qtype'} eq 'preview') {
1768 $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
1769 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1772 $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
1775 # Scales only along the X axis
1779 my %opts=(scalefactor=>0.5,@_);
1781 unless (defined wantarray) {
1782 my @caller = caller;
1783 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
1787 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1789 my $img = Imager->new();
1791 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
1793 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1794 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
1796 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1800 # Scales only along the Y axis
1804 my %opts=(scalefactor=>0.5,@_);
1806 unless (defined wantarray) {
1807 my @caller = caller;
1808 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
1812 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1814 my $img = Imager->new();
1816 if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
1818 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1819 $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
1821 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
1826 # Transform returns a spatial transformation of the input image
1827 # this moves pixels to a new location in the returned image.
1828 # NOTE - should make a utility function to check transforms for
1833 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1835 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
1837 # print Dumper(\%opts);
1840 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
1842 eval ("use Affix::Infix2Postfix;");
1845 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
1848 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
1849 {op=>'-',trans=>'Sub'},
1850 {op=>'*',trans=>'Mult'},
1851 {op=>'/',trans=>'Div'},
1852 {op=>'-','type'=>'unary',trans=>'u-'},
1854 {op=>'func','type'=>'unary'}],
1855 'grouping'=>[qw( \( \) )],
1856 'func'=>[qw( sin cos )],
1861 @xt=$I2P->translate($opts{'xexpr'});
1862 @yt=$I2P->translate($opts{'yexpr'});
1864 $numre=$I2P->{'numre'};
1867 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
1868 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
1869 @{$opts{'parm'}}=@pt;
1872 # print Dumper(\%opts);
1874 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
1875 $self->{ERRSTR}='transform: no xopcodes given.';
1879 @op=@{$opts{'xopcodes'}};
1881 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1882 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1885 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1891 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
1892 $self->{ERRSTR}='transform: no yopcodes given.';
1896 @op=@{$opts{'yopcodes'}};
1898 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
1899 $self->{ERRSTR}="transform: illegal opcode '$_'.";
1902 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
1907 if ( !exists $opts{'parm'}) {
1908 $self->{ERRSTR}='transform: no parameter arg given.';
1912 # print Dumper(\@ropx);
1913 # print Dumper(\@ropy);
1914 # print Dumper(\@ropy);
1916 my $img = Imager->new();
1917 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
1918 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
1924 my ($opts, @imgs) = @_;
1926 require "Imager/Expr.pm";
1928 $opts->{variables} = [ qw(x y) ];
1929 my ($width, $height) = @{$opts}{qw(width height)};
1931 $width ||= $imgs[0]->getwidth();
1932 $height ||= $imgs[0]->getheight();
1934 for my $img (@imgs) {
1935 $opts->{constants}{"w$img_num"} = $img->getwidth();
1936 $opts->{constants}{"h$img_num"} = $img->getheight();
1937 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
1938 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
1943 $opts->{constants}{w} = $width;
1944 $opts->{constants}{cx} = $width/2;
1947 $Imager::ERRSTR = "No width supplied";
1951 $opts->{constants}{h} = $height;
1952 $opts->{constants}{cy} = $height/2;
1955 $Imager::ERRSTR = "No height supplied";
1958 my $code = Imager::Expr->new($opts);
1960 $Imager::ERRSTR = Imager::Expr::error();
1963 my $channels = $opts->{channels} || 3;
1964 unless ($channels >= 1 && $channels <= 4) {
1965 return Imager->_set_error("channels must be an integer between 1 and 4");
1968 my $img = Imager->new();
1969 $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
1970 $channels, $code->code(),
1971 $code->nregs(), $code->cregs(),
1972 [ map { $_->{IMG} } @imgs ]);
1973 if (!defined $img->{IMG}) {
1974 $Imager::ERRSTR = Imager->_error_as_msg();
1983 my %opts=(tx => 0,ty => 0, @_);
1985 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
1986 unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
1988 %opts = (src_minx => 0,
1990 src_maxx => $opts{src}->getwidth(),
1991 src_maxy => $opts{src}->getheight(),
1994 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
1995 $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
1996 $self->{ERRSTR} = $self->_error_as_msg();
2006 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2008 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2009 $dir = $xlate{$opts{'dir'}};
2010 return $self if i_flipxy($self->{IMG}, $dir);
2018 unless (defined wantarray) {
2019 my @caller = caller;
2020 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2024 if (defined $opts{right}) {
2025 my $degrees = $opts{right};
2027 $degrees += 360 * int(((-$degrees)+360)/360);
2029 $degrees = $degrees % 360;
2030 if ($degrees == 0) {
2031 return $self->copy();
2033 elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2034 my $result = Imager->new();
2035 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2039 $self->{ERRSTR} = $self->_error_as_msg();
2044 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2048 elsif (defined $opts{radians} || defined $opts{degrees}) {
2049 my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
2051 my $result = Imager->new;
2053 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
2056 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2058 if ($result->{IMG}) {
2062 $self->{ERRSTR} = $self->_error_as_msg();
2067 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2072 sub matrix_transform {
2076 unless (defined wantarray) {
2077 my @caller = caller;
2078 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2082 if ($opts{matrix}) {
2083 my $xsize = $opts{xsize} || $self->getwidth;
2084 my $ysize = $opts{ysize} || $self->getheight;
2086 my $result = Imager->new;
2088 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2089 $opts{matrix}, $opts{back})
2093 $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2101 $self->{ERRSTR} = "matrix parameter required";
2107 *yatf = \&matrix_transform;
2109 # These two are supported for legacy code only
2112 return Imager::Color->new(@_);
2116 return Imager::Color::set(@_);
2119 # Draws a box between the specified corner points.
2122 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2123 my $dflcl=i_color_new(255,255,255,255);
2124 my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
2126 if (exists $opts{'box'}) {
2127 $opts{'xmin'} = min($opts{'box'}->[0],$opts{'box'}->[2]);
2128 $opts{'xmax'} = max($opts{'box'}->[0],$opts{'box'}->[2]);
2129 $opts{'ymin'} = min($opts{'box'}->[1],$opts{'box'}->[3]);
2130 $opts{'ymax'} = max($opts{'box'}->[1],$opts{'box'}->[3]);
2133 if ($opts{filled}) {
2134 my $color = _color($opts{'color'});
2136 $self->{ERRSTR} = $Imager::ERRSTR;
2139 i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2140 $opts{ymax}, $color);
2142 elsif ($opts{fill}) {
2143 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2144 # assume it's a hash ref
2145 require 'Imager/Fill.pm';
2146 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2147 $self->{ERRSTR} = $Imager::ERRSTR;
2151 i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
2152 $opts{ymax},$opts{fill}{fill});
2155 my $color = _color($opts{'color'});
2157 $self->{ERRSTR} = $Imager::ERRSTR;
2160 i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
2168 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2169 my $dflcl=i_color_new(255,255,255,255);
2170 my %opts=(color=>$dflcl,
2171 'r'=>min($self->getwidth(),$self->getheight())/3,
2172 'x'=>$self->getwidth()/2,
2173 'y'=>$self->getheight()/2,
2174 'd1'=>0, 'd2'=>361, @_);
2177 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2178 # assume it's a hash ref
2179 require 'Imager/Fill.pm';
2180 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2181 $self->{ERRSTR} = $Imager::ERRSTR;
2185 i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2186 $opts{'d2'}, $opts{fill}{fill});
2189 my $color = _color($opts{'color'});
2191 $self->{ERRSTR} = $Imager::ERRSTR;
2194 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
2195 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
2199 i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2200 $opts{'d1'}, $opts{'d2'}, $color);
2206 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2207 # assume it's a hash ref
2208 require 'Imager/Fill.pm';
2209 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2210 $self->{ERRSTR} = $Imager::ERRSTR;
2214 i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
2215 $opts{'d2'}, $opts{fill}{fill});
2218 my $color = _color($opts{'color'});
2220 $self->{ERRSTR} = $Imager::ERRSTR;
2223 i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
2224 $opts{'d1'}, $opts{'d2'}, $color);
2231 # Draws a line from one point to the other
2232 # the endpoint is set if the endp parameter is set which it is by default.
2233 # to turn of the endpoint being set use endp=>0 when calling line.
2237 my $dflcl=i_color_new(0,0,0,0);
2238 my %opts=(color=>$dflcl,
2241 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2243 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
2244 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
2246 my $color = _color($opts{'color'});
2248 $self->{ERRSTR} = $Imager::ERRSTR;
2252 $opts{antialias} = $opts{aa} if defined $opts{aa};
2253 if ($opts{antialias}) {
2254 i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2255 $color, $opts{endp});
2257 i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
2258 $color, $opts{endp});
2263 # Draws a line between an ordered set of points - It more or less just transforms this
2264 # into a list of lines.
2268 my ($pt,$ls,@points);
2269 my $dflcl=i_color_new(0,0,0,0);
2270 my %opts=(color=>$dflcl,@_);
2272 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2274 if (exists($opts{points})) { @points=@{$opts{points}}; }
2275 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
2276 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
2279 # print Dumper(\@points);
2281 my $color = _color($opts{'color'});
2283 $self->{ERRSTR} = $Imager::ERRSTR;
2286 $opts{antialias} = $opts{aa} if defined $opts{aa};
2287 if ($opts{antialias}) {
2290 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
2297 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
2307 my ($pt,$ls,@points);
2308 my $dflcl = i_color_new(0,0,0,0);
2309 my %opts = (color=>$dflcl, @_);
2311 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2313 if (exists($opts{points})) {
2314 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
2315 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
2318 if (!exists $opts{'x'} or !exists $opts{'y'}) {
2319 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
2322 if ($opts{'fill'}) {
2323 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
2324 # assume it's a hash ref
2325 require 'Imager/Fill.pm';
2326 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
2327 $self->{ERRSTR} = $Imager::ERRSTR;
2331 i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
2332 $opts{'fill'}{'fill'});
2335 my $color = _color($opts{'color'});
2337 $self->{ERRSTR} = $Imager::ERRSTR;
2340 i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2347 # this the multipoint bezier curve
2348 # this is here more for testing that actual usage since
2349 # this is not a good algorithm. Usually the curve would be
2350 # broken into smaller segments and each done individually.
2354 my ($pt,$ls,@points);
2355 my $dflcl=i_color_new(0,0,0,0);
2356 my %opts=(color=>$dflcl,@_);
2358 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2360 if (exists $opts{points}) {
2361 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
2362 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
2365 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
2366 $self->{ERRSTR}='Missing or invalid points.';
2370 my $color = _color($opts{'color'});
2372 $self->{ERRSTR} = $Imager::ERRSTR;
2375 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
2381 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
2384 unless (exists $opts{'x'} && exists $opts{'y'}) {
2385 $self->{ERRSTR} = "missing seed x and y parameters";
2390 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
2391 # assume it's a hash ref
2392 require 'Imager/Fill.pm';
2393 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
2394 $self->{ERRSTR} = $Imager::ERRSTR;
2398 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
2401 my $color = _color($opts{'color'});
2403 $self->{ERRSTR} = $Imager::ERRSTR;
2406 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
2408 if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
2414 my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
2416 unless (exists $opts{'x'} && exists $opts{'y'}) {
2417 $self->{ERRSTR} = 'missing x and y parameters';
2423 my $color = _color($opts{color})
2425 if (ref $x && ref $y) {
2426 unless (@$x == @$y) {
2427 $self->{ERRSTR} = 'length of x and y mismatch';
2430 if ($color->isa('Imager::Color')) {
2431 for my $i (0..$#{$opts{'x'}}) {
2432 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color);
2436 for my $i (0..$#{$opts{'x'}}) {
2437 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color);
2442 if ($color->isa('Imager::Color')) {
2443 i_ppix($self->{IMG}, $x, $y, $color);
2446 i_ppixf($self->{IMG}, $x, $y, $color);
2456 my %opts = ( "type"=>'8bit', @_);
2458 unless (exists $opts{'x'} && exists $opts{'y'}) {
2459 $self->{ERRSTR} = 'missing x and y parameters';
2465 if (ref $x && ref $y) {
2466 unless (@$x == @$y) {
2467 $self->{ERRSTR} = 'length of x and y mismatch';
2471 if ($opts{"type"} eq '8bit') {
2472 for my $i (0..$#{$opts{'x'}}) {
2473 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
2477 for my $i (0..$#{$opts{'x'}}) {
2478 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
2481 return wantarray ? @result : \@result;
2484 if ($opts{"type"} eq '8bit') {
2485 return i_get_pixel($self->{IMG}, $x, $y);
2488 return i_gpixf($self->{IMG}, $x, $y);
2497 my %opts = ( type => '8bit', x=>0, @_);
2499 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2501 unless (defined $opts{'y'}) {
2502 $self->_set_error("missing y parameter");
2506 if ($opts{type} eq '8bit') {
2507 return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2510 elsif ($opts{type} eq 'float') {
2511 return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2515 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2522 my %opts = ( x=>0, @_);
2524 unless (defined $opts{'y'}) {
2525 $self->_set_error("missing y parameter");
2530 if (ref $opts{pixels} && @{$opts{pixels}}) {
2531 # try to guess the type
2532 if ($opts{pixels}[0]->isa('Imager::Color')) {
2533 $opts{type} = '8bit';
2535 elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
2536 $opts{type} = 'float';
2539 $self->_set_error("missing type parameter and could not guess from pixels");
2545 $opts{type} = '8bit';
2549 if ($opts{type} eq '8bit') {
2550 if (ref $opts{pixels}) {
2551 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2554 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2557 elsif ($opts{type} eq 'float') {
2558 if (ref $opts{pixels}) {
2559 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
2562 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
2566 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2573 my %opts = ( type => '8bit', x=>0, @_);
2575 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
2577 unless (defined $opts{'y'}) {
2578 $self->_set_error("missing y parameter");
2582 unless ($opts{channels}) {
2583 $opts{channels} = [ 0 .. $self->getchannels()-1 ];
2586 if ($opts{type} eq '8bit') {
2587 return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2588 $opts{y}, @{$opts{channels}});
2590 elsif ($opts{type} eq 'float') {
2591 return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
2592 $opts{y}, @{$opts{channels}});
2595 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
2600 # make an identity matrix of the given size
2604 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
2605 for my $c (0 .. ($size-1)) {
2606 $matrix->[$c][$c] = 1;
2611 # general function to convert an image
2613 my ($self, %opts) = @_;
2616 unless (defined wantarray) {
2617 my @caller = caller;
2618 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
2622 # the user can either specify a matrix or preset
2623 # the matrix overrides the preset
2624 if (!exists($opts{matrix})) {
2625 unless (exists($opts{preset})) {
2626 $self->{ERRSTR} = "convert() needs a matrix or preset";
2630 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
2631 # convert to greyscale, keeping the alpha channel if any
2632 if ($self->getchannels == 3) {
2633 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
2635 elsif ($self->getchannels == 4) {
2636 # preserve the alpha channel
2637 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
2642 $matrix = _identity($self->getchannels);
2645 elsif ($opts{preset} eq 'noalpha') {
2646 # strip the alpha channel
2647 if ($self->getchannels == 2 or $self->getchannels == 4) {
2648 $matrix = _identity($self->getchannels);
2649 pop(@$matrix); # lose the alpha entry
2652 $matrix = _identity($self->getchannels);
2655 elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
2657 $matrix = [ [ 1 ] ];
2659 elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
2660 $matrix = [ [ 0, 1 ] ];
2662 elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
2663 $matrix = [ [ 0, 0, 1 ] ];
2665 elsif ($opts{preset} eq 'alpha') {
2666 if ($self->getchannels == 2 or $self->getchannels == 4) {
2667 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
2670 # the alpha is just 1 <shrug>
2671 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
2674 elsif ($opts{preset} eq 'rgb') {
2675 if ($self->getchannels == 1) {
2676 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
2678 elsif ($self->getchannels == 2) {
2679 # preserve the alpha channel
2680 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
2683 $matrix = _identity($self->getchannels);
2686 elsif ($opts{preset} eq 'addalpha') {
2687 if ($self->getchannels == 1) {
2688 $matrix = _identity(2);
2690 elsif ($self->getchannels == 3) {
2691 $matrix = _identity(4);
2694 $matrix = _identity($self->getchannels);
2698 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
2704 $matrix = $opts{matrix};
2707 my $new = Imager->new();
2708 $new->{IMG} = i_img_new();
2709 unless (i_convert($new->{IMG}, $self->{IMG}, $matrix)) {
2710 # most likely a bad matrix
2711 $self->{ERRSTR} = _error_as_msg();
2718 # general function to map an image through lookup tables
2721 my ($self, %opts) = @_;
2722 my @chlist = qw( red green blue alpha );
2724 if (!exists($opts{'maps'})) {
2725 # make maps from channel maps
2727 for $chnum (0..$#chlist) {
2728 if (exists $opts{$chlist[$chnum]}) {
2729 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
2730 } elsif (exists $opts{'all'}) {
2731 $opts{'maps'}[$chnum] = $opts{'all'};
2735 if ($opts{'maps'} and $self->{IMG}) {
2736 i_map($self->{IMG}, $opts{'maps'} );
2742 my ($self, %opts) = @_;
2744 defined $opts{mindist} or $opts{mindist} = 0;
2746 defined $opts{other}
2747 or return $self->_set_error("No 'other' parameter supplied");
2748 defined $opts{other}{IMG}
2749 or return $self->_set_error("No image data in 'other' image");
2752 or return $self->_set_error("No image data");
2754 my $result = Imager->new;
2755 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
2757 or return $self->_set_error($self->_error_as_msg());
2762 # destructive border - image is shrunk by one pixel all around
2765 my ($self,%opts)=@_;
2766 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
2767 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
2771 # Get the width of an image
2775 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2776 return (i_img_info($self->{IMG}))[0];
2779 # Get the height of an image
2783 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2784 return (i_img_info($self->{IMG}))[1];
2787 # Get number of channels in an image
2791 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2792 return i_img_getchannels($self->{IMG});
2799 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
2800 return i_img_getmask($self->{IMG});
2808 if (!defined($self->{IMG})) {
2809 $self->{ERRSTR} = 'image is empty';
2812 unless (defined $opts{mask}) {
2813 $self->_set_error("mask parameter required");
2816 i_img_setmask( $self->{IMG} , $opts{mask} );
2821 # Get number of colors in an image
2825 my %opts=('maxcolors'=>2**30,@_);
2826 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
2827 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
2828 return ($rc==-1? undef : $rc);
2831 # draw string to an image
2835 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2837 my %input=('x'=>0, 'y'=>0, @_);
2838 $input{string}||=$input{text};
2840 unless(defined $input{string}) {
2841 $self->{ERRSTR}="missing required parameter 'string'";
2845 unless($input{font}) {
2846 $self->{ERRSTR}="missing required parameter 'font'";
2850 unless ($input{font}->draw(image=>$self, %input)) {
2862 unless ($self->{IMG}) {
2863 $self->{ERRSTR}='empty input image';
2872 my %input=('x'=>0, 'y'=>0, @_);
2873 $input{string}||=$input{text};
2875 unless(exists $input{string}) {
2876 $self->_set_error("missing required parameter 'string'");
2880 unless($input{font}) {
2881 $self->_set_error("missing required parameter 'font'");
2886 unless (@result = $input{font}->align(image=>$img, %input)) {
2890 return wantarray ? @result : $result[0];
2893 my @file_limit_names = qw/width height bytes/;
2895 sub set_file_limits {
2902 @values{@file_limit_names} = (0) x @file_limit_names;
2905 @values{@file_limit_names} = i_get_image_file_limits();
2908 for my $key (keys %values) {
2909 defined $opts{$key} and $values{$key} = $opts{$key};
2912 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
2915 sub get_file_limits {
2916 i_get_image_file_limits();
2919 # Shortcuts that can be exported
2921 sub newcolor { Imager::Color->new(@_); }
2922 sub newfont { Imager::Font->new(@_); }
2924 *NC=*newcolour=*newcolor;
2931 #### Utility routines
2934 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
2938 my ($self, $msg) = @_;
2941 $self->{ERRSTR} = $msg;
2949 # Default guess for the type of an image from extension
2951 sub def_guess_type {
2954 $ext=($name =~ m/\.([^\.]+)$/)[0];
2955 return 'tiff' if ($ext =~ m/^tiff?$/);
2956 return 'jpeg' if ($ext =~ m/^jpe?g$/);
2957 return 'pnm' if ($ext =~ m/^p[pgb]m$/);
2958 return 'png' if ($ext eq "png");
2959 return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
2960 return 'tga' if ($ext eq "tga");
2961 return 'rgb' if ($ext eq "rgb");
2962 return 'gif' if ($ext eq "gif");
2963 return 'raw' if ($ext eq "raw");
2967 # get the minimum of a list
2971 for(@_) { if ($_<$mx) { $mx=$_; }}
2975 # get the maximum of a list
2979 for(@_) { if ($_>$mx) { $mx=$_; }}
2983 # string stuff for iptc headers
2987 $str = substr($str,3);
2988 $str =~ s/[\n\r]//g;
2995 # A little hack to parse iptc headers.
3000 my($caption,$photogr,$headln,$credit);
3002 my $str=$self->{IPTCRAW};
3006 @ar=split(/8BIM/,$str);
3011 @sar=split(/\034\002/);
3012 foreach $item (@sar) {
3013 if ($item =~ m/^x/) {
3014 $caption=&clean($item);
3017 if ($item =~ m/^P/) {
3018 $photogr=&clean($item);
3021 if ($item =~ m/^i/) {
3022 $headln=&clean($item);
3025 if ($item =~ m/^n/) {
3026 $credit=&clean($item);
3032 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
3039 or die "Only C language supported";
3041 require Imager::ExtUtils;
3042 return Imager::ExtUtils->inline_config;
3047 # Below is the stub of documentation for your module. You better edit it!
3051 Imager - Perl extension for Generating 24 bit Images
3061 die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
3066 my $img = Imager->new();
3067 # see Imager::Files for information on the read() method
3068 $img->read(file=>$file) or die $img->errstr();
3070 $file =~ s/\.[^.]*$//;
3072 # Create smaller version
3073 # documented in Imager::Transformations
3074 my $thumb = $img->scale(scalefactor=>.3);
3076 # Autostretch individual channels
3077 $thumb->filter(type=>'autolevels');
3079 # try to save in one of these formats
3082 for $format ( qw( png gif jpg tiff ppm ) ) {
3083 # Check if given format is supported
3084 if ($Imager::formats{$format}) {
3085 $file.="_low.$format";
3086 print "Storing image as: $file\n";
3087 # documented in Imager::Files
3088 $thumb->write(file=>$file) or
3096 Imager is a module for creating and altering images. It can read and
3097 write various image formats, draw primitive shapes like lines,and
3098 polygons, blend multiple images together in various ways, scale, crop,
3099 render text and more.
3101 =head2 Overview of documentation
3107 Imager - This document - Synopsis Example, Table of Contents and
3112 L<Imager::Tutorial> - a brief introduction to Imager.
3116 L<Imager::Cookbook> - how to do various things with Imager.
3120 L<Imager::ImageTypes> - Basics of constructing image objects with
3121 C<new()>: Direct type/virtual images, RGB(A)/paletted images,
3122 8/16/double bits/channel, color maps, channel masks, image tags, color
3123 quantization. Also discusses basic image information methods.
3127 L<Imager::Files> - IO interaction, reading/writing images, format
3132 L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
3137 L<Imager::Color> - Color specification.
3141 L<Imager::Fill> - Fill pattern specification.
3145 L<Imager::Font> - General font rendering, bounding boxes and font
3150 L<Imager::Transformations> - Copying, scaling, cropping, flipping,
3151 blending, pasting, convert and map.
3155 L<Imager::Engines> - Programmable transformations through
3156 C<transform()>, C<transform2()> and C<matrix_transform()>.
3160 L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
3165 L<Imager::Expr> - Expressions for evaluation engine used by
3170 L<Imager::Matrix2d> - Helper class for affine transformations.
3174 L<Imager::Fountain> - Helper for making gradient profiles.
3178 L<Imager::API> - using Imager's C API
3182 L<Imager::APIRef> - API function reference
3186 L<Imager::Inline> - using Imager's C API from Inline::C
3190 L<Imager::ExtUtils> - tools to get access to Imager's C API.
3194 =head2 Basic Overview
3196 An Image object is created with C<$img = Imager-E<gt>new()>.
3199 $img=Imager->new(); # create empty image
3200 $img->read(file=>'lena.png',type=>'png') or # read image from file
3201 die $img->errstr(); # give an explanation
3202 # if something failed
3204 or if you want to create an empty image:
3206 $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
3208 This example creates a completely black image of width 400 and height
3211 When an operation fails which can be directly associated with an image
3212 the error message is stored can be retrieved with
3213 C<$img-E<gt>errstr()>.
3215 In cases where no image object is associated with an operation
3216 C<$Imager::ERRSTR> is used to report errors not directly associated
3217 with an image object. You can also call C<Imager->errstr> to get this
3220 The C<Imager-E<gt>new> method is described in detail in
3221 L<Imager::ImageTypes>.
3225 Where to find information on methods for Imager class objects.
3227 addcolors() - L<Imager::ImageTypes/addcolors>
3229 addtag() - L<Imager::ImageTypes/addtag> - add image tags
3231 arc() - L<Imager::Draw/arc>
3233 align_string() - L<Imager::Draw/align_string>
3235 bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
3238 box() - L<Imager::Draw/box>
3240 circle() - L<Imager::Draw/circle>
3242 colorcount() - L<Imager::Draw/colorcount>
3244 convert() - L<Imager::Transformations/"Color transformations"> -
3245 transform the color space
3247 copy() - L<Imager::Transformations/copy>
3249 crop() - L<Imager::Transformations/crop> - extract part of an image
3251 deltag() - L<Imager::ImageTypes/deltag> - delete image tags
3253 difference() - L<Imager::Filters/"Image Difference">
3255 errstr() - L<"Basic Overview">
3257 filter() - L<Imager::Filters>
3259 findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
3262 flip() - L<Imager::Transformations/flip>
3264 flood_fill() - L<Imager::Draw/flood_fill>
3266 getchannels() - L<Imager::ImageTypes/getchannels>
3268 getcolorcount() - L<Imager::ImageTypes/getcolorcount>
3270 getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
3271 palette, if it has one
3273 get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3275 getheight() - L<Imager::ImageTypes/getwidth>
3277 getpixel() - L<Imager::Draw/getpixel>
3279 getsamples() - L<Imager::Draw/getsamples>
3281 getscanline() - L<Imager::Draw/getscanline>
3283 getwidth() - L<Imager::ImageTypes/getwidth>
3285 img_set() - L<Imager::ImageTypes/img_set>
3287 line() - L<Imager::Draw/line>
3289 map() - L<Imager::Transformations/"Color Mappings"> - remap color
3292 masked() - L<Imager::ImageTypes/masked> - make a masked image
3294 matrix_transform() - L<Imager::Engines/"Matrix Transformations">
3296 maxcolors() - L<Imager::ImageTypes/maxcolors>
3298 new() - L<Imager::ImageTypes/new>
3300 open() - L<Imager::Files> - an alias for read()
3302 paste() - L<Imager::Transformations/paste> - draw an image onto an image
3304 polygon() - L<Imager::Draw/polygon>
3306 polyline() - L<Imager::Draw/polyline>
3308 read() - L<Imager::Files> - read a single image from an image file
3310 read_multi() - L<Imager::Files> - read multiple images from an image
3313 rotate() - L<Imager::Transformations/rotate>
3315 rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
3316 image and use the alpha channel
3318 scale() - L<Imager::Transformations/scale>
3320 setscanline() - L<Imager::Draw/setscanline>
3322 scaleX() - L<Imager::Transformations/scaleX>
3324 scaleY() - L<Imager::Transformations/scaleY>
3326 setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
3329 setpixel() - L<Imager::Draw/setpixel>
3331 set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
3333 string() - L<Imager::Draw/string> - draw text on an image
3335 tags() - L<Imager::ImageTypes/tags> - fetch image tags
3337 to_paletted() - L<Imager::ImageTypes/to_paletted>
3339 to_rgb8() - L<Imager::ImageTypes/to_rgb8>
3341 transform() - L<Imager::Engines/"transform">
3343 transform2() - L<Imager::Engines/"transform2">
3345 type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
3347 virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
3350 write() - L<Imager::Files> - write an image to a file
3352 write_multi() - L<Imager::Files> - write multiple image to an image
3355 =head1 CONCEPT INDEX
3357 animated GIF - L<Imager::File/"Writing an animated GIF">
3359 aspect ratio - L<Imager::ImageTypes/i_xres>,
3360 L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
3362 blend - alpha blending one image onto another
3363 L<Imager::Transformations/rubthrough>
3365 blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
3367 boxes, drawing - L<Imager::Draw/box>
3369 changes between image - L<Imager::Filter/"Image Difference">
3371 color - L<Imager::Color>
3373 color names - L<Imager::Color>, L<Imager::Color::Table>
3375 combine modes - L<Imager::Fill/combine>
3377 compare images - L<Imager::Filter/"Image Difference">
3379 contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
3381 convolution - L<Imager::Filter/conv>
3383 cropping - L<Imager::Transformations/crop>
3385 C<diff> images - L<Imager::Filter/"Image Difference">
3387 dpi - L<Imager::ImageTypes/i_xres>
3389 drawing boxes - L<Imager::Draw/box>
3391 drawing lines - L<Imager::Draw/line>
3393 drawing text - L<Imager::Font/string>, L<Imager::Font/align>
3395 error message - L<"Basic Overview">
3397 files, font - L<Imager::Font>
3399 files, image - L<Imager::Files>
3401 filling, types of fill - L<Imager::Fill>
3403 filling, boxes - L<Imager::Draw/box>
3405 filling, flood fill - L<Imager::Draw/flood_fill>
3407 flood fill - L<Imager::Draw/flood_fill>
3409 fonts - L<Imager::Font>
3411 fonts, drawing with - L<Imager::Font/string>, L<Imager::Font/align>,
3412 L<Imager::Font::Wrap>
3414 fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3416 fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
3418 fountain fill - L<Imager::Fill/"Fountain fills">,
3419 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3420 L<Imager::Filters/gradgen>
3422 GIF files - L<Imager::Files/"GIF">
3424 GIF files, animated - L<Imager::File/"Writing an animated GIF">
3426 gradient fill - L<Imager::Fill/"Fountain fills">,
3427 L<Imager::Filters/fountain>, L<Imager::Fountain>,
3428 L<Imager::Filters/gradgen>
3430 guassian blur - L<Imager::Filter/guassian>
3432 hatch fills - L<Imager::Fill/"Hatched fills">
3434 invert image - L<Imager::Filter/hardinvert>
3436 JPEG - L<Imager::Files/"JPEG">
3438 limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
3440 lines, drawing - L<Imager::Draw/line>
3442 matrix - L<Imager::Matrix2d>,
3443 L<Imager::Transformations/"Matrix Transformations">,
3444 L<Imager::Font/transform>
3446 metadata, image - L<Imager::ImageTypes/"Tags">
3448 mosaic - L<Imager::Filter/mosaic>
3450 noise, filter - L<Imager::Filter/noise>
3452 noise, rendered - L<Imager::Filter/turbnoise>,
3453 L<Imager::Filter/radnoise>
3455 paste - L<Imager::Transformations/paste>,
3456 L<Imager::Transformations/rubthrough>
3458 pseudo-color image - L<Imager::ImageTypes/to_paletted>,
3459 L<Imager::ImageTypes/new>
3461 posterize - L<Imager::Filter/postlevels>
3463 png files - L<Imager::Files>, L<Imager::Files/"PNG">
3465 pnm - L<Imager::Files/"PNM (Portable aNy Map)">
3467 rectangles, drawing - L<Imager::Draw/box>
3469 resizing an image - L<Imager::Transformations/scale>,
3470 L<Imager::Transformations/crop>
3472 saving an image - L<Imager::Files>
3474 scaling - L<Imager::Transformations/scale>
3476 sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
3478 size, image - L<Imager::ImageTypes/getwidth>,
3479 L<Imager::ImageTypes/getheight>
3481 size, text - L<Imager::Font/bounding_box>
3483 tags, image metadata - L<Imager::ImageTypes/"Tags">
3485 text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
3486 L<Imager::Font::Wrap>
3488 text, wrapping text in an area - L<Imager::Font::Wrap>
3490 text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
3492 tiles, color - L<Imager::Filter/mosaic>
3494 unsharp mask - L<Imager::Filter/unsharpmask>
3496 watermark - L<Imager::Filter/watermark>
3498 writing an image to a file - L<Imager::Files>
3502 You can ask for help, report bugs or express your undying love for
3503 Imager on the Imager-devel mailing list.
3505 To subscribe send a message with C<subscribe> in the body to:
3507 imager-devel+request@molar.is
3513 L<http://www.molar.is/en/lists/imager-devel/>
3517 where you can also find the mailing list archive.
3519 If you're into IRC, you can typically find the developers in #Imager
3520 on irc.perl.org. As with any IRC channel, the participants could be
3521 occupied or asleep, so please be patient.
3523 You can report bugs by pointing your browser at:
3527 L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
3531 Please remember to include the versions of Imager, perl, supporting
3532 libraries, and any relevant code. If you have specific images that
3533 cause the problems, please include those too.
3537 Bugs are listed individually for relevant pod pages.
3541 Arnar M. Hrafnkelsson and Tony Cook (tony@imager.perl.org) among
3542 others. See the README for a complete list.
3546 L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
3547 L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
3548 L<Imager::Font>(3), L<Imager::Transformations>(3),
3549 L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
3550 L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
3552 L<http://imager.perl.org/>
3554 L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
3556 Other perl imaging modules include:
3558 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).