在 Perl 模块中找不到对象方法:Imager

Object method not found in Perl module : Imager

我正在尝试使用 Imager 模块生成 gif 图像,但出现错误

Can't locate object method "_valid_image" Can't locate object method "_valid_image" via package "D:\work...graph1.bmp" (perhaps you forgot to load "D:\work...\graph1.bmp"?) at C:/Perl/site/lib/Imager.pm line 1950.

我检查了模块的 .pm 文件,其中定义了命名函数。

我正在使用的代码片段:

use strict;
use warnings;
use File::Find::Rule;
use Imager;
my @path = $ARGV[0];

my @images = File::Find::Rule->file()
                            ->name( '*.bmp' )
                            ->in( @path );
my $type = 'bmp';
foreach my $filename(@images)
{
    my $img = Imager->new;
    $img->read(file=>$filename, type=>$type) or die "Cannot read $filename: ", $img->errstr;
}
my $filename1 = 'ctpdbn';
Imager->write_multi({ file=>$filename1, type=>'bmp' }, @images) or die Imager->errstr;

所以我安装了 Perl 模块 cpan Imager::valid_image 并尝试添加 use Imager::valid_image;use Imager::_valid_image;,但它引发了另一个错误

Can't locate Imager/valid_image.pm in @INC (you may need to install the Imager::valid_image module) (@INC contains: C:/Perl/site/lib C:/Perl/lib .) at make_gif.pl line 14.

很抱歉没有贴出完整的代码,我错过了实际出错的部分。现在我更新了它

这个错误真的是由您向我们展示的代码产生的吗? Imager.pm的1950行是这段代码:

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;
}

这是一个名为 write_multi() 的子例程,该子例程作为其参数之一(或者,实际上,我想是几个)传递给 @images。您向我们展示的代码都是关于读取文件,而不是写入文件。

仔细查看错误信息,其含义很清楚。它试图在图像对象上调用 _valid_image() 方法。但是它没有图像对象,而是有一个字符串,它是图像文件名。因此,似乎在某个地方,您正在调用 write_multi() 向它传递一个图像文件名数组,而您应该向它传递一个图像对象数组。没有看到您的真实代码,我帮不上什么忙。

So I installed the Perl modules cpan Imager::valid_image and tried with adding use Imager::valid_image; or use Imager::_valid_image;

这简直是疯话!报错信息很清楚_valid_image是方法名,不是模块名

始终仔细阅读错误消息。有人花了很多精力让它尽可能清楚。

更新:好的。现在您已经发布了更多代码。看起来问题就像我说的那样。这是我昨天说的:

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.

这是您的代码:

Imager->write_multi({ ... }, @images) or die Imager->errstr;

这里重要的变量是@images@images 是如何填充的?

my @images = File::Find::Rule->file()
                             ->name( '*.bmp' )
                             ->in( @path );

所以 @images 包含图像文件名列表。不是图像对象列表。

看看你的主循环。

foreach my $filename(@images)
{
    my $img = Imager->new;
    $img->read(file=>$filename, type=>$type)
        or die "Cannot read $filename: ", $img->errstr;
}

在这里你循环你的图像文件名数组,每次循环,你创建一个新的 Imager 对象。然后,当您到达循环迭代的末尾时,您将对象扔掉。这不是个好主意。

您可能想要创建一个包含图像对象的新数组。大概是这样的。

@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;
}

然后你应该将这个新数组传递给write_multi()

Imager->write_multi({ ... }, @image_objects) or die Imager->errstr;

为您辩护,the documentation for write_multi() 不是很清楚。它说:

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;

但它从不费心告诉你 @images.

中应该有什么