imagemagick - tamaño - optimizar para web lightroom
ImageMagick: ¿cómo recortar mínimamente una imagen a una determinada relación de aspecto? (5)
Con imagemagick, me gustaría recortar una imagen, de manera mínima, para que se ajuste a una relación de aspecto determinada.
Ejemplo: dada una imagen de, digamos, 3038 x 2014 px, quiero recortarla para que tenga una relación de aspecto de 3: 2. La imagen resultante sería entonces 3021 x 2014 px, recortada del centro, digamos, de la imagen original.
Así que busco un comando que busque algo como convert in.jpg -gravity center -crop_to_aspect_ratio 3:2 out.jpg
.
1. Resolución específica del objetivo.
Si su objetivo al final es tener una cierta resolución (por ejemplo, 1920x1080), entonces es fácil, usando -geometry
, el símbolo de circunflejo / sombrero / techo / casa ( ^
) y -crop
:
convert in.jpg -geometry 1920x1080^ -gravity center -crop 1920x1080+0+0 out.jpg
Para recorrer varios archivos jpg:
for i in *jpg
do convert "$i" -geometry 1920x1080^ -gravity center -crop 1920x1080+0+0 out-"$i"
done
2. Relación de aspecto sólo para cultivos
Si desea evitar el escalado, debe calcular la nueva longitud del lado recortado fuera de Imagemagick. Esto es más complicado:
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
Estoy usando 16: 9 en los ejemplos, esperando que sea más útil que 3: 2 para la mayoría de los lectores. Cambie ambas apariciones de 1920x1080
en la solución 1 o las variables aw
/ ah
en la solución 2 para obtener la relación de aspecto deseada.
Con el advenimiento de ImageMagick 7, puede usar expresiones FX para lograr un recorte al mayor tamaño de imagen posible, dada la relación de aspecto en un solo comando.
El único truco es que necesitarás ingresar el aspecto deseado en cuatro lugares diferentes en el mismo comando, por lo que me resulta más fácil crear una variable para ese bit. El aspecto puede ser un número decimal o una fracción como una cadena que la expresión fx puede resolver.
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
Una vez que el aspecto es correcto, puede hacer un seguimiento de las dos operaciones de -extent
con un -resize
para llevar la imagen terminada a su tamaño de salida. El ejemplo anterior lo mantiene tan grande como se le puede dar la imagen de entrada.
Las versiones recientes de Imagemagick (desde 6.9.9-34) tienen un recorte de aspecto. Así que puedes hacer:
Entrada:
convert barn.jpg -gravity center -crop 3:2 +repage barn_crop_3to2.png
La salida es 400x267 + 0 + 0. Pero tenga en cuenta que el símbolo + es necesario para eliminar el lienzo virtual de 400x299 + 0 + 16, porque la salida PNG es compatible con el lienzo virtual. La salida de JPG no necesitaría el repage +, ya que no admite un lienzo virtual.
Necesita calcular las dimensiones requeridas y luego hacer un recorte. Aquí hay una función que, dado el width
y el height
la imagen más la relación de aspecto requerida como aspect_x
y aspect_y
, generará una cadena de recorte que se puede usar con 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
Estoy usando algo similar a esto en una aplicación que usa la gema Dragonfly.
Necesitaba dividir imágenes muy largas verticalmente con relación de aspecto de papel A4 (1x1.414). Así que se me ocurrió una solución a continuación. Supongamos que el nombre de archivo de la imagen es ch1.jpg:
convert -crop $(identify -format "%w" ch1.jpg)x$(printf "%.0f" $(echo $(identify -format "%w" ch1.jpg) /* 1.414|bc)) +repage ch1.jpg ch1.jpg