# Add image size where largest possible proportional size is generated

I'd like to add an image size where the resulting image will be the largest possible size while retaining a 4:3 aspect ratio.

Suppose I've added an image size like so:

`add_image_size( 'cover-image', 2048, 1536, true );`

By default, WP will only create an image with that size if the full size image is larger than those dimensions.

But suppose my full size image is only 1000px wide. I would still like to have an image cropped to the largest possible 4:3 ratio, which in this case would be 1000x750.

Can this be done?

# The Approach

I think the best approach is to create an image size "on the fly", just before the images is resized.

You can do that using `'intermediate_image_sizes_advanced'` filter hook. That allows you to edit the size to be generated, but being aware of the current image size, that is stored in the array `\$metadata` passed by the filter as second argument.

# The Math

First of all let's write a class that returns the biggest sizes for a specific ratio.

``````class ImageRatio {

private \$ratio;

function __construct(\$ratioW = 4, \$ratioH = 3) {
\$this->ratio = array(\$ratioW, \$ratioH);
}

function getLargestSize(\$imgW, \$imgH) {
\$inverse = false;
// let's try to keep width and calculate new height
\$newSize = round((\$this->ratio[1] * \$imgW) / \$this->ratio[0]);
if (\$newSize > \$imgH) {
\$inverse = true;
// if the calculated height is bigger than actual size
// let's keep current height and calculate new width
\$newSize = round((\$this->ratio[0] * \$imgH) / \$this->ratio[1]);
}

return \$inverse ? array( \$newSize, \$imgH ) : array( \$imgW, \$newSize );
}

}
``````

# Class usage

The usage of the class is pretty easy:

``````\$ratio = new ImageRatio(4, 3)

\$ratio->getLargestSize(1000, 500); // return: array(667, 500)
\$ratio->getLargestSize(1000, 800); // return: array(1000, 750)
``````

# In Action

At this point, we can make use of the class to calculate on the fly an new images size, based on the image is being uploaded

``````add_filter( 'intermediate_image_sizes_advanced', function( \$sizes, \$metadata ) {

if (! empty( \$metadata['width'] ) && ! empty( \$metadata['height'] ) ) {
// calculate the max width and height for the ratio
\$ratio = new ImageRatio( 4, 3 );
list(\$width, \$height) = \$ratio->getLargestSize(
);
// let's add our custom size
\$sizes['biggest-4-3'] = array(
'width'  => \$width,
'height' => \$height,
'crop'   => true
);
}

return \$sizes;

}, 10, 2 );
``````

# Using the New Size

``````\$image = wp_get_attachment_image( \$attachment_id, 'biggest-4-3' );
``````

# Note

Of course, this works for all the images that you upload after the code is in place. For older images, you should re-generate the thumbnails, on the fly when they are used, or in bulk using one of the plugins available on the web.

• This works great, thanks! One minor correction I would make: I think it's unnecessary to set a default ratio in the constructor, as I might use this for other ratios in the future. Makes sense to always supply the desired ratio on instantiation. Commented Dec 24, 2015 at 14:45
• The args in constructor are just default. You can pass any ratio you want, default are used only if you don't pass anything Commented Dec 25, 2015 at 11:11