ImageMagick: как минимально обрезать изображение с определенным соотношением сторон?
С imagemagick я хотел бы обрезать изображение минимальным образом, чтобы он соответствовал данному соотношению сторон.
Пример: с учетом изображения, скажем, 3038 x 2014 px, я хочу обрезать его с соотношением сторон 3: 2. Тогда получившееся изображение будет 3021 x 2014 px, обрезанное из, скажем, центра исходного изображения.
Итак, ища команду, выглядящую как-то вроде convert in.jpg -gravity center -crop_to_aspect_ratio 3:2 out.jpg
.
Ответы
Ответ 1
1. Конкретное разрешение цели
Если ваша цель в конце должна иметь определенное разрешение (например, 1920x1080), то легко, используя -geometry
, символ circumflex/hat/roof/house (^
) и -crop
:
convert in.jpg -geometry 1920x1080^ -gravity center -crop 1920x1080+0+0 out.jpg
Чтобы перебрать несколько файлов jpg:
for i in *jpg
do convert "$i" -geometry 1920x1080^ -gravity center -crop 1920x1080+0+0 out-"$i"
done
2. Только для формата изображения
Если вы хотите избежать масштабирования, вам нужно вычислить новую длину обрезанной стороны вне Imagemagick. Это более важно:
aw=16 #desired aspect ratio width...
ah=9 #and height
in="in.jpg"
out="out.jpg"
wid=`convert "$in" -format "%[w]" info:`
hei=`convert "$in" -format "%[h]" info:`
tarar=`echo $aw/$ah | bc -l`
imgar=`convert "$in" -format "%[fx:w/h]" info:`
if (( $(bc <<< "$tarar > $imgar") ))
then
nhei=`echo $wid/$tarar | bc`
convert "$in" -gravity center -crop ${wid}x${nhei}+0+0 "$out"
elif (( $(bc <<< "$tarar < $imgar") ))
then
nwid=`echo $hei*$tarar | bc`
convert "$in" -gravity center -crop ${nwid}x${hei}+0+0 "$out"
else
cp "$in" "$out"
fi
Я использую 16: 9 в примерах, ожидая, что он будет более полезен, чем 3: 2, для большинства читателей. Измените оба входа 1920x1080
в решении 1 или переменные aw
/ah
в решении 2, чтобы получить желаемое соотношение сторон.
Ответ 2
С появлением ImageMagick 7 вы можете использовать выражения FX для достижения урожая с максимальным размером изображения, которое возможно с учетом соотношения сторон в одной команде.
Единственный трюк - вам нужно будет ввести желаемый аспект в четырех разных местах по одной и той же команде, поэтому мне легче всего сделать переменную для этого бита. Аспект может быть десятичным числом или дробью в виде строки, которую может разрешить выражение fx.
aspect="16/9"
magick input.png -gravity center \
-extent "%[fx:w/h>=$aspect?h*$aspect:w]x" \
-extent "x%[fx:w/h<=$aspect?w/$aspect:h]" \
output.png
Как только аспект прав, вы можете выполнить две операции -extent
с помощью -resize
, чтобы довести готовое изображение до вашего размера вывода. Приведенный выше пример сохраняет его как можно больше, поскольку ему может быть предоставлено входное изображение.
Ответ 3
Вам нужно выработать необходимые размеры, а затем сделать урожай. Здесь функция, которая при изображении width
и height
плюс требуемое соотношение сторон как aspect_x
и aspect_y
, выведет строку обрезки, которая может использоваться с Imagemagick.
def aspect(width, height, aspect_x, aspect_y)
old_ratio = width.to_f / height
new_ratio = aspect_x.to_f / aspect_y
return if old_ratio == new_ratio
if new_ratio > old_ratio
height = (width / new_ratio).to_i # same width, shorter height
else
width = (height * new_ratio).to_i # shorter width, same height
end
"#{width}x#{height}#" # the hash mark gives centre-gravity
end
Я использую нечто похожее на это в приложении, использующем Dragonfly Gem.