I am trying to get the aspect ratio of a photo but the following code shows wrong aspect ratio on a photo with 3776 in width and 2520 in height (472:315) but it shows correct aspect ratio on a photo with 3968 in width and 2232 in height though (16:9).
function gcd($a, $b) { if($a == 0 || $b == 0) { return abs(max(abs($a), abs($b))); } $r = $a % $b; return ($r != 0) ? gcd($b, $r) : abs($b); } $gcd = gcd($widtho, $heighto); echo ($widtho / $gcd).':'.($heighto / $gcd);
How can I solve my problem?
Thanks in advance.
Advertisement
Answer
Actually, 3780×2520 is an aspect ratio of 3:2; because you’re using 3776 for the width, 472:315 is the correct ratio. If you do the division, it comes out to 1.498, which is pretty close-enough to 1.5 to consider rounding to 3:2.
If you want only “standard” ratios (like “3:2” or “16:9”), you could pass the detected ratio to another function that rounds them to find the nearest/best-match instead.
This is a thrown-together function that can do the rounding for you (only tested against the dimensions in your example, so I can’t guarantee 100% success yet):
function findBestMatch($ratio) { $commonRatios = array( array(1, '1:1'), array((4 / 3), '4:3'), array((3 / 2), '3:2'), array((5 / 3), '5:3'), array((16 / 9), '16:9'), array(3, '3') ); list($numerator, $denominator) = explode(':', $ratio); $value = $numerator / $denominator; $end = (count($commonRatios) - 1); for ($i = 0; $i < $end; $i++) { if ($value == $commonRatios[$i][0]) { // we have an equal-ratio; no need to check anything else! return $commonRatios[$i][1]; } else if ($value < $commonRatios[$i][0]) { // this can only happen if the ratio is `< 1` return $commonRatios[$i][1]; } else if (($value > $commonRatios[$i][0]) && ($value < $commonRatios[$i + 1][0])) { // the ratio is in-between the current common-ratio and the next in the list // find whichever one it's closer-to and return that one. return (($value - $commonRatios[$i][0]) < ($commonRatios[$i + 1][0] - $value)) ? $commonRatios[$i][1] : $commonRatios[$i + 1][1]; } } // we didn't find a match; that means we have a ratio higher than our biggest common one // return the original value return $ratio; }
To use this function, you pass in the ratio-string (not the numeric value) to it and it will attempt to “find a best match” in the common list of ratios.
Example usage:
$widtho = 3968; $heighto = 2232; $gcd = gcd($widtho, $heighto); $ratio = ($widtho / $gcd).':'.($heighto / $gcd); echo 'found: ' . $ratio . "n"; echo 'match: ' . findBestMatch($ratio) . "n"; $widtho = 3776; $heighto = 2520; $gcd = gcd($widtho, $heighto); $ratio = ($widtho / $gcd).':'.($heighto / $gcd); echo 'found: ' . $ratio . "n"; echo 'match: ' . findBestMatch($ratio) . "n"; $widtho = 3780; $heighto = 2520; $gcd = gcd($widtho, $heighto); $ratio = ($widtho / $gcd).':'.($heighto / $gcd); echo 'found: ' . $ratio . "n"; echo 'match: ' . findBestMatch($ratio) . "n";
The above test will output the following:
found: 16:9 match: 16:9 found: 472:315 match: 3:2 found: 3:2 match: 3:2
* I took the list of “standard” aspect ratios from wikipedia, if you want a reference.