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

时间:2016-09-15 15:06:33

标签: perl perl-module

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

  

找不到对象方法“_valid_image”   无法通过包“D:\ work ... graph1.bmp”找到对象方法“_valid_image”(也许你忘了加载“D:\ work ... \ graph1.bmp”?)在C:/ Perl / site / lib / Imager.pm 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;,但它又引发了另一个错误

  

无法在@INC中找到Imager / valid_image.pm(您可能需要安装Imager :: valid_image模块)(@INC    包含:C:/ Perl / site / lib C:/ Perl / lib。)at make_gif.pl第14行。

真的很抱歉没有提供完整的代码,我错过了实际出现错误的部分。现在我已经更新了

1 个答案:

答案 0 :(得分:0)

这个错误是否真的由您向我们展示的代码生成? 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()传递一个图像文件名数组,你应该在其中传递一个图像对象数组。如果没有看到真正的代码,我就无法提供更多帮助。

  

所以我安装了Perl模块cpan Imager::valid_image并尝试添加use Imager::valid_image;use Imager::_valid_image;

那只是疯狂的谈话!错误消息非常清楚_valid_image是方法名称,而不是模块名称。

请务必仔细阅读错误消息。有人投入了大量精力使其尽可能清晰。

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

  

所以似乎在某个地方,你正在调用write_multi()传递一个图像文件名数组,你应该在其中传递一组图像对象。

这是你的代码:

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()

     

如果要将多个图像写入单个文件,请使用write_multi()方法:

Imager->write_multi({ file=> $filename, type=>$type }, @images)
  or die "Cannot write $filename: ", Imager->errstr;

但它绝不会告诉你@images中的内容。