<?php

class Image {

    public static function getRatio($file) {
	list($width, $height, $type, $attr) = getimagesize($_SERVER['DOCUMENT_ROOT'] . $file);
	if (function_exists("gmp_gcd")) {
	    $gcd = gmp_gcd($width, $height);
	    $ratio = ($width / $gcd) . ':' . ($height / $gcd);
	    $array = array('16:9', '4:3', '3:2', '7:5', '10:8');

	    if (in_array($ratio, $array)) {
		return $ratio;
	    } else {
		return "Onbekend";
	    }
	} else {
	    return "n/a";
	}
    }

}
?>

Vanavond een prachtige class gebouwd.
Echter blijkt gmp_gcd() niet overal te werken, omdat het niet altijd geïnstalleerd is.
Dat kan ik uiteraard wel doen, maar zijn er nog andere truukjes om de verhouding te achterhalen aan de hand van de ingevoerde dimensies?
Die gebruik ik al om van de bron-afbeelding de dimensies op te halen.
Maar hoe kom ik dan zonder de GMP-functies achter de verhouding, zoals 16:9, 4:3 etc...?
Is dat niet een kwestie van uitrekenen?

Je weet de width en de height.

Om te bepalen of de ratio 16:9 is, moet de verhouding 16/9 zijn. Dat zou je als volgt kunnen testen:

width * (9/16) = height

En dan zou ik bij de controle een marge aanhouden van een paar (bijv. 3) pixels voor als de hoogte net een paar pixels te groot of klein is, bijv. als gevolg van onsecuur uitsnijden of het verspringen van een pixel bij het schalen van de afbeelding.
Ja, jouw berekening klopt, maar zowel de lengte als de breedtte weet ik al.

In jouw berekening weet je de ratio 16:9 al, maar die wil ik juist bepalen aan de hand van de afmetingen.
<?php

/**
 * Calculate the ratio between two numbers.
 * 
 * @param int $num1 The first number.
 * @param int $num2 The second number.
 * @return string A string containing the ratio.
 */
function getRatio( $num1, $num2 )
{
	for($i = $num2; $i > 1; $i--)
	{
		if(($num1 % $i) == 0 && ($num2 % $i) == 0)
		{
			$num1 = $num1 / $i;
			$num2 = $num2 / $i;
		}
	}
	$ratio = "$num1:$num2";
	$array = array('16:9', '4:3', '3:2', '7:5', '10:8', '1:5');
	if (in_array($ratio, $array))
	{
		return $ratio;
	} else {
		return "Onbekend";
		//return "$num1:$num2";
	}
}

list($width, $height, $type, $attr) = getimagesize($_SERVER['DOCUMENT_ROOT'] . $file);

echo getRatio( $width, $height ), '<br>';

//Example returns 1:5
echo getRatio( 2, 10 ), '<br>';

?>


Kwam het hier tegen :

https://thisinterestsme.com/php-calculate-ratio/
@Adoptive Solutuon: Thanks!
@Ward: De link tussen 1:1 en SEO ontgaat mij eventjes. Kan je dit uitleggen? :-)
Voor bijvoorbeeld afbeeldingen bij een artikel ziet Google het liefst de drie verhoudingen 16:9, 4:3 én 1:1:

For best results, provide multiple high-resolution images (minimum of 800,000 pixels when multiplying width and height) with the following aspect ratios: 16x9, 4x3, and 1x1.


https://developers.google.com/search/docs/data-types/article

Een vergelijkbare eis geldt voor onder andere foto's voor productpagina's en recepten:

https://developers.google.com/search/docs/data-types/product

https://developers.google.com/search/docs/data-types/recipe

Verder moet een bedrijfslogo minimaal 112 × 112 pixels groot zijn:

https://developers.google.com/search/docs/data-types/logo

Als je aan de slag gaat met beeldratio's (en schalen of bijsnijden) is het wel zo handig meteen de functionele eisen voor Google mee te nemen.
- Ariën - op 11/10/2019 23:47:11
maar zijn er nog andere truukjes om de verhouding te achterhalen aan de hand van de ingevoerde dimensies?

Nou, de eerste user comment op de documentatiepagina van gmp_gcd() geeft een zeer nette recursieve implementatie:
<?php
function gcd($a, $b) {
    return ($a % $b) ? gcd($b, $a % $b) : $b;
}
?>

Voor de goede orde zou je misschien ook rekening moeten houden met staande afbeeldingen (portretten). Dus of je voegt ook de ratio's 9:16 et cetera toe, maar dat is een beetje dubbel, of je kijkt gewoon naar de langste zijde en de kortere zijde, ongeacht of dit een breedte of hoogte is. Het gaat (waarschijnlijk?) per slot van rekening om de ratio. Misschien wil je dan wel ergens een soort van "portrait flag" (true of false) bijhouden.

Nog wat wiskundige achtergrond:
Elk getal is te schrijven als een product van priemgetallen (het bewijs hiervoor laat ik even achterwege :p).

Bijvoorbeeld 1024 is 2^10 en 768 is 2^8 * 3^1. Dit wordt ook wel de priemfactorisatie genoemd.

Het verband met gcd (greatest common divisor, grootste gemene deler) en ook de lcm (least common multiple, kleinste gemene veelvoud) is als volgt: bij de priemfactorisatie kun je altijd vermenigvuldigen met 1. Dit verandert niets aan het resultaat: 2^10 * 1 * 1 * 1 is nog steeds 1024. 1024 kun je dus bijvoorbeeld ook schrijven als 2^10 * 3^0.

Als je van twee getallen de gcd wilt bepalen dan is dat het minimum van alle product-machten van de priemfactorisatie. Dat lijkt een mond vol, maar dit is toch redelijk simpel:
1024 = 2^10 * 3^0
 768 = 2^ 8 * 3^1
----------------- GCD (min)
 256 = 2^ 8 * 3^0

De kleinste factor van het priemgetal 2 is 8. De kleiste factor van het priemgetal 3 is 0. De grootste gemene deler van 1024 en 768 is dus 256 (2^8 * 3^0).

Het complement hiervan (lcm) is, je raadt het misschien al, het maximum van alle product-machten van de priemfactorisatie:
1024 = 2^10 * 3^0
 768 = 2^ 8 * 3^1
----------------- LCM (max)
3072 = 2^10 * 3^1

3072 is daarmee het kleinste gemene veelvoud van 1024 en 768.
Bedankt voor de uitgebreide uitleg Thomas.
Mijn hogere wiskunde is een beetje roestig, maar ik zal het op mijn gemak even doorlezen.

Ik ga er niet echt veel actiefs mee doen, maar ik vind het wel een handig idee om de verhoudingen als eigenschap bij de foto's in mijn fotoarchief in mijn CMS te tonen. Dan kan je prima zien welke formaten prima in de ankeilers van mijn site zullen passen. Uiteraard zal ik andere formaten visueel netjes croppen, maar als ze netjes passen op 4:3, dan is het helemaal prima zonder enig beeldverlies.

Reageren