简体   繁体   English

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

[英]Image::Magick (perlmagick) resizing aspect ratio and quality issues (different than convert command line utility)

I am attempting to do some bulk resizing operations of images using ImageMagick and perlmagick (Image::Magick).我正在尝试使用 ImageMagick 和 perlmagick (Image::Magick) 对图像进行一些批量调整大小操作。 All of the images I have as sources are large images and I want to resize them down to various intervals or either height or width.我作为源的所有图像都是大图像,我想将它们调整为不同的间隔或高度或宽度。 I want to always preserve the aspect ratio.我想始终保持纵横比。

Given an example image with dimensions of 3840 pixels × 2160 pixels (3840x2160) I want to create the following resized images:给定尺寸为 3840 像素 × 2160 像素 (3840x2160) 的示例图像,我想创建以下调整大小的图像:

    ?x1000
    ?x500
    ?x100
    1600x?
    1200x?
    800x?
    400x?

I can do this very simply using the convert command line utility with the following commands (in order):我可以非常简单地使用带有以下命令的convert命令行实用程序(按顺序):

    convert input_filename.jpg -resize x1000 output_wx1000.jpg
    convert input_filename.jpg -resize x500  output_wx500.jpg
    convert input_filename.jpg -resize x100  output_wx100.jpg
    convert input_filename.jpg -resize 1600  output_1600xh.jpg
    convert input_filename.jpg -resize 1200  output_1200xh.jpg
    convert input_filename.jpg -resize 800   output_800xh.jpg
    convert input_filename.jpg -resize 400   output_400xh.jpg

Since I am attempting to perform these operations in bulk in conjunction with other operations I am attempting to perform these same operations in perl using Image::Magick .由于我试图与其他操作一起批量执行这些操作,因此我尝试使用Image::Magick在 perl 中执行这些相同的操作。 I have tried several different methods with the following results:我尝试了几种不同的方法,结果如下:

#METHOD 1
    my $image = Image::Magick->new();
    $image->Read($input_filename);
    $image->Resize(
        ($width  ? ('width'  => $width)  : ()),
        ($height ? ('height' => $height) : ()),
    );
    $image->Write(filename => $output_filename);

This results in images that do not maintain aspect ratio.这会导致图像不保持纵横比。 For example, if a height of 100 is supplied, the output image will be the original width by 100 (3840x100).例如,如果提供的高度为 100,则输出图像将为原始宽度乘以 100 (3840x100)。 A comparable effect is had when supplying a width -- the height is maintained, but the aspect ratio is not.提供宽度时具有类似的效果 - 保持高度,但不保持纵横比。

#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);

This results in images that maintain aspect ratio , and if the geometry operation is based on height, the output is exactly what is intended.这导致图像保持纵横比,如果几何操作基于高度,则输出正是预期的。 However, if a width is supplied the output is terribly blurry.但是,如果提供了宽度,则输出会非常模糊。

#METHOD 3
    `convert "$input_filename" -resize $width   "$output_filename"` if $width;
    `convert "$input_filename" -resize x$height "$output_filename"` if $height;

This results in images that are all correct, but forks outside of the perl process leading to efficiency issues.这导致图像全部正确,但在 perl 进程之外分叉导致效率问题。

Is there a better way in perl to make this resize operation produce the same results as the command-line convert utility? perl 中是否有更好的方法来使此调整大小操作产生与命令行转换实用程序相同的结果?

My command line utility reports version 6.7.9-10, and Image::Magick reports version 6.79.我的命令行实用程序报告版本 6.7.9-10,Image::Magick 报告版本 6.79。

Your method #2 is on the right track.您的方法#2 走在正确的轨道上。 To preserve aspect ratio, supply the width and height via the geometry keyword.要保持纵横比,请通过geometry关键字提供宽度和高度。 Your procedure can be made more general by performing the resize in one call instead of two:通过在一次调用而不是两次调用中执行调整大小,可以使您的过程更加通用:

$image->Resize(geometry => "${width}x${height}");

This ensures that Resize will only be called once, even if you supply both $width and $height.这确保 Resize 只会被调用一次,即使您同时提供 $width 和 $height。 Just make sure that if either value is not supplied, you set it to the empty string.只要确保如果未提供任一值,则将其设置为空字符串。 If you supplied both a width and height to your procedure in method #2, that could have been the cause of the blurriness you saw.如果您在方法 2 中为您的过程提供了宽度和高度,这可能是您看到的模糊的原因。

Another possible source of blurriness is the filter used by the resize operator.另一个可能的模糊来源是调整大小操作符使用的过滤器。 The best filter to use for a given operation depends on both the color characteristics of the image and the relationship between the original dimensions and the target dimensions.用于给定操作的最佳过滤器取决于图像的颜色特征以及原始尺寸和目标尺寸之间的关系。 I recommend reading through http://www.imagemagick.org/script/command-line-options.php#filter for information about that.我建议通读http://www.imagemagick.org/script/command-line-options.php#filter以获取有关信息。 In PerlMagick, you can specify the filter for Resize to use via the filter keyword.在 PerlMagick 中,您可以通过filter关键字指定要使用的 Resize filter

That said, I did not find particular problems with blurriness with images that I tried, so if the problem persists, a test image would be most helpful.也就是说,我没有发现我尝试过的图像模糊的特殊问题,所以如果问题仍然存在,测试图像将是最有帮助的。

I might be a little late to this party, but as I had a very similar goal - resizing an image and maintaining a balance between image quality and the amount of disc space it takes up - I came up with the following code.我参加这个聚会可能有点晚了,但是因为我有一个非常相似的目标 - 调整图像大小并在图像质量和它占用的磁盘空间量之间保持平衡 - 我想出了以下代码。 I started out with OPs code and followed this very interesting article: https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/我从 OPs 代码开始,并遵循了这篇非常有趣的文章: https : //www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/

This is the result:这是结果:

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'
    );

}

At least for me it produces very satisfactory size reduction (my 6MB sample images were reduced to about 90Kb), while keeping a quality similar to Photoshops "for web" settings and of course maintaining aspect ratio no matter if you provide width or height.至少对我来说,它产生了非常令人满意的尺寸缩小(我的 6MB 样本图像缩小到大约 90Kb),同时保持类似于 Photoshop 的“网络”设置的质量,当然无论您提供宽度还是高度都保持纵横比。

Too late for OP but maybe it helps other people. OP 为时已晚,但也许可以帮助其他人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM