Précédent   Forum des professionnels en informatique > PHP > Langage
Langage Forum sur le langage PHP, la POO, les conventions, la sécurité, etc. Avant de poster : FAQ Langage, toutes les FAQ PHP, cours langage et sources PHP
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/05/2011, 02h21   #1
Membre expérimenté
 
Avatar de FMaz
 
Inscription : mars 2005
Messages : 648
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 648
Points : 527
Points : 527
Par défaut Trouver la taille maximale d'une sélection avec ratio dans une image.

Bonjour à tous,

J'ai un petit puzzle de logique, qui pour une raison obscure me pose actuellement problème.

J'ai un système de Crop et je veux définir la taille maximale possible de la sélection par défaut.

Explication des données d'entrée

Je défini un ratio qui peut être n'importe quoi, du moment que c'est une fraction réduite. Par exemple 4/3.

Je passe une taille d'image, qui peut vraiment être n'importe quoi, et qui ne respecte aucun ratio précis. Par exemple 2000x62.

J'ai donc 4 valeurs:
Code :
1
2
3
4
5
 
$ratioW = 4;
$ratioH = 3;
$imageW = 2000;
$imageH = 62;
Explication des données de sortie

En sortie, je désire obtenir 2 entiers non arrondi, qui respectent le ratio initial.

Pour l'exemple que j'ai donné, les résultats seraient:
Code :
1
2
3
 
$outW = 80;
$outH  = 60;
Tentative actuelle

Jusqu'ici, j'en suis venu à la fonction suivante (qui ne fonctionne pas). Sous toute réserve, les formules me semblent bonnes, cependant la condition ne semble pas arriver à bien aiguiller l'exécution vers les bonnes formules.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
public function findBestSizeForRatio($inputW, $inputH, $ratioW, $ratioH)
{
    if($inputW / $ratioW > $ratioH / $inputH){
        $w = floor($inputW / $ratioW) * $ratioW;
        $h = $w * $ratioH / $ratioW;
    }
    else{
        $h = floor($inputH / $ratioH) * $ratioH;
        $w = $h * $ratioW / $ratioH;
    }
 
    return array($w, $h);
}
Test unitaires

Pour ceux que ca pourrait aider, j'ai rédigé quelques test unitaires:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 
public function testfindBestSizeForRatioReturnValidValueForEasyInput()
{
 
    $img = new Img_GD();
 
    //1
    $iW = 400; $iH = 300; //Input image size
    $rW =   4; $rH =   3; //ratio
    $eW = 400; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //2
    $iW = 400; $iH = 3000; //Input image size
    $rW =   4; $rH =   3; //ratio
    $eW = 400; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //3
    $iW = 4000; $iH = 300; //Input image size
    $rW =   4; $rH =   3; //ratio.
    $eW = 400; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //4
    $iW = 400; $iH = 3000; //Input image size
    $rW =   3; $rH =   4; //ratio
    $eW = 399; $eH = 532; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //5
    $iW = 4000; $iH = 300; //Input image size
    $rW =   3; $rH =   4; //ratio.
    $eW = 225; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //6
    $iW = 4000; $iH = 300; //Input image size
    $rW =   3; $rH =   4; //ratio.
    $eW = 225; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
}
 
public function testfindBestSizeForRatioReturnValidValueForNonExactInput()
{
    $img = new Img_GD();
 
    //7
    $iW = 403; $iH = 302; //Input image size
    $rW =   4; $rH =   3; //ratio
    $eW = 400; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //8
    $iW = 403; $iH = 3000; //Input image size
    $rW =   4; $rH =   3; //ratio
    $eW = 400; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //9
    $iW = 4000; $iH = 302; //Input image size
    $rW =   4; $rH =   3; //ratio.
    $eW = 400; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //10
    $iW = 403; $iH = 3000; //Input image size
    $rW =   3; $rH =   4; //ratio
    $eW = 402; $eH = 536; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //11
    $iW = 4000; $iH = 302; //Input image size
    $rW =   3; $rH =   4; //ratio.
    $eW = 225; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
    //12
    $iW = 4000; $iH = 302; //Input image size
    $rW =   3; $rH =   4; //ratio.
    $eW = 225; $eH = 300; //Expected
    $this->assertEquals(array($eW, $eH), $img->findBestSizeForRatio($iW, $iH, $rW, $rH), "Img: {$iW} x {$iH} Ratio: {$rW} x {$rH}");
 
}
FMaz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2011, 03h08   #2
Expert Confirmé
 
Avatar de Séb.
 
Inscription : mars 2005
Messages : 2 823
Détails du profil
Informations personnelles :
Âge : 34
Localisation : France

Informations professionnelles :
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : mars 2005
Messages : 2 823
Points : 3 449
Points : 3 449
Ceci répond à tes assertions (exceptée la 10e mais le résultat attendu me semble erroné) :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$width = 4000 ;
$height = 302 ;
 
$ratio_width = 3 ;
$ratio_height = 4 ;
 
if ( $width < $height ) {
    $ratio = floor($width / $ratio_width) ;
} else {
    $ratio = floor($height / $ratio_height) ;
}
 
$crop_width = $ratio_width * $ratio ;
$crop_height = $ratio_height * $ratio ;
 
echo "{$width}x{$height} => $ratio_width/$ratio_height => {$crop_width}x{$crop_height}" ;
// 4000x302 => 3/4 => 225x300
Est-ce que ça t'a l'air bon ?
__________________
Un problème exposé clairement est déjà à moitié résolu
Keep It Smart and Simple
Séb. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2011, 03h42   #3
Membre expérimenté
 
Avatar de FMaz
 
Inscription : mars 2005
Messages : 648
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 648
Points : 527
Points : 527
Effectivement, le 10eme test était en erreur. J'ai édité.

Je vais essayé la logique que tu propose demain, soit:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
 
public function findBestSizeForRatio($inputW, $inputH, $ratioW, $ratioH)
{
    if ( $inputW < $inputH ) {
        $ratio = floor($inputW / $ratioW) ;
    } else {
        $ratio = floor($inputH / $ratioH) ;
    }
    $w = $ratioW * $ratio ;
    $w = $ratioH * $ratio ;
 
    return array($w, $h);
}

Je me demande cependant si le test simple des dimensions de l'image sera suffisant pour les cas ou le ratio ne serait pas 4:3... Enfin, l'écriture de quelques tests supplémentaires le dira assez rapidement !

Je met à jour dès que j'aurais testé demain
FMaz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2011, 01h07   #4
Membre expérimenté
 
Avatar de FMaz
 
Inscription : mars 2005
Messages : 648
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 648
Points : 527
Points : 527
Je confirme que la méthode proposée fonctionne. Merci !
Cependant, --double bonne nouvelle-- j'ai aussi réussit à débogger le mienne:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public function findBestSizeForRatio($inputW, $inputH, $ratioW, $ratioH)
    {
 
        if($inputW / $ratioW < $inputH / $ratioH ){
            $w = floor($inputW / $ratioW) * $ratioW;
            $h = $w / $ratioW * $ratioH;
        }
        else{
            $h = floor($inputH / $ratioH) * $ratioH;
            $w = $h / $ratioH * $ratioW;
        }
 
        return array($w, $h);
    }
En gros:
Code :
1
2
- if($inputW / $ratioW > $ratioH / $inputH ){
+ if($inputW / $ratioW < $inputH / $ratioH ){
FMaz est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 11h27.


 
 
 
 
Partenaires

Hébergement Web