ImageMagick: how to minimally crop an image to a certain aspect ratio?

Kelley van Evert picture Kelley van Evert · Jan 21, 2014 · Viewed 10.5k times · Source

With imagemagick, I'd like to crop an image, in a minimal fashion, so that it fits a given aspect ratio.

Example: given an image of, say, 3038 x 2014 px, I want to crop it to have a 3:2 aspect ratio. The resulting image would then be 3021 x 2014 px, cropped from the, say, center of the original image.

So looking for a command looking something like convert in.jpg -gravity center -crop_to_aspect_ratio 3:2 out.jpg.

Answer

qubodup picture qubodup · May 4, 2016

1. Specific target resolution

If your goal at the end is to have a certain resolution (for example 1920x1080) then it's easy, using -geometry, the circumflex/hat/roof/house symbol (^) and -crop:

convert in.jpg -geometry 1920x1080^ -gravity center -crop 1920x1080+0+0 out.jpg

To loop over multiple jpg files:

for i in *jpg
  do convert "$i" -geometry 1920x1080^ -gravity center -crop 1920x1080+0+0 out-"$i"
done

2. Aspect ratio crop only

If you want to avoid scaling you have to calculate the new length of the cropped side outside of Imagemagick. This is more involved:

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

I'm using 16:9 in the examples, expecting it to be more useful than 3:2 to most readers. Change both occurences of 1920x1080 in solution 1 or the aw/ah variables in solution 2 to get your desired aspect ratio.