如何在不使用 ImageMagick 调整大小或裁剪的情况下以固定的纵横比调整图像?

How to fit images within fixed aspect ratio without resizing or cropping with ImageMagick?

我的摄影网站连接到打印服务,但它们只提供几种标准宽高比(2:3、4:5、1:1 等)。我的许多照片使用其他宽高比,因此根本不作为打印件提供。

为了解决这个问题,我想使用 ImageMagick CLI 或其他工具将图像放在具有标准宽高比的 canvas 上,比如 4:5。在任何阶段都不得对源图像进行重采样或裁剪,只有外部尺寸 (canvas) 可能会增长。

我想出的概念是:

  1. 取一张非标准纵横比的源图,canvas用白色在各个方向扩大20%。由于源图像大小不同,这必须是相对的,因为像素尺寸需要对图像重新采样。
  2. 以 4:5 宽高比将生成的乱码图像设置在另一个白色 canvas 内。在大多数情况下,垂直或水平边都会被裁剪,但裁剪只会影响 20% 的白色边框,不会影响源图像。

输出应该是不同像素尺寸的图像,具有固定的 4:5 纵横比,所有四个边缘周围都有不同厚度的白色边框。我创建了一个 sample page with before and after views on my website.

由于宽高比差异很大,我必须通过脚本多次 运行 我的所有照片,目标宽高比各不相同,然后为每张照片选择最平衡的宽高比。很乏味,但我认为没有办法将其自动化。

知道如何完成这个吗?或者更好的建议?

我在 Windows 或 Linux 中使用 IM 的 6.x,而不是在网站上。

我倾向于在 php 工作,现在要睡觉了,但这是一个使用 php 和版本 7 的示例。正如您在版本 7 中看到的那样,您可以进行一些计算命令内。在版本 6 上,它必须是一个单独的行,保存到一个变量中,然后该变量将在命令中使用。

只是快速测试以查看它是否有效,我可能把 landscape/portrate 逻辑搞错了。但它应该让您了解它是如何工作的。

<?php
// Setup the image to use
$image = '_MG_4949.jpg';
// Get the dimensions of the image into an array
$size = getimagesize("$image");

// Aspect array
$aspect = array(.87, 1.45);

// If landscape original image do this
If ($size[0] > $size[1])    {
foreach ( $aspect as $value )   { 
    exec("magick $image -background white -gravity center -extent \"%[fx:w*1.2]\"x\"%[fx:w*$value]\" $value.jpg"); 
                                }
                        }
// If portrate image do this
else {
foreach ( $aspect as $value )   { 
    exec("magick $image -background white -gravity center -extent \"%[fx:h*$value]\"x\"%[fx:h*1.2]\" $value.jpg"); 
                                }
}   
?>

编辑上面的代码现在应该可以了

这是 V6 的 php 版本(这次没有 php getimagesize 函数),您应该可以将这两个版本转换为 bash 或批处理文件。

// Setup the image to use
$image = '_MG_6790.jpg';
// Get the dimensions of the image into an array
$height = exec("identify $image -ping -format %[fx:h] info:");
$width = exec("identify $image -ping -format %[fx:w] info:");

// Aspect array
$aspect = array(.87, 1.45);

// If landscape original image do this
If ($width > $height)   {
foreach ( $aspect as $value )   { 
    $newWidth = $width*1.2;
    $newHeight = $height*$value;
    exec("convert $image -background white -gravity center -extent {$newWidth}x{$newHeight} $value.jpg"); 
                                }
                        }
// If portrate image do this
else {
foreach ( $aspect as $value )   { 
    $newWidth = $width*$value;
    $newHeight = $height*1.2;
    exec("convert $image -background white -gravity center -extent {$newWidth}x{$newHeight} $value.jpg"); 
                                }
}