Image::Magick(perlmagick)调整纵横比和质量问题的大小(不同于convert命令行实用程序)

Image::Magick(perlmagick)调整纵横比和质量问题的大小(不同于convert命令行实用程序),image,perl,resize,imagemagick,perlmagick,Image,Perl,Resize,Imagemagick,Perlmagick,我正在尝试使用ImageMagick和perlmagick(Image::Magick)对图像进行一些批量调整大小的操作。我所有作为源的图像都是大图像,我想将它们调整到不同的间隔或高度或宽度。我希望始终保持纵横比 给定一个尺寸为3840像素×2160像素(3840x2160)的示例图像,我想创建以下调整大小的图像: ?x1000 ?x500 ?x100 1600x? 1200x? 800x? 400x? 我可以非常简单地使用convert

我正在尝试使用ImageMagick和perlmagick(Image::Magick)对图像进行一些批量调整大小的操作。我所有作为源的图像都是大图像,我想将它们调整到不同的间隔或高度或宽度。我希望始终保持纵横比

给定一个尺寸为3840像素×2160像素(3840x2160)的示例图像,我想创建以下调整大小的图像:

    ?x1000
    ?x500
    ?x100
    1600x?
    1200x?
    800x?
    400x?
我可以非常简单地使用convert命令行实用程序和以下命令(按顺序)执行此操作:

由于我试图将这些操作与其他操作一起批量执行,所以我试图使用Image::Magick在perl中执行这些相同的操作。我尝试了几种不同的方法,结果如下:

#METHOD 1
    my $image = Image::Magick->new();
    $image->Read($input_filename);
    $image->Resize(
        ($width  ? ('width'  => $width)  : ()),
        ($height ? ('height' => $height) : ()),
    );
    $image->Write(filename => $output_filename);
这会导致图像无法保持纵横比。例如,如果提供的高度为100,则输出图像将是原始宽度的100倍(3840x100)。提供宽度时会产生类似的效果——高度保持不变,但纵横比不保持不变

#METHOD 2
    my $image = Image::Magick->new();
    $image->Read($input_filename);
    die "Only one dimension can be supplied" if $width && $height;
    $image->Resize(geometry => $width) if $width;
    $image->Resize(geometry => "x$height") if $height;
    $image->Write(filename => $output_filename);
这将生成保持纵横比的图像,如果几何体操作基于高度,则输出正是预期的结果。但是,如果提供了宽度,则输出非常模糊

#METHOD 3
    `convert "$input_filename" -resize $width   "$output_filename"` if $width;
    `convert "$input_filename" -resize x$height "$output_filename"` if $height;
这会产生所有正确的图像,但会在perl过程之外分叉,从而导致效率问题

在perl中是否有更好的方法使此调整大小操作产生与命令行转换实用程序相同的结果?

我的命令行实用程序报告版本6.7.9-10,Image::Magick报告版本6.79。

您的方法2是正确的。要保留纵横比,请通过
几何体
关键字提供宽度和高度。通过在一次调用中而不是两次调用中执行调整大小,可以使您的过程更加通用:

$image->Resize(geometry => "${width}x${height}");
这确保了即使同时提供$width和$height,Resize也只调用一次。只要确保没有提供任何一个值,就将其设置为空字符串。如果您在方法2中为您的过程提供了宽度和高度,那么这可能就是您看到的模糊的原因

另一个可能的模糊源是“调整大小”操作符使用的过滤器。用于给定操作的最佳过滤器取决于图像的颜色特征以及原始维度和目标维度之间的关系。我建议大家通读一遍,了解这方面的信息。在PerlMagick中,您可以通过
过滤器
关键字指定要调整大小的过滤器


也就是说,我没有发现我尝试过的图像的模糊性有什么特别的问题,所以如果问题仍然存在,测试图像将是最有帮助的。

我参加这次聚会可能会晚一点,但是,由于我有一个非常相似的目标——调整图像大小,并在图像质量和占用的磁盘空间之间保持平衡——我想出了以下代码。我从OPs代码开始,接着读了这篇非常有趣的文章:

结果是:

sub optimize_image_size
{
my $imagePath = shift();
my $height = shift(); #720
my $width = shift(); #1080

 my $image = Image::Magick->new();
    $image->Read($imagePath);
    die "Only one dimension can be supplied" if $width && $height;
    $image->Thumbnail(geometry => "$width",filter=>'Triangle') if $width;
    $image->Thumbnail(geometry => "x$height",filter=>'Triangle') if $height;
    $image->Colorspace(colorspace=>'sRGB');
    $image->Posterize(levels=>136, dither=>'false');
    $image->UnsharpMask(radius=>0.25, sigma=>0.25, threshold=>0.065, gain=>8);
    $image->Write(filename => $imagePath
            , quality=>'82'
            , interlace=>'None'
    );

}
至少对我来说,它可以产生非常令人满意的大小缩减(我的6MB样本图像被缩减到约90Kb),同时保持与Photoshop“用于web”设置类似的质量,当然,无论您提供的是宽度还是高度,都可以保持纵横比


对于OP来说太晚了,但也许它能帮助其他人。

我正在用方法2做这件事。我正在基于单个维度调整大小,因此只会进行一次调整大小调用。我将更新代码示例以使其更清晰。您是否建议我的宽度几何参数改为“${width}x”?如果给定的宽度为100,则几何体应为“100x”,如果给定的高度为100,则几何体也应为“x100”。如果提供了$width 100,则我的代码当前将通过几何体的'100'。在仅具有宽度的'geometry'参数中是否有“x”并不重要。它可以安全地在那里,也可以不在那里。
sub optimize_image_size
{
my $imagePath = shift();
my $height = shift(); #720
my $width = shift(); #1080

 my $image = Image::Magick->new();
    $image->Read($imagePath);
    die "Only one dimension can be supplied" if $width && $height;
    $image->Thumbnail(geometry => "$width",filter=>'Triangle') if $width;
    $image->Thumbnail(geometry => "x$height",filter=>'Triangle') if $height;
    $image->Colorspace(colorspace=>'sRGB');
    $image->Posterize(levels=>136, dither=>'false');
    $image->UnsharpMask(radius=>0.25, sigma=>0.25, threshold=>0.065, gain=>8);
    $image->Write(filename => $imagePath
            , quality=>'82'
            , interlace=>'None'
    );

}