2011-05-11 54 views
0

我和一所大學正試圖建立一種方法,可以找到圖像中默認顯示的選區的最大尺寸。選擇有一個比例。PHP:在尊重比例的同時找到最大的放大尺寸

到現在爲止,我們已經試過這樣:

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); 
} 

但它失敗我們的單元測試。

我們也嘗試過這樣的:

public function findBestSizeForRatio($inputW, $inputH, $ratioW, $ratioH) 
{ 
    return $this->findBestSizeInBox($ratioW*10000, $ratioH*10000, $inputW, $inputH); 
} 
public function findBestSizeInBox($inputW, $inputH, $boxW, $boxH) 
{ 
    if($inputW/$boxW > $inputH/$boxH){ 
     return array($boxW, round($inputH * $boxW/$inputW)); 
    } 
    else{ 
     return array(round($inputW * $boxH/$inputH), $boxH); 
    } 
} 

它似乎工作,但它不是像素完美。由於我們的比例是由少數人組成的,我們需要一種真正尊重比例的方法,即使圖像不是100%填充。硬編碼常數(如* 10000)也很愚蠢,因爲我們無法找出一個好的數學公式。 ;)

我們還建立這些PHPUnit測試,這似乎是代表我們(因此,我們可能會忘記某些情況下)

/** 
* @covers Img_GD::findBestSizeInBox 
*/ 
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}"); 

} 

/** 
* @covers Img_GD::findBestSizeInBox 
*/ 
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}"); 

} 

那會通過了所有測試的任何解決方案?

+0

如果您的計算精度與您有關,您可能需要查看http://php.net/manual/en/book.bc.php或http://php.net/manual/en/ book.gmp.php – Mikk 2011-05-11 23:04:40

+0

@Mikk這不是我需要精確度像浮點精度。這是我不想四捨五入。如果看看測試#4。我不想要400 x 533.333,我想要399 x 532,因爲它不可能保持400的理想寬度的比例。我只想要在我的結果中的整數,總是,而不是四捨五入。 – FMaz008 2011-05-12 00:01:30

回答

2

試試這個微妙的變化:

public function findBestSizeForRatio($inputW, $inputH, $ratioW, $ratioH) 
{ 
    if($inputW/$ratioW < $inputH/$ratioH){ 
     $w = floor($inputW/$ratioW) * $ratioW; 
     $h = $w * $ratioH/$ratioW; 
    } 
    else{ 
     $h = floor($inputH/$ratioH) * $ratioH; 
     $w = $h * $ratioW/$ratioH; 
    } 

    return array($w, $h); 
} 

我看你已經解決您的單元測試爲btilly suggested;好。

2

讓我確定我有這個權利。你想要拍攝一張圖像,並將你所能做到的最大的塊與具有指定h/w比例的矩形相匹配。

在這種情況下,請記住單元測試也是代碼的規則。當你的單元測試失敗時,甚至有可能在單元測試中出現錯誤。考慮到這一點,你的單元測試看起來是錯誤的。例如#4。 533/400並不是完全4/3的比例。具有該確切比例的最佳答案是532/399。

如果你願意放寬比例的正確性,那麼你應該這樣做:

public function findBestSizeForRatio($inputW, $inputH, $ratioW, $ratioH) 
{ 
    if($inputW/$ratioW > $ratioH/$inputH){ 
     $w = $inputW; 
     $h = round($w * $ratioH/$ratioW); 
    } 
    else{ 
     $h = $inputH; 
     $h = round($h * $ratioW/$ratioH); 
    } 

    return array($w, $h); 
} 
+0

你已經正確地理解了這個問題。但是,不,我不想放鬆。正如你所注意到的,我已經有了這種方法(它運行良好)。你說得對,第四次測試是錯誤的,正如你指出的那樣,預期的結果應該是532/399。我將編輯帖子。 – FMaz008 2011-05-11 23:54:34

+0

@ FMaz008:啊。在這種情況下,'$ w = $ inputW - ($ inputW%$ ratioW)'然後是'$ h = $ w * $ ratioH/$ ratioW'。這假設'$ ratioW'和'$ ratioH'是相對主要的。如果你不能這樣認爲,通過將它們除以gcd很容易保證它。在http://php.net/manual/en/ref.math.php中搜索「gcd」以查找其示例實現。 – btilly 2011-05-12 00:25:58

+0

@btilly不是$ w = $ inputW - ($ inputW%$ ratioW)和$ w = floor($ inputW/$ ratioW)* $ ratioW;回報幾乎相同?我沒有看到太大的區別...是的,我確實認爲比例會降低(40/30總是4/3) – FMaz008 2011-05-12 00:33:25