Is that error really generated by the code that you show us? Line 1950 of Imager.pm is this piece of code:
my $index = 1;
for my $img (@images) {
unless ($img->_valid_image("write_multi")) { # Line 1950 here
$class->_set_error($img->errstr . " (image $index)");
return;
}
++$index;
}
This is inside a subroutine called write_multi()
which is passed @images
as one (or, really, several I suppose) of its parameters. The code you have shown us is all about reading files, not writing them.
Looking more closely at the error message, its meaning is clear. It is trying to call the _valid_image()
method on an image object. But instead of having an image object, it has a string which is the image filename. So it seems that somewhere, you are calling write_multi()
passing it an array of image filenames where you should be passing it an array of image objects. Without seeing your real code, I can't be much more help.
So I installed the Perl modules cpan Imager::valid_image
and tried with adding use Imager::valid_image;
or use Imager::_valid_image;
That's just crazy talk! The error message is very clear that _valid_image
is a method name, not a module name.
Always read the error message carefully. Someone put a lot of effort into making it as clear as possible.
Update: Ok. Now you've posted more of the code. And it looks like the problem is exactly as I said. Here's what I said yesterday:
So it seems that somewhere, you are calling write_multi()
passing it an array of image filenames where you should be passing it an array of image objects.
And here's your code:
Imager->write_multi({ ... }, @images) or die Imager->errstr;
The important variable here is @images
. How is @images
populated?
my @images = File::Find::Rule->file()
->name( '*.bmp' )
->in( @path );
So @images
contains a list of image filenames. Not a list of image objects.
Look at your main loop.
foreach my $filename(@images)
{
my $img = Imager->new;
$img->read(file=>$filename, type=>$type)
or die "Cannot read $filename: ", $img->errstr;
}
Here you loop over your array of image filenames and each time round the loop, you create a new Imager object. And then, when you get to the end of the loop iteration, you throw the object away. That's not a good idea.
You probably want to create a new array containing your image objects. Something like this perhaps.
@my @image_objects;
foreach my $filename(@images)
{
my $img = Imager->new;
$img->read(file=>$filename, type=>$type)
or die "Cannot read $filename: ", $img->errstr;
push @image_objects, $img;
}
Then you should pass this new array to write_multi()
.
Imager->write_multi({ ... }, @image_objects) or die Imager->errstr;
In your defence, the documentation for write_multi()
isn't exactly clear. It says:
write_multi()
and if you want to write multiple images to a single file use the write_multi() method:
Imager->write_multi({ file=> $filename, type=>$type }, @images)
or die "Cannot write $filename: ", Imager->errstr;
But it never bothers to tell you what should be in @images
.