Smart crop using focus points

Recently, I faced the task of cropping about a hundred huge pictures from a photobank for several dozen different sizes. These ready-made pictures will then be used by CMS clients to design their sites. Having figured out how long this process will take in Photoshop, I got a bit sad - to celebrate the next New Year with cropping pictures is not in my plans.


The brain of a programmer cannot exist without programming. Any task that requires the repetition of routine operations more than 3 times immediately begins to raise in my head the questions “How would this be automated?” And draw up outline algorithms. So it happened this time.

Having a little "scratched" my brain, I came to the conclusion that we need to introduce the concept of a focal point and consider it when cropping. If the proportions of the new image are close to the original ones, for example, we cut a rectangle from the square with an aspect ratio of 3: 4, then everything is fine, the new image will not even lose in composition. If the size of the new image is very different, for example, this is a narrow strip for the slider, then at least we will save the most significant information. Do not forget, we are still talking about automatic cropping.

Here is an illustration to demonstrate the mechanism.

So, the focal point is the point in the center of the area containing the most important part of the image, and which, when cropped, should remain anyway. For ordinary photography, the lens will be focused in this area during shooting, this is especially clearly seen if shooting was carried out with a shallow depth of field. Hence, in fact, the name for the concept.

I decided to check my conclusions and look if someone had already done something similar. An HTML / CSS library was found for adaptive image cropping . Here, the concept of “focus point” is also used, which means my idea is true! But I needed a ready-made utility that could generate physical images. This could not be found.


Then I took up Node.js, which, although it is not my regular working tool, but which I really like to use for automation and small utilities.

The cropping algorithm for the new image is as follows:
  1. Calculate the final image aspect ratio:
    where Wr and Hr - the width and height of the image of the future
  2. Determine the maximum rectangle that will fit into the original image:
    if Wr >= Hr
    then Wm = Wi, Hm = Wi/k
    else Hm = Hi, Wm = Hm*k,
    where Wi, Hi - the size of the original, and Wm, Hm - the maximum size of the rectangle.
  3. We calculate new coordinates for the focal point:
    fx2 = fx*Wm/Wi,
    fy2 = fy*Hm/Hi,
    fx, fx - the coordinates of the focus on the original image
  4. We do the actual cropping by shifting the rectangle by the difference between the old and new coordinates of the focal point:
    crop(Wm, Hm, (fx-fx2), (fy-fy2))
  5. Reduce the result to the desired size:
    resize(Wr, Hr)

For image processing, I took the GraphicsMagick for node module because it promised to work seamlessly with graphics libraries under Windows. And almost did not lie. ImageMagick along with it I could not start (and the older imagemagick-node module worked without problems), but the alternative in the form of GraphicsMagick worked right away and without shamanism. Theoretically, ImageMagick should also work on another platform, there is no hard link to the library in the gm module.

In the final utility, I added a bit of optimization for the web: all EXIF, ICM, etc. are cut out of the final image and the information is received and the resulting small image is run with a sharpness filter. When reducing from 3000x4000px to 200x300px this is really necessary.

For convenience, the source data is accepted in the form of 2 files:
  1. formats.json - file that lists the formats to which you want to crop
  2. images.json - a file in which images are listed and focus points are set. Here you can specify where and in what quality to save images.

You can read more about file formats, installation, and additional features in the repository on GitHub . There you can find a demo for examples.

And finally, an example of how the utility works.
Link to the original image 5.4 Mb




Also popular now: