Измените размер изображения без искажения, сохраняя пропорции, а затем избыток урожая с помощью WideImage
У меня есть область на сайте, над которой я работаю, будет отображаться образ профиля пользователя, который вытягивается из внешнего источника (поэтому не имеет никакого контроля над его исходным размером).
Я хочу сделать изображение (в этом примере 1000px x 800px
и изменить его размер на 200px x 150px
). Очевидно, что существует разница в соотношении сторон.
Я хочу изменить размер исходного изображения без искажений, что в данном случае приведет к созданию образа 200px x 160px
. То, что я тогда хочу сделать, - обрезать любой избыток с краев, чтобы получить правильный размер изображения. Поэтому в этом случае растение 5px
сверху и снизу изображения, наконец, произведет 200px x 150px
.
В настоящее время я располагаю библиотекой WideImage и хотел бы использовать ее. Я видел несколько подобных вопросов о SO, но ничего, что я могу сказать, точно делает, как я пытаюсь достичь.
Ответы
Ответ 1
Вы можете попробовать:
$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);
Ответ 2
Я пробовал все ваши решения и каждый раз придумывал странные цифры. Итак, это мой способ делать вычисления.
Базовая пропорциональная формула: 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;
}
Выше функция возвращает массив, очевидно. Вы можете использовать формулу в любом script, над которым работаете. Это оказалось правильной формулой для работы. Итак... до вас, используете ли вы его или нет. ПОЗЖЕ!
Ответ 3
Ответ # 1 (отредактирован)
После просмотра этого и this, вам, вероятно, нужно сделать что-то вроде этого:
$img->resize(200, 150, 'outside')->crop("center", "center", 200, 150);
При изменении размера оно изменит размер изображения так, чтобы оно либо соответствовало точно в рамке (box = 200x150), либо одно из размеров приспосабливалось, а другое превысило значение поля. Во время обрезки часть изображения, которая выходит за пределы коробки, будет обрезана. Задание умной координаты 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)
Ответ 4
//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;
}
Ответ 5
Как вы можете рассчитать размер урожая:
$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;