Найти максимальный масштабированный размер при соблюдении соотношения - PullRequest
0 голосов
/ 12 мая 2011

Я и колледж пытаемся создать метод, который может найти самый большой размер для выбора, отображаемого по умолчанию на изображении. Выбор имеет соотношение.

До сих пор мы пробовали это:

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

}

Любое решение, которое прошло бы все испытания?

Ответы [ 2 ]

2 голосов
/ 12 мая 2011

Попробуйте это одно тонкое изменение:

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

Я вижу, вы уже исправили свои юнит-тесты как , предложенные Биллили ;хорошо.

2 голосов
/ 12 мая 2011

Позвольте мне быть уверенным, что у меня есть это право. Вы хотите сделать снимок и взять самый большой фрагмент, который вы можете, который представляет собой прямоугольник с точно заданным соотношением ч / б.

В этом случае помните правило, что модульные тесты также являются кодом. Когда вы проваливаете свой модульный тест, есть вероятность, что ошибка в модульном тесте. Имея это в виду, ваши юнит-тесты выглядят неправильно. Например, возьмите № 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...