unload_plugin
)]);
+# registered file readers
+my %readers;
+
+# modules we attempted to autoload
+my %attempted_to_load;
+
BEGIN {
require Exporter;
@ISA = qw(Exporter);
return undef;
}
+ _reader_autoload($input{type});
+
+ if ($readers{$input{type}} && $readers{$input{type}}{single}) {
+ return $readers{$input{type}}{single}->($self, $IO, %input);
+ }
+
unless ($formats{$input{'type'}}) {
$self->_set_error("format '$input{'type'}' not supported");
return;
return $self;
}
+sub register_reader {
+ my ($class, %opts) = @_;
+
+ defined $opts{type}
+ or die "register_reader called with no type parameter\n";
+
+ my $type = $opts{type};
+
+ defined $opts{single} || defined $opts{multiple}
+ or die "register_reader called with no single or multiple parameter\n";
+
+ $readers{$type} = { };
+ if ($opts{single}) {
+ $readers{$type}{single} = $opts{single};
+ }
+ if ($opts{multiple}) {
+ $readers{$type}{multiple} = $opts{multiple};
+ }
+
+ return 1;
+}
+
+# probes for an Imager::File::whatever module
+sub _reader_autoload {
+ my $type = shift;
+
+ return if $formats{$type} || $readers{$type};
+
+ return unless $type =~ /^\w+$/;
+
+ my $file = "Imager/File/\U$type\E.pm";
+
+ unless ($attempted_to_load{$file}) {
+ eval {
+ ++$attempted_to_load{$file};
+ require $file;
+ };
+ }
+}
+
sub _fix_gif_positions {
my ($opts, $opt, $msg, @imgs) = @_;
sub read_multi {
my ($class, %opts) = @_;
- if ($opts{file} && !exists $opts{'type'}) {
+ my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
+ or return;
+
+ my $type = $opts{'type'};
+ unless ($type) {
+ $type = i_test_format_probe($IO, -1);
+ }
+
+ if ($opts{file} && !$type) {
# guess the type
- my $type = $FORMATGUESS->($opts{file});
- $opts{'type'} = $type;
+ $type = $FORMATGUESS->($opts{file});
}
- unless ($opts{'type'}) {
+
+ unless ($type) {
$ERRSTR = "No type parameter supplied and it couldn't be guessed";
return;
}
- my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
- or return;
- if ($opts{'type'} eq 'gif') {
+ _reader_autoload($type);
+
+ if ($readers{$type} && $readers{$type}{multiple}) {
+ return $readers{$type}{multiple}->($IO, %opts);
+ }
+
+ if ($type eq 'gif') {
my @imgs;
@imgs = i_readgif_multi_wiol($IO);
if (@imgs) {
return;
}
}
- elsif ($opts{'type'} eq 'tiff') {
+ elsif ($type eq 'tiff') {
my @imgs = i_readtiff_multi_wiol($IO, -1);
if (@imgs) {
return map {
There are no PNG specific tags.
+=head1 ADDING NEW FORMATS
+
+To support a new format for reading, call the register_reader() class
+method:
+
+=over
+
+=item register_reader
+
+Registers single or multiple image read functions.
+
+Parameters:
+
+=over
+
+=item *
+
+type - the identifier of the file format, if Imager's
+i_test_format_probe() can identify the format then this value should
+match i_test_format_probe()'s result.
+
+This parameter is required.
+
+=item *
+
+single - a code ref to read a single image from a file. This is
+supplied:
+
+=over
+
+=item *
+
+the object that read() was called on,
+
+=item *
+
+an Imager::IO object that should be used to read the file, and
+
+=item *
+
+all the parameters supplied to the read() method.
+
+=back
+
+The single parameter is required.
+
+=item *
+
+multiple - a code ref which is called to read multiple images from a
+file. This is supplied:
+
+=over
+
+=item *
+
+an Imager::IO object that should be used to read the file, and
+
+=item *
+
+all the parameters supplied to the read_multi() method.
+
+=back
+
+=back
+
+Example:
+
+ # from Imager::File::ICO
+ Imager->register_reader
+ (
+ type=>'ico',
+ single =>
+ sub {
+ my ($im, $io, %hsh) = @_;
+ $im->{IMG} = i_readico_single($io, $hsh{page} || 0);
+
+ unless ($im->{IMG}) {
+ $im->_set_error(Imager->_error_as_msg);
+ return;
+ }
+ return $im;
+ },
+ multiple =>
+ sub {
+ my ($io, %hsh) = @_;
+
+ my @imgs = i_readico_multi($io);
+ unless (@imgs) {
+ Imager->_set_error(Imager->_error_as_msg);
+ return;
+ }
+ return map {
+ bless { IMG => $_, DEBUG => $Imager::DEBUG, ERRSTR => undef }, 'Imager'
+ } @imgs;
+ },
+ );
+
+=back
+
+If you name the reader module C<Imager::File::>I<your-format-name>
+where I<your-format-name> is a fully upper case version of the type
+value you would pass to read() or read_multi() then Imager will
+attempt to load that module if it has no other way to read that
+format.
+
+For example, if you create a module Imager::File::GIF and the user has
+built Imager without it's normal GIF support then an attempt to read a
+GIF image will attempt to load Imager::File::GIF.
+
=head1 EXAMPLES
=head2 Producing an image from a CGI script