X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/6a3cbaef62aadb0bd0aa0174e99cc129d9f032f6..86c50c46b13eb07f84a907b798e62b0f2fc94600:/Imager.pm diff --git a/Imager.pm b/Imager.pm index ec5f08e9..3b689b4a 100644 --- a/Imager.pm +++ b/Imager.pm @@ -1,7 +1,7 @@ package Imager; use strict; -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR $fontstate %OPCODES $I2P $FORMATGUESS $warn_obsolete); +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete); use IO::File; use Imager::Color; @@ -19,7 +19,6 @@ use Imager::Font; unload_plugin i_list_formats - i_has_format i_color_new i_color_set @@ -61,37 +60,11 @@ use Imager::Font; i_img_diff - i_init_fonts - i_t1_new - i_t1_destroy - i_t1_set_aa - i_t1_cp - i_t1_text - i_t1_bbox - i_tt_set_aa i_tt_cp i_tt_text i_tt_bbox - i_readjpeg_wiol - i_writejpeg_wiol - - i_readtiff_wiol - i_writetiff_wiol - i_writetiff_wiol_faxable - - i_readpng_wiol - i_writepng_wiol - - i_readgif - i_readgif_wiol - i_readgif_callback - i_writegif - i_writegifmc - i_writegif_gen - i_writegif_callback - i_readpnm_wiol i_writeppm_wiol @@ -173,7 +146,7 @@ my %defaults; BEGIN { require Exporter; @ISA = qw(Exporter); - $VERSION = '0.70'; + $VERSION = '0.82'; eval { require XSLoader; XSLoader::load(Imager => $VERSION); @@ -185,14 +158,22 @@ BEGIN { } } -BEGIN { - Imager::Font::__init(); - for(i_list_formats()) { $formats{$_}++; } +my %formats_low; +my %format_classes = + ( + png => "Imager::File::PNG", + gif => "Imager::File::GIF", + tiff => "Imager::File::TIFF", + jpeg => "Imager::File::JPEG", + w32 => "Imager::Font::W32", + ft2 => "Imager::Font::FT2", + t1 => "Imager::Font::T1", + ); - if (!$formats{'t1'} and !$formats{'tt'} - && !$formats{'ft2'} && !$formats{'w32'}) { - $fontstate='no font support'; - } +tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes; + +BEGIN { + for(i_list_formats()) { $formats_low{$_}++; } %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]); @@ -225,6 +206,13 @@ BEGIN { callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); } }; + $filters{hardinvertall} = + { + callseq => ['image'], + defaults => { }, + callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); } + }; + $filters{autolevels} ={ callseq => ['image','lsat','usat','skew'], defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 }, @@ -323,12 +311,18 @@ BEGIN { cd => 1.0, cs => 40, n => 1.3, - Ia => Imager::Color->new(rgb=>[0,0,0]), - Il => Imager::Color->new(rgb=>[255,255,255]), - Is => Imager::Color->new(rgb=>[255,255,255]), + Ia => [0,0,0], + Il => [255,255,255], + Is => [255,255,255], }, callsub => sub { my %hsh = @_; + for my $cname (qw/Ia Il Is/) { + my $old = $hsh{$cname}; + my $new_color = _color($old) + or die $Imager::ERRSTR, "\n"; + $hsh{$cname} = $new_color; + } i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel}, $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz}, $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il}, @@ -394,8 +388,8 @@ BEGIN { super_sample => 0, ssample_param => 4, segments=>[ [ 0, 0.5, 1, - Imager::Color->new(0,0,0), - Imager::Color->new(255, 255, 255), + [0,0,0], + [255, 255, 255], 0, 0, ], ], @@ -472,13 +466,10 @@ sub init { $warn_obsolete = $parms{'warn_obsolete'}; } -# if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; } -# if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) { -# i_init_fonts(); -# $fontstate='ok'; -# } if (exists $parms{'t1log'}) { - i_init_fonts($parms{'t1log'}); + if ($formats{t1}) { + Imager::Font::T1::i_init_t1($parms{'t1log'}); + } } } @@ -638,7 +629,8 @@ sub new { defined $hsh{fh} || defined $hsh{fd} || defined $hsh{callback} || - defined $hsh{readcb}) { + defined $hsh{readcb} || + defined $hsh{data}) { # allow $img = Imager->new(file => $filename) my %extras; @@ -910,11 +902,16 @@ sub masked { $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left}, $opts{top}, $opts{right} - $opts{left}, $opts{bottom} - $opts{top}); + unless ($result->{IMG}) { + $self->_set_error(Imager->_error_as_msg); + return; + } + # keep references to the mask and base images so they don't # disappear on us $result->{DEPENDS} = [ $self->{IMG}, $mask ]; - $result; + return $result; } # convert an RGB image into a paletted image @@ -1353,36 +1350,15 @@ sub read { return $readers{$input{type}}{single}->($self, $IO, %input); } - unless ($formats{$input{'type'}}) { + unless ($formats_low{$input{'type'}}) { my $read_types = join ', ', sort Imager->read_types(); $self->_set_error("format '$input{'type'}' not supported - formats $read_types available for reading"); return; } - # Setup data source - if ( $input{'type'} eq 'jpeg' ) { - ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO ); - if ( !defined($self->{IMG}) ) { - $self->{ERRSTR}=$self->_error_as_msg(); return undef; - } - $self->{DEBUG} && print "loading a jpeg file\n"; - return $self; - } - my $allow_incomplete = $input{allow_incomplete}; defined $allow_incomplete or $allow_incomplete = 0; - if ( $input{'type'} eq 'tiff' ) { - my $page = $input{'page'}; - defined $page or $page = 0; - $self->{IMG}=i_readtiff_wiol( $IO, $allow_incomplete, $page ); - if ( !defined($self->{IMG}) ) { - $self->{ERRSTR}=$self->_error_as_msg(); return undef; - } - $self->{DEBUG} && print "loading a tiff file\n"; - return $self; - } - if ( $input{'type'} eq 'pnm' ) { $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete ); if ( !defined($self->{IMG}) ) { @@ -1393,15 +1369,6 @@ sub read { return $self; } - if ( $input{'type'} eq 'png' ) { - $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed - if ( !defined($self->{IMG}) ) { - $self->{ERRSTR} = $self->_error_as_msg(); - return undef; - } - $self->{DEBUG} && print "loading a png file\n"; - } - if ( $input{'type'} eq 'bmp' ) { $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete ); if ( !defined($self->{IMG}) ) { @@ -1558,7 +1525,7 @@ sub write_types { sub _reader_autoload { my $type = shift; - return if $formats{$type} || $readers{$type}; + return if $formats_low{$type} || $readers{$type}; return unless $type =~ /^\w+$/; @@ -1586,7 +1553,7 @@ sub _reader_autoload { sub _writer_autoload { my $type = shift; - return if $formats{$type} || $readers{$type}; + return if $formats_low{$type} || $readers{$type}; return unless $type =~ /^\w+$/; @@ -1745,7 +1712,7 @@ sub write { or return undef; } else { - if (!$formats{$input{'type'}}) { + if (!$formats_low{$input{'type'}}) { my $write_types = join ', ', sort Imager->write_types(); $self->_set_error("format '$input{'type'}' not supported - formats $write_types available for writing"); return undef; @@ -1754,24 +1721,7 @@ sub write { ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'}) or return undef; - if ($input{'type'} eq 'tiff') { - $self->_set_opts(\%input, "tiff_", $self) - or return undef; - $self->_set_opts(\%input, "exif_", $self) - or return undef; - - if (defined $input{class} && $input{class} eq 'fax') { - if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) { - $self->{ERRSTR} = $self->_error_as_msg(); - return undef; - } - } else { - if (!i_writetiff_wiol($self->{IMG}, $IO)) { - $self->{ERRSTR} = $self->_error_as_msg(); - return undef; - } - } - } elsif ( $input{'type'} eq 'pnm' ) { + if ( $input{'type'} eq 'pnm' ) { $self->_set_opts(\%input, "pnm_", $self) or return undef; if ( ! i_writeppm_wiol($self->{IMG},$IO) ) { @@ -1787,14 +1737,6 @@ sub write { return undef; } $self->{DEBUG} && print "writing a raw file\n"; - } elsif ( $input{'type'} eq 'png' ) { - $self->_set_opts(\%input, "png_", $self) - or return undef; - if ( !i_writepng_wiol($self->{IMG}, $IO) ) { - $self->{ERRSTR}='unable to write png image'; - return undef; - } - $self->{DEBUG} && print "writing a png file\n"; } elsif ( $input{'type'} eq 'jpeg' ) { $self->_set_opts(\%input, "jpeg_", $self) or return undef; @@ -1895,37 +1837,7 @@ sub write_multi { ($IO, $file) = $class->_get_writer_io($opts, $type) or return undef; - if ($type eq 'gif') { - $class->_set_opts($opts, "gif_", @images) - or return; - my $gif_delays = $opts->{gif_delays}; - local $opts->{gif_delays} = $gif_delays; - if ($opts->{gif_delays} && !ref $opts->{gif_delays}) { - # assume the caller wants the same delay for each frame - $opts->{gif_delays} = [ ($gif_delays) x @images ]; - } - unless (i_writegif_wiol($IO, $opts, @work)) { - $class->_set_error($class->_error_as_msg()); - return undef; - } - } - elsif ($type eq 'tiff') { - $class->_set_opts($opts, "tiff_", @images) - or return; - $class->_set_opts($opts, "exif_", @images) - or return; - my $res; - $opts->{fax_fine} = 1 unless exists $opts->{fax_fine}; - if ($opts->{'class'} && $opts->{'class'} eq 'fax') { - $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work); - } - else { - $res = i_writetiff_multi_wiol($IO, @work); - } - unless ($res) { - $class->_set_error($class->_error_as_msg()); - return undef; - } + if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere } else { if (@images == 1) { @@ -1979,30 +1891,15 @@ sub read_multi { return $readers{$type}{multiple}->($IO, %opts); } - if ($type eq 'gif') { - my @imgs; - @imgs = i_readgif_multi_wiol($IO); - if (@imgs) { - return map { - bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager' - } @imgs; - } - else { - $ERRSTR = _error_as_msg(); - return; - } + unless ($formats{$type}) { + my $read_types = join ', ', sort Imager->read_types(); + Imager->_set_error("format '$type' not supported - formats $read_types available for reading"); + return; } - elsif ($type eq 'tiff') { - my @imgs = i_readtiff_multi_wiol($IO, -1); - if (@imgs) { - return map { - bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager' - } @imgs; - } - else { - $ERRSTR = _error_as_msg(); - return; - } + + my @imgs; + if ($type eq 'pnm') { + @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0); } else { my $img = Imager->new; @@ -2010,9 +1907,16 @@ sub read_multi { return ( $img ); } Imager->_set_error($img->errstr); + return; } + if (!@imgs) { + $ERRSTR = _error_as_msg(); return; + } + return map { + bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager' + } @imgs; } # Destroy an Imager object @@ -2738,25 +2642,46 @@ sub i_color_set { # Draws a box between the specified corner points. sub box { my $self=shift; - unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; } - my $dflcl=i_color_new(255,255,255,255); - my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_); + my $raw = $self->{IMG}; + + unless ($raw) { + $self->{ERRSTR}='empty input image'; + return undef; + } + + my %opts = @_; + my ($xmin, $ymin, $xmax, $ymax); if (exists $opts{'box'}) { - $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]); - $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]); - $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]); - $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]); + $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]); + $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]); + $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]); + $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]); + } + else { + defined($xmin = $opts{xmin}) or $xmin = 0; + defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1; + defined($ymin = $opts{ymin}) or $ymin = 0; + defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1; } if ($opts{filled}) { - my $color = _color($opts{'color'}); - unless ($color) { - $self->{ERRSTR} = $Imager::ERRSTR; - return; + my $color = $opts{'color'}; + + if (defined $color) { + unless (_is_color_object($color)) { + $color = _color($color); + unless ($color) { + $self->{ERRSTR} = $Imager::ERRSTR; + return; + } + } + } + else { + $color = i_color_new(255,255,255,255); } - i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax}, - $opts{ymax}, $color); + + i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color); } elsif ($opts{fill}) { unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) { @@ -2767,30 +2692,47 @@ sub box { return undef; } } - i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax}, - $opts{ymax},$opts{fill}{fill}); + i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill}); } else { - my $color = _color($opts{'color'}); + my $color = $opts{'color'}; + if (defined $color) { + unless (_is_color_object($color)) { + $color = _color($color); + unless ($color) { + $self->{ERRSTR} = $Imager::ERRSTR; + return; + } + } + } + else { + $color = i_color_new(255, 255, 255, 255); + } unless ($color) { $self->{ERRSTR} = $Imager::ERRSTR; return; } - i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax}, - $color); + i_box($raw, $xmin, $ymin, $xmax, $ymax, $color); } + return $self; } sub arc { my $self=shift; unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; } - my $dflcl=i_color_new(255,255,255,255); - my %opts=(color=>$dflcl, - 'r'=>_min($self->getwidth(),$self->getheight())/3, - 'x'=>$self->getwidth()/2, - 'y'=>$self->getheight()/2, - 'd1'=>0, 'd2'=>361, @_); + my $dflcl= [ 255, 255, 255, 255]; + my $good = 1; + my %opts= + ( + color=>$dflcl, + 'r'=>_min($self->getwidth(),$self->getheight())/3, + 'x'=>$self->getwidth()/2, + 'y'=>$self->getheight()/2, + 'd1'=>0, 'd2'=>361, + filled => 1, + @_, + ); if ($opts{aa}) { if ($opts{fill}) { unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) { @@ -2804,7 +2746,7 @@ sub arc { i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'}, $opts{'d2'}, $opts{fill}{fill}); } - else { + elsif ($opts{filled}) { my $color = _color($opts{'color'}); unless ($color) { $self->{ERRSTR} = $Imager::ERRSTR; @@ -2819,6 +2761,15 @@ sub arc { $opts{'d1'}, $opts{'d2'}, $color); } } + else { + my $color = _color($opts{'color'}); + if ($opts{d2} - $opts{d1} >= 360) { + $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color); + } + else { + $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color); + } + } } else { if ($opts{fill}) { @@ -2837,12 +2788,26 @@ sub arc { my $color = _color($opts{'color'}); unless ($color) { $self->{ERRSTR} = $Imager::ERRSTR; - return; + return; + } + if ($opts{filled}) { + i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'}, + $opts{'d1'}, $opts{'d2'}, $color); + } + else { + if ($opts{d1} == 0 && $opts{d2} == 361) { + $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color); + } + else { + $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color); + } } - i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'}, - $opts{'d1'}, $opts{'d2'}, $color); } } + unless ($good) { + $self->_set_error($self->_error_as_msg); + return; + } return $self; } @@ -3071,9 +3036,18 @@ sub flood_fill { } sub setpixel { - my $self = shift; + my ($self, %opts) = @_; - my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_); + my $color = $opts{color}; + unless (defined $color) { + $color = $self->{fg}; + defined $color or $color = NC(255, 255, 255); + } + + unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) { + $color = _color($color) + or return undef; + } unless (exists $opts{'x'} && exists $opts{'y'}) { $self->{ERRSTR} = 'missing x and y parameters'; @@ -3082,8 +3056,6 @@ sub setpixel { my $x = $opts{'x'}; my $y = $opts{'y'}; - my $color = _color($opts{color}) - or return undef; if (ref $x && ref $y) { unless (@$x == @$y) { $self->{ERRSTR} = 'length of x and y mismatch'; @@ -3488,6 +3460,46 @@ sub convert { return $new; } +# combine channels from multiple input images, a class method +sub combine { + my ($class, %opts) = @_; + + my $src = delete $opts{src}; + unless ($src) { + $class->_set_error("src parameter missing"); + return; + } + my @imgs; + my $index = 0; + for my $img (@$src) { + unless (eval { $img->isa("Imager") }) { + $class->_set_error("src must contain image objects"); + return; + } + unless ($img->{IMG}) { + $class->_set_error("empty input image"); + return; + } + push @imgs, $img->{IMG}; + } + my $result; + if (my $channels = delete $opts{channels}) { + $result = i_combine(\@imgs, $channels); + } + else { + $result = i_combine(\@imgs); + } + unless ($result) { + $class->_set_error($class->_error_as_msg); + return; + } + + my $img = $class->new; + $img->{IMG} = $result; + + return $img; +} + # general function to map an image through lookup tables @@ -3546,16 +3558,26 @@ sub border { sub getwidth { my $self = shift; - if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; } - return (i_img_info($self->{IMG}))[0]; + + if (my $raw = $self->{IMG}) { + return i_img_get_width($raw); + } + else { + $self->{ERRSTR} = 'image is empty'; return undef; + } } # Get the height of an image sub getheight { my $self = shift; - if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; } - return (i_img_info($self->{IMG}))[1]; + + if (my $raw = $self->{IMG}) { + return i_img_get_height($raw); + } + else { + $self->{ERRSTR} = 'image is empty'; return undef; + } } # Get number of channels in an image @@ -3699,7 +3721,8 @@ sub align_string { } my %input=('x'=>0, 'y'=>0, @_); - $input{string}||=$input{text}; + defined $input{string} + or $input{string} = $input{text}; unless(exists $input{string}) { $self->_set_error("missing required parameter 'string'"); @@ -3749,7 +3772,10 @@ sub get_file_limits { sub newcolor { Imager::Color->new(@_); } sub newfont { Imager::Font->new(@_); } -sub NCF { Imager::Color::Float->new(@_) } +sub NCF { + require Imager::Color::Float; + return Imager::Color::Float->new(@_); +} *NC=*newcolour=*newcolor; *NF=*newfont; @@ -3878,6 +3904,128 @@ sub Inline { return Imager::ExtUtils->inline_config; } +# threads shouldn't try to close raw Imager objects +sub Imager::ImgRaw::CLONE_SKIP { 1 } + +sub preload { + # this serves two purposes: + # - a class method to load the file support modules included with Image + # (or were included, once the library dependent modules are split out) + # - something for Module::ScanDeps to analyze + # https://rt.cpan.org/Ticket/Display.html?id=6566 + local $@; + eval { require Imager::File::GIF }; + eval { require Imager::File::JPEG }; + eval { require Imager::File::PNG }; + eval { require Imager::File::SGI }; + eval { require Imager::File::TIFF }; + eval { require Imager::File::ICO }; + eval { require Imager::Font::W32 }; + eval { require Imager::Font::FT2 }; + eval { require Imager::Font::T1 }; +} + +# backward compatibility for %formats +package Imager::FORMATS; +use strict; +use constant IX_FORMATS => 0; +use constant IX_LIST => 1; +use constant IX_INDEX => 2; +use constant IX_CLASSES => 3; + +sub TIEHASH { + my ($class, $formats, $classes) = @_; + + return bless [ $formats, [ ], 0, $classes ], $class; +} + +sub _check { + my ($self, $key) = @_; + + (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g; + my $value; + if (eval { require $file; 1 }) { + $value = 1; + } + else { + $value = undef; + } + $self->[IX_FORMATS]{$key} = $value; + + return $value; +} + +sub FETCH { + my ($self, $key) = @_; + + exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key}; + + $self->[IX_CLASSES]{$key} or return undef; + + return $self->_check($key); +} + +sub STORE { + die "%Imager::formats is not user monifiable"; +} + +sub DELETE { + die "%Imager::formats is not user monifiable"; +} + +sub CLEAR { + die "%Imager::formats is not user monifiable"; +} + +sub EXISTS { + my ($self, $key) = @_; + + if (exists $self->[IX_FORMATS]{$key}) { + my $value = $self->[IX_FORMATS]{$key} + or return; + return 1; + } + + $self->_check($key) or return 1==0; + + return 1==1; +} + +sub FIRSTKEY { + my ($self) = @_; + + unless (@{$self->[IX_LIST]}) { + # full populate it + @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_}, + keys %{$self->[IX_FORMATS]}; + + for my $key (keys %{$self->[IX_CLASSES]}) { + $self->[IX_FORMATS]{$key} and next; + $self->_check($key) + and push @{$self->[IX_LIST]}, $key; + } + } + + @{$self->[IX_LIST]} or return; + $self->[IX_INDEX] = 1; + return $self->[IX_LIST][0]; +} + +sub NEXTKEY { + my ($self) = @_; + + $self->[IX_INDEX] < @{$self->[IX_LIST]} + or return; + + return $self->[IX_LIST][$self->[IX_INDEX]++]; +} + +sub SCALAR { + my ($self) = @_; + + return scalar @{$self->[IX_LIST]}; +} + 1; __END__ # Below is the stub of documentation for your module. You better edit it! @@ -3900,7 +4048,7 @@ Imager - Perl extension for Generating 24 bit Images my $format; # see Imager::Files for information on the read() method - my $im = Imager->new(file=>$file) + my $img = Imager->new(file=>$file) or die Imager->errstr(); $file =~ s/\.[^.]*$//; @@ -3994,7 +4142,7 @@ C, C and C. =item * L - Filters, sharpen, blur, noise, convolve etc. and -filter plugins. +filter plug-ins. =item * @@ -4047,11 +4195,11 @@ This example creates a completely black image of width 400 and height =head1 ERROR HANDLING In general a method will return false when it fails, if it does use -the errstr() method to find out why: +the C method to find out why: =over -=item errstr +=item errstr() Returns the last error message in that context. @@ -4079,202 +4227,210 @@ L. Where to find information on methods for Imager class objects. -addcolors() - L - add colors to a +addcolors() - L - add colors to a paletted image -addtag() - L - add image tags +addtag() - L - add image tags -align_string() - L - draw text aligned on a +align_string() - L - draw text aligned on a point -arc() - L - draw a filled arc +arc() - L - draw a filled arc -bits() - L - number of bits per sample for the +bits() - L - number of bits per sample for the image -box() - L - draw a filled or outline box. +box() - L - draw a filled or outline box. + +circle() - L - draw a filled circle -circle() - L - draw a filled circle +colorcount() - L - the number of +colors in an image's palette (paletted images only) -colorcount() - L - the number of colors in an -image's palette (paletted images only) +combine() - L - combine channels +from one or more images. -combines() - L - return a list of the different -combine type keywords +combines() - L - return a list of the +different combine type keywords -compose() - L - compose one image +compose() - L - compose one image over another. convert() - L - transform the color space -copy() - L - make a duplicate of an +copy() - L - make a duplicate of an image -crop() - L - extract part of an image +crop() - L - extract part of an image -def_guess_type() - L - default function -used to guess the output file format based on the output filename +def_guess_type() - L - default function +used to guess the output file format based on the output file name -deltag() - L - delete image tags +deltag() - L - delete image tags difference() - L - produce a difference images from two input images. -errstr() - L<"Basic Overview"> - the error from the last failed +errstr() - L - the error from the last failed operation. filter() - L - image filtering -findcolor() - L - search the image +findcolor() - L - search the image palette, if it has one -flip() - L - flip an image, vertically, +flip() - L - flip an image, vertically, horizontally -flood_fill() - L - fill an enclosed or same +flood_fill() - L - fill an enclosed or same color area -getchannels() - L - the number of +getchannels() - L - the number of samples per pixel for an image -getcolorcount() - L - the number of +getcolorcount() - L - the number of different colors used by an image (works for direct color images) -getcolors() - L - get colors from the image +getcolors() - L - get colors from the image palette, if it has one -getcolorusage() - L +getcolorusage() - L -getcolorusagehash() - L +getcolorusagehash() - L get_file_limits() - L -getheight() - L - height of the image in +getheight() - L - height of the image in pixels -getmask() - L - write mask for the image +getmask() - L - write mask for the image -getpixel() - L - retrieve one or more pixel +getpixel() - L - retrieve one or more pixel colors -getsamples() - L - retrieve samples from a -row or subrow of pixels. +getsamples() - L - retrieve samples from a +row or partial row of pixels. -getscanline() - L - retrieve colors for a -row or subrow of pixels. +getscanline() - L - retrieve colors for a +row or partial row of pixels. -getwidth() - L - width of the image in +getwidth() - L - width of the image in pixels. -img_set() - L - re-use an Imager object +img_set() - L - re-use an Imager object for a new image. -init() - L +init() - L -is_bilevel() - L - returns whether -image write functions should write the image in their bi-level (blank -and white, no grey levels) format +is_bilevel() - L - returns whether +image write functions should write the image in their bilevel (blank +and white, no gray levels) format -line() - L - draw an interval +line() - L - draw an interval -load_plugin() - L +load_plugin() - L map() - L - remap color channel values -masked() - L - make a masked image +masked() - L - make a masked image -matrix_transform() - L +matrix_transform() - L -maxcolors() - L +maxcolors() - L -NC() - L +NC() - L -NCF() - L +NCF() - L -new() - L +new() - L -newcolor() - L +newcolor() - L -newcolour() - L +newcolour() - L -newfont() - L +newfont() - L -NF() - L +NF() - L open() - L - an alias for read() -parseiptc() - L - parse IPTC data from a JPEG +=for stopwords IPTC + +parseiptc() - L - parse IPTC data from a JPEG image -paste() - L - draw an image onto an image +paste() - L - draw an image onto an +image + +polygon() - L -polygon() - L +polyline() - L -polyline() - L +preload() - L read() - L - read a single image from an image file read_multi() - L - read multiple images from an image file -read_types() - L - list image types Imager +read_types() - L - list image types Imager can read. -register_filter() - L +register_filter() - L -register_reader() - L +register_reader() - L -register_writer() - L +register_writer() - L -rotate() - L +rotate() - L -rubthrough() - L - draw an image onto an -image and use the alpha channel +rubthrough() - L - draw an image +onto an image and use the alpha channel -scale() - L +scale() - L -scale_calculate() - L +scale_calculate() - L -scaleX() - L +scaleX() - L -scaleY() - L +scaleY() - L -setcolors() - L - set palette colors in -a paletted image +setcolors() - L - set palette colors +in a paletted image set_file_limits() - L -setmask() - L +setmask() - L -setpixel() - L +setpixel() - L -setsamples() - L +setsamples() - L -setscanline() - L +setscanline() - L -settag() - L +settag() - L -string() - L - draw text on an image +string() - L - draw text on an image -tags() - L - fetch image tags +tags() - L - fetch image tags -to_paletted() - L +to_paletted() - L -to_rgb16() - L +to_rgb16() - L -to_rgb8() - L +to_rgb8() - L -transform() - L +transform() - L -transform2() - L +transform2() - L -type() - L - type of image (direct vs paletted) +type() - L - type of image (direct vs paletted) -unload_plugin() - L +unload_plugin() - L -virtual() - L - whether the image has it's own +virtual() - L - whether the image has it's own data write() - L - write an image to a file @@ -4282,25 +4438,27 @@ write() - L - write an image to a file write_multi() - L - write multiple image to an image file. -write_types() - L - list image types Imager +write_types() - L - list image types Imager can write. =head1 CONCEPT INDEX animated GIF - L -aspect ratio - L, -L, L +aspect ratio - C, C, C in +L. blend - alpha blending one image onto another -L +L -blur - L, L +blur - L, L -boxes, drawing - L +boxes, drawing - L changes between image - L +channels, combine into one image - L + color - L color names - L, L @@ -4313,22 +4471,22 @@ contrast - L, L convolution - L -cropping - L +cropping - L CUR files - L C images - L -dpi - L, +dpi - C, C in L, L -drawing boxes - L +drawing boxes - L -drawing lines - L +drawing lines - L -drawing text - L, L +drawing text - L, L -error message - L<"ERROR HANDLING"> +error message - L files, font - L @@ -4336,18 +4494,18 @@ files, image - L filling, types of fill - L -filling, boxes - L +filling, boxes - L -filling, flood fill - L +filling, flood fill - L -flood fill - L +flood fill - L fonts - L -fonts, drawing with - L, -L, L +fonts, drawing with - L, +L, L -fonts, metrics - L, L +fonts, metrics - L, L fonts, multiple master - L @@ -4357,31 +4515,32 @@ L GIF files - L -GIF files, animated - L +GIF files, animated - L gradient fill - L, L, L, L -grayscale, convert image to - L +gray scale, convert image to - L -guassian blur - L +gaussian blur - L hatch fills - L ICO files - L -invert image - L +invert image - L, +L JPEG - L limiting image sizes - L -lines, drawing - L +lines, drawing - L matrix - L, -L, -L +L, +L metadata, image - L @@ -4392,55 +4551,71 @@ noise, filter - L noise, rendered - L, L -paste - L, -L +paste - L, +L + +pseudo-color image - L, +L -pseudo-color image - L, -L +=for stopwords posterize posterize - L -png files - L, L +PNG files - L, L -pnm - L +PNM - L -rectangles, drawing - L +rectangles, drawing - L -resizing an image - L, -L +resizing an image - L, +L RGB (SGI) files - L saving an image - L -scaling - L +scaling - L SGI files - L sharpen - L, L -size, image - L, -L +size, image - L, +L -size, text - L +size, text - L tags, image metadata - L -text, drawing - L, L, +text, drawing - L, L, L text, wrapping text in an area - L -text, measuring - L, L +text, measuring - L, L tiles, color - L +transparent images - L, +L + +=for stopwords unsharp + unsharp mask - L watermark - L writing an image to a file - L +=head1 THREADS + +Imager doesn't support perl threads. + +Imager has limited code to prevent double frees if you create images, +colors etc, and then create a thread, but has no code to prevent two +threads entering Imager's error handling code, and none is likely to +be added. + =head1 SUPPORT The best place to get help with Imager is the mailing list. @@ -4497,11 +4672,14 @@ at CPAN Ratings: http://cpanratings.perl.org/dist/Imager -This requires a Bitcard Account (http://www.bitcard.org). +=for stopwords Bitcard + +This requires a Bitcard account (http://www.bitcard.org). You can also send email to the maintainer below. -If you send me a bug report via email, it will be copied to RT. +If you send me a bug report via email, it will be copied to Request +Tracker. =head2 Patches @@ -4518,9 +4696,20 @@ Tony Cook is the current maintainer for Imager. Arnar M. Hrafnkelsson is the original author of Imager. -Many others have contributed to Imager, please see the README for a +Many others have contributed to Imager, please see the C for a complete list. +=head1 LICENSE + +Imager is licensed under the same terms as perl itself. + +=for stopwords +makeblendedfont Fontforge + +A test font, FT2/fontfiles/MMOne.pfb, contains a Postscript operator +definition copyrighted by Adobe. See F in the source for +license information. + =head1 SEE ALSO L(1), L(3), L(3),