Press enter to see results or esc to cancel.

Focal point crop 2.0

Public links are pre-generated and cached on CDN, and transformations are generated on-the-fly. Also, public links can be custom cropped, thus the algorithm can be influenced to obtain the desired result of focal point cropping; while transformations can only be either cropped ‘smart’ or centered. Those two reasons steered me in the direction of basing my initial focal point crop functionality solely on public links.

After the first pilot phase though, I discovered three disadvantages of this method:

  • you would have to create a public link for each desired image size,
  • you are unnecessarily downsizing your original image too early in the process,
  • and you cannot easily add a new image size to all of your assets.

The first disadvantage means that you will end up with a lot of public links, which clutters the user interface and has a negative impact on performance upon regeneration of the public links (when the focal point changes, when the source image changes, or when the user requests to refresh the public links) and possibly on your Content Hub implementation in general. The second disadvantage means that you rule out the possibility of delivering content for retina displays: if you pre-configure a fixed size like 1024 x 576 while the original image is 5624 x 3749, you are inadvertently loosing a lot of image data. If you want to serve the image on your website for retina displays you would need 2048 x 1152 for example, which is perfectly possible given the original image size. You could add all of your image sizes in twice the resolution, but than you would even double the amount of required public links! Lastly, the third disadvantage is a huge blocker in flexibility and maintenance if you ever want to extend the list of desired image resolutions.

Additionally, I should mention that while transformations are generated on demand, they are still being cached on CDN after that, making each subsequent request way faster.

A rational solution

The solution I came up with drastically reduces the amount of required public links, while removing any limitation caused by predefined image sizes. I simply added the possibility to crop on ratio instead of size, and moved the cropping by size to the transformation functionality of Content Hub.

I’ve first extended my own cropping definition class with a boolean to indicate I want to generate a public link for the original image (without cropping, this is also a new feature of this version). And I’ve added extra members to be able to crop by ratio:

I didn’t remove the possibility to crop on image size as I want maximum flexibility. Consequently, you can now either create a cropping definition for the original, based on a specific size, or for a more generic ratio.

I admit that it would be even nicer to create different cropping definition classes inheriting from a base interface instead of setting unused parameters to int 0 values, but since custom Scripts in Content Hub exist of one long code file within a text box in your browser, I opted for this shorter implementation, albeit being a little dirty in a way.

For the Original image size all I had to do was omit creating a ConversionConfiguration JSON object. The rest of the public link generation stays the same.

For the ratio cropping I needed a bit more logic. I didn’t alter the original focal point cropping algorithm though, I just added a step before this algorithm to calculate the maximum available size for the given ratio within original image size of the current asset, and then continued cropping by image width and height:

Going back to the example above, I can now generate a 16×9 public link for the asset that is originally sized 5624 x 3749 pixels. Then, I can chose to add a transformation for either w1024 or w2048 or both, like so:

Adding transformations is a way more maintenance friendly process, you don’t need to go over all of your assets to generate a new public link. Thus tackling the third disadvantage: as long as you are staying within the boundaries of your pre-defined ratios, you can add new sizes by simply adding new transformations without any regeneration process at all!

Endless possibilities

Also, you can cover small deviations to the pre-defined ratios as well. If for one application you would need let’s say 1024 x 544 (which is effectively 16×8.5) you are only off by 32 pixels from the pure 16×9 ratio. What you can do is just use the 16×9 ratio public link, and create a new transformation for specifically 1024 x 544 pixels, while selecting the “Smart” cropping algorithm for your transformation. This small deviation doesn’t influence the focal point you’ve selected much, and the last bit of cropping will be done using the Smart algorithm, which almost exclusively produces good results when the differences in cropping ratio are that small. So with this approach, you basically have endless possibilities with no more than 8 public links to cover all the mainstream image ratios.

A consideration regarding stability

In the example code I am using the asset field Title to generate my public links. This generates a more human friendly URL and some say also increases SEO value. The downside of this is though, that when someone changes the title of an asset and re-generates the public links, you end up with broken links if you have selected the public links from your Sitecore CMS implementation (or other consumer). This is because Sitecore Connect for Content Hub stores selected public links as external links. It obviously doesn’t maintain or update links dynamically. To avoid this, we’ve chosen to stick to the asset ID for naming the auto-generated public links. This way, as long as an asset is still available, the public links remains the same:

This means that the new result of an auto-generated public link with transformation via my focal point cropping functionality is a very logical, self-explanatory and predictable format (ID, ratio and size):


Check out the latest version of my Content Hub extension at


Comments are disabled for this post