Измените размер изображения без искажения, сохраняя пропорции, а затем избыток урожая с помощью WideImage

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

То, что я хочу сделать, это взять изображение (в этом примере 1000px x 800px и изменить его размер до 200px x 150px . Очевидно, что с этим существует разница в соотношении сторон.

Я хочу изменить размер исходного изображения без искажений, что в данном случае приведет к 200px x 160px изображения 200px x 160px . То, что я тогда хочу сделать, – обрезать любой избыток с краев, чтобы получить правильный размер изображения. Таким образом, в этом случае урожай 5px сверху и снизу изображения, наконец, создает 200px x 150px .

В настоящее время я имею библиотеку WideImage и хотел бы использовать ее. Я видел несколько подобных вопросов о SO, но ничего, что я могу сказать, точно делает, как я пытаюсь достичь.

    Related of "Измените размер изображения без искажения, сохраняя пропорции, а затем избыток урожая с помощью WideImage"

    Вы можете попробовать:

     $img->resize(200, 150, 'outside')->crop('center', 'middle', 200, 150); 

    Некоторые пользователи публикуют свои версии вычислений … Вот моя версия:

     $sourceWidth = 1000; $sourceHeight = 250; $targetWidth = 200; $targetHeight = 150; $sourceRatio = $sourceWidth / $sourceHeight; $targetRatio = $targetWidth / $targetHeight; if ( $sourceRatio < $targetRatio ) { $scale = $sourceWidth / $targetWidth; } else { $scale = $sourceHeight / $targetHeight; } $resizeWidth = (int)($sourceWidth / $scale); $resizeHeight = (int)($sourceHeight / $scale); $cropLeft = (int)(($resizeWidth - $targetWidth) / 2); $cropTop = (int)(($resizeHeight - $targetHeight) / 2); var_dump($resizeWidth, $resizeHeight, $cropLeft, $cropTop); 

    Я пробовал все ваши решения и каждый раз придумывал странные цифры. Итак, это мой способ делать вычисления.

    Основная пропорциональная формула: a / b = x / y -> ay = bx, затем решите для неизвестного значения. Итак, давайте поместим это в код.

    Эта функция предполагает, что вы открыли изображение в переменную. Если вы пройдете путь, вам нужно будет открыть изображение в функции, выполнить математику, убить ее, вернуть значения, а затем снова открыть изображение, когда вы измените его размер, это неэффективно …

     function resize_values($image){ #for the purpose of this example, we'll set this here #to make this function more powerful, i'd pass these #to the function on the fly $maxWidth = 200; $maxHeight = 200; #get the size of the image you're resizing. $origHeight = imagesy($image); $origWidth = imagesx($image); #check for longest side, we'll be seeing that to the max value above if($origHeight > $origWidth){ #if height is more than width $newWidth = ($maxHeight * $origWidth) / $origHeight; $retval = array(width => $newWidth, height => $maxHeight); }else{ $newHeight= ($maxWidth * $origHeight) / $origWidth; $retval = array(width => $maxWidth, height => $newHeight); } return $retval; } 

    Выше функция возвращает массив, очевидно. Вы можете использовать формулу в любом скрипте, над которым работаете. Это оказалось правильной формулой для работы. Итак … до вас, используете ли вы его или нет. ПОЗЖЕ!

    Ответ №1 (отредактирован)

    Посмотрев на это , вы, вероятно, должны сделать что-то вроде этого:

     $img->resize(200, 150, 'outside')->crop("center", "center", 200, 150); 

    При изменении размера он изменит размер изображения так, чтобы он либо точно помещался в поле (box = 200×150), либо одно из размеров соответствовало, в то время как другое превысило поле. Во время обрезки часть изображения, которая выходит за пределы коробки, будет обрезана. Указание center интеллектуальной координаты означает, что верхняя + нижняя или левая + правая часть будет удалена.

    Ответ №2

    Если у вас возникли проблемы при вычислении урожая, попробуйте следующее:

     <?php $target_wide = 200; $target_tall = 150; $test_case = array( array(1000, 800), array(800, 1000), array(1000, 750), // perfect fit array(750, 1000) ); foreach($test_case as $test) { list( $source_wide, $source_tall ) = $test; $source_aspect_ratio = $source_wide / $source_tall; $target_aspect_ratio = $target_wide / $target_tall; if ($source_aspect_ratio > $target_aspect_ratio) { $output_tall = $target_tall; $output_wide = (int) ($target_tall * $source_aspect_ratio); } else { $output_wide = $target_wide; $output_tall = (int) ($target_wide / $source_aspect_ratio); } $output_crop_hori = (int) (($output_wide - $target_wide) / 2); $output_crop_vert = (int) (($output_tall - $target_tall) / 2); var_dump($source_wide, $source_tall, $output_wide, $output_tall, $output_crop_hori, $output_crop_vert); echo PHP_EOL; } 

    Вывод:

     int(1000) int(800) int(200) int(160) int(0) int(5) int(800) int(1000) int(200) int(250) int(0) int(50) int(1000) int(750) int(200) int(150) int(0) int(0) int(750) int(1000) int(200) int(266) int(0) int(58) 
     //Following code for keeping aspect ratio $srcWidth=1000; $srcHeight=800; $targetWidth=200; $targetHeight=150; $diff=0; //get difference if( $srcWidth > $srcHeight ) // 1000 > 800 { $diff = $srcWidth - $srcHeight; // 1000 - 800 = 200 $diff = ($diff / $srcWidth) * 100; // ( 200 / 1000 ) * 100 = 20 } else { $diff = $srcHeight - $srcWidth; $diff = ($diff / $srcHeight)*100; } if( $targetWidth > $targetHeight) { $targetHeight = (( $targetHeight * $diff ) / 100) - $targetWidth; // (( 200 * 20 ) / 100) - 200 = 160 } else { $targetWidth = (( $targetWidth * $diff ) / 100) - $targetHeight; } 

    Вот как вы можете рассчитать размер урожая:

     $src_width = 1000; $src_height = 500; $src_ratio = $src_width/$src_height; $width = 200; $height = 150; $ratio = $width/$height; $crop_height = 0; $crop_width = 0; if ($src_height > $src_width) { $new_height = $width/$src_ratio; $crop_height = $new_height-$height; } else { $new_width = $height*$src_ratio; $crop_width = $new_width-$width; } print 'Crop height: '.$crop_height.PHP_EOL .'Crop width: '.$crop_width;