我正在尝试使用ImageMagick和perlmagick (Image::Magick)对图像进行一些批量调整操作。我所有的图片都是大图片,我想调整它们的大小到不同的间隔或高度或宽度。我想一直保持长宽比
给定一个尺寸为3840像素× 2160像素(3840x2160)的示例图像,我想创建以下调整大小的图像:
?x1000
?x500
?x100
1600x?
1200x?
800x?
400x?
我可以非常简单地使用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
由于我试图将这些操作与其他操作一起批量执行,因此我试图在perl中使用Image::Magick执行这些相同的操作。我尝试了几种不同的方法,结果如下:
#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是正确的。为了保持长宽比,通过geometry
关键字提供宽度和高度。通过在一次调用而不是两次调用中执行resize,可以使您的过程更通用:
$image->Resize(geometry => "${width}x${height}");
这确保Resize只被调用一次,即使你同时提供了$width和$height。只需确保如果没有提供任何一个值,则将其设置为空字符串。如果你在方法#2中为你的过程提供了宽度和高度,这可能就是你看到的模糊的原因。
另一个可能的模糊来源是resize操作符使用的过滤器。对于给定操作使用的最佳过滤器取决于图像的颜色特征以及原始尺寸和目标尺寸之间的关系。我建议通过http://www.imagemagick.org/script/command-line-options.php#filter了解相关信息。在PerlMagick中,您可以通过filter
关键字指定要使用的Resize过滤器。
也就是说,我没有发现我所尝试的图像有特别的模糊问题,所以如果问题仍然存在,测试图像将是最有帮助的。
我可能有点晚了,但是我有一个非常相似的目标—调整图像大小并保持图像质量和它占用的磁盘空间量之间的平衡—我编写了以下代码。我从OPs代码开始,并遵循这篇非常有趣的文章:https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/
结果如下:
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的质量。设置,当然保持长宽比,无论你提供的是宽度还是高度。
为时已晚,但也许它可以帮助其他人。