I came across the same problem trying to standardize logos. At first, I thought that I could choose a standard area and resize all the images to that area, but there are two problems with that strategy. First, you have to set limits for height and width, so sometimes you end up images with a smaller area because they are very wide or tall. Secondly, that might make your layout look ugly. In my case I have a header on top, an image and then text below. I realized that a very wide image would leave a big gap between the header and the text. Because of that, I needed a solution that would give preference to width. What I mean by that is that the image can change a lot in width without changing the height a lot. Different applications may have different requirements, but I think my solution allows for any situation such as a preference for height as well:
function width_to_height($width, $slope, $icpt){
if ($width == 0){
return FALSE;
}
return floor(($icpt + sqrt(pow($icpt, 2) + 4*$slope*pow($width, 2)))/(2*$width));
}
function ratio_to_height($ratio, $slope, $icpt){
if ($ratio == 0){
return FALSE;
}
$area = $ratio*$slope + $icpt;
return floor(sqrt($area/$ratio));
}
function calc_dims($width, $height, $max_w=168, $max_h=100){
$slope = 2500;
$icpt = 6000;
$ratio = $width/$height;
$max_ratio = $max_w/$this->width_to_height($max_w, $slope, $icpt);
if ($ratio > $max_ratio){
$ht = floor($max_w/$ratio);
return array('width' => $max_w, 'height' => $ht);
}
$ht = $this->ratio_to_height($ratio, $slope, $icpt);
if ($ht > $max_h){
$wd = floor($max_h*$ratio);
return array('width' => $wd, 'height' => $max_h);
}
$wd = floor($ht*$ratio);
return array('width' => $wd, 'height' => $ht);
}
The main function is calc_dims() which calls the other two functions. Since I almost always work with classes, these functions are called with the "this->" operator. If you don't use classes, you can simply delete the operator.
You can see that I hard-coded some variables. (In my real life application, these are called from a configuration file.) $max_w and $max_h are pretty self explanatory as the maximum height and width of the images. However $slope and $icpt may be a little more difficult to understand. As you can see in the ratio_to_height() function, $slope and $icpt (intercept) are components in a linear relationship between area and the aspect ratio of the image.
You can use the values that I provide ($slope = 2500; $icpt = 6000), or you can calculate your own. I thought of automating the process a little more, but since the parameters are highly subjective, it didn't seem very practical. In order to calculate them, it's necessary to define areas for two different instances of the aspect ratios, where the ratio is $width/$height. For example, when the ratio is 1 ($width = $height), you might want the area to be 8000 pixels^2, and when the ratio is 2 ($width = 2*$height) the area could be 12000 pixels^2. With these values we have:
$A1 = 8000;
$A2 = 12000;
$r1 = 1;
$r2 = 2;
You can calculate slope and intercept as follows:
$slope = ($A2 - $A1)/($r2 - $r1);
$icpt = $A1 - $slope*$r1;