Вычисление отношения размера изображения для изменения размера

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

Например, скажем, я определил ширину 1024px и высоту 768px . И я хочу изменить размер вертикального изображения (высота 1100 пикселей и ширина 200 пикселей) . Поэтому в моем случае он изменит размер до фиксированного размера (1024×768) , поэтому ширина будет увеличена с 100 пикселей до 768 пикселей , и это будет очень уродливо. Аналогично, если изображение имеет высоту менее 768 пикселей , оно увеличит высоту силой до 768 пикселей .

Поэтому я хотел бы рассчитать новый размер изображения на основе исходного соотношения размеров изображения. Допустим, если изображение вышеприведенного изображения должно быть изменено до максимальной высоты 768 пикселей , но тогда как насчет ширины? он уже меньше моей «максимальной ширины», то есть 200 пикселей , так что ширина останется неизменной? или он должен быть дополнительно уменьшен?

Аналогично, если изображение имеет высоту 200px и ширину 1100px . Поэтому ширина должна быть уменьшена до 1024 пикселей , но как насчет высоты?

Третья проблема заключается в том, что предположим, что и высота, и ширина больше максимальной высоты и максимальной ширины, скажем, ширина: 1100 пикселей и высота: 4000 пикселей . Теперь, поскольку ширина и высота не превышают максимальную ширину и максимальную высоту, но изображение вертикальное, оно будет горизонтальным. Итак, как я могу проверить, если в этом случае, если я должен изменить размер изображения в соответствии с максимальной высотой или в соответствии с максимальной шириной?

Я ценю любую помощь в этом.

Solutions Collecting From Web of "Вычисление отношения размера изображения для изменения размера"

Вот код из моего личного мешка для захвата кода изменения размера изображения. Во-первых, данные, которые вам нужны:

list($originalWidth, $originalHeight) = getimagesize($imageFile); $ratio = $originalWidth / $originalHeight; 

Затем этот алгоритм соответствует изображению в размере цели, насколько это возможно, сохраняя исходное соотношение сторон, а не растягивая изображение, большее, чем оригинал:

 $targetWidth = $targetHeight = min($size, max($originalWidth, $originalHeight)); if ($ratio < 1) { $targetWidth = $targetHeight * $ratio; } else { $targetHeight = $targetWidth / $ratio; } $srcWidth = $originalWidth; $srcHeight = $originalHeight; $srcX = $srcY = 0; 

Это обрезает изображение, чтобы полностью заполнить целевой размер, а не растягивать его:

 $targetWidth = $targetHeight = min($originalWidth, $originalHeight, $size); if ($ratio < 1) { $srcX = 0; $srcY = ($originalHeight / 2) - ($originalWidth / 2); $srcWidth = $srcHeight = $originalWidth; } else { $srcY = 0; $srcX = ($originalWidth / 2) - ($originalHeight / 2); $srcWidth = $srcHeight = $originalHeight; } 

И это делает фактическое изменение размера:

 $targetImage = imagecreatetruecolor($targetWidth, $targetHeight); imagecopyresampled($targetImage, $originalImage, 0, 0, $srcX, $srcY, $targetWidth, $targetHeight, $srcWidth, $srcHeight); 

В этом случае $size равен только одному числу для ширины и высоты (размер квадратного размера). Я уверен, что вы можете изменить его, чтобы использовать не-квадратные цели. Это также должно дать вам вдохновение в отношении того, какие другие алгоритмы изменения размера вы можете использовать.

 $ratio = $originalWidth / $originalHeight 

если вы хотите изменить высоту:

 $targetWidth = $targetHeight * $ratio 

если вы хотите изменить ширину:

 $targetHeight = $targetWidth / $ratio 

Вы хотите сохранить соотношение сторон исходного изображения. Это соотношение между шириной и высотой изображения. Таким образом, вы вычисляете коэффициент, с помощью которого вы должны изменить размер изображения в вертикальном и горизонтальном направлениях, а затем вы держите верхнюю из двух. В псевдокоде:

 target_height = 768 target_width = 1024 # v_fact and h_fact are the factor by which the original vertical / horizontal # image sizes should be multiplied to get the image to your target size. v_fact = target_height / im_height h_fact = target_width / im_width # you want to resize the image by the same factor in both vertical # and horizontal direction, so you need to pick the correct factor from # v_fact / h_fact so that the largest (relative to target) of the new height/width # equals the target height/width and the smallest is lower than the target. # this is the lowest of the two factors im_fact = min(v_fact, h_fact) new_height = im_height * im_fact new_width = im_width * im_fact image.resize(new_width, new_height) 

это работает.

 function calculateDimensions($width,$height,$maxwidth,$maxheight) { if($width != $height) { if($width > $height) { $t_width = $maxwidth; $t_height = (($t_width * $height)/$width); //fix height if($t_height > $maxheight) { $t_height = $maxheight; $t_width = (($width * $t_height)/$height); } } else { $t_height = $maxheight; $t_width = (($width * $t_height)/$height); //fix width if($t_width > $maxwidth) { $t_width = $maxwidth; $t_height = (($t_width * $height)/$width); } } } else $t_width = $t_height = min($maxheight,$maxwidth); return array('height'=>(int)$t_height,'width'=>(int)$t_width); } 

Проверьте код php ниже:

 $new_width = 1024; $new_height = 768; $this_image = "images/my_image"; list($width, $height, $type, $attr) = getimagesize("$this_image"); if ($width > $height) { $image_height = floor(($height/$width)*$new_width); $image_width = $new_width; } else { $image_width = floor(($width/$height)*$new_height); $image_height = $new_height; } echo "<img src='$this_image' height='$image_height' width='$image_width'>"; 

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

 if(($w - $w_max) > ($h - $h_max)) { $w_new = $w_max; $h_new = (int) ($h * ($w_max / $w)); } else { $h_new = $h_max; $w_new = (int) ($w * ($h_max / $h)); } 

Я дошел до этого вопроса и не нашел подходящего ответа, поэтому я решил самостоятельно ответить на вопрос.

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

 function calculate_dimensions($width,$height,$max){ if($width != $height){ if($width > $height){ $t_height = $max; $t_width = min(($width * $t_height)/$height); } if($height > $width){ $t_width = $max; $t_height = min(($t_width * $height)/$width) } }else{ if($width > $max){ $t_width = $t_height = $max; } } $res = ['height'=>$t_height,'width'=>$t_width] return $res; } 

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

кредит моему другу Джастину Джиллетту за его блестящее предложение о перекрестном умножении.

Этот пример уменьшит изображение, чтобы он соответствовал определенному размеру пикселя (16: 9), создав изображение размером не более указанного предела (1200 x 675).

Установите коэффициент изображения и любой верхний предел:

 const RATIO_W = 16; const RATIO_H = 9; const RATIO_MULIPLIER_UPPER_LIMIT = 75; 

Вычислите ширину и высоту нового изображения

 list($imageWidth, $imageHeight) = getimagesize($path_to_image); if( ($imageWidth / $imageHeight) === (self::RATIO_W / self::RATIO_H) ){ return; // Find closest ratio multiple to image size if($imageWidth > $imageHeight){ // landscape $ratioMultiple = round($imageHeight / self::RATIO_H, 0, PHP_ROUND_HALF_DOWN); }else{ // portrait $ratioMultiple = round($imageWidth / self::RATIO_W, 0, PHP_ROUND_HALF_DOWN); } $newWidth = $ratioMultiple * self::RATIO_W; $newHeight = $ratioMultiple * self::RATIO_H; if($newWidth > self::RATIO_W * self::RATIO_MULIPLIER_UPPER_LIMIT|| $newHeight > self::RATIO_H * self::RATIO_MULIPLIER_UPPER_LIMIT){ // File is larger than upper limit $ratioMultiple = self::RATIO_MULIPLIER_UPPER_LIMIT; } $this->tweakMultiplier($ratioMultiple, $imageWidth, $imageHeight); $newWidth = $ratioMultiple * self::RATIO_W; $newHeight = $ratioMultiple * self::RATIO_H; 

Изменить размер изображения

 $originalImage = imagecreatefromjpeg( $tempImagePath ); $newImage = imagecreatetruecolor($newWidth, $newHeight); imagefilledrectangle($newImage, 0, 0, $newWidth, $newHeight, imagecolorallocate($newImage, 255, 255, 255)); imagecopyresampled($newImage, $originalImage, 0, 0, 0, 0, $newWidth, $newHeight, $imageWidth, $imageHeight); imagejpeg($newImage, $tempImagePath, 100); 

Пропускайте коэффициенты до тех пор, пока оба измерения не будут меньше исходного размера изображения

 protected function tweakMultiplier( &$ratioMultiple, $fitInsideWidth, $fitInsideHeight ){ $newWidth = $ratioMultiple * self::RATIO_W; $newHeight = $ratioMultiple * self::RATIO_H; if($newWidth > $fitInsideWidth || $newHeight > $fitInsideHeight){ echo " Tweak "; $ratioMultiple--; $this->tweakMultiplier($ratioMultiple, $fitInsideWidth, $fitInsideHeight); }else{ return; } } 

Если максимальная высота или ширина заданы или нет, используя логику @ (jilles de wit)

соображения: они уже должны быть определены!

 $mh = given height limit; //optional $mw = given width limit; //optional $height = $nh =[your original height]; $width = $nw =[your original width]; 

Код

 if($mh || $mw){ if(is_numeric($mh)){$h_fact = $mh / $nh;} if(is_numeric($mw)){$v_fact = $mw / $nw;} if(is_numeric($v_fact) && is_numeric($h_fact) ){$im_fact = min($v_fact, $h_fact);}else{$im_fact=is_numeric($v_fact)?$v_fact:$h_fact;} $nw = $nw * $im_fact; $nh = $nh * $im_fact; } 

передискретизации

 $dst_img = imagecreatetruecolor($nw,$nh); imagecopyresampled ($dst_img, $image, 0, 0, 0, 0, $nw, $nh, $width , $height); 
 class Image_Aspect_Ratio_Resize { var $image_to_resize; var $new_width; var $new_height; var $ratio; var $new_image_name; var $save_folder; function resize() { if (!file_exists($this->image_to_resize)) { exit("File " . $this->image_to_resize . " does not exist."); } $info = GetImageSize($this->image_to_resize); if (empty($info)) { exit("The file " . $this->image_to_resize . " doesn't seem to be an image."); } $width = $info[0]; $height = $info[1]; $mime = $info['mime']; /* Keep Aspect Ratio? */ if ($this->ratio) { $thumb = ($this->new_width < $width && $this->new_height < $height) ? true : false; // Thumbnail $bigger_image = ($this->new_width > $width || $this->new_height > $height) ? true : false; // Bigger Image if ($thumb) { if ($this->new_width >= $this->new_height) { $x = ($width / $this->new_width); $this->new_height = ($height / $x); } else if ($this->new_height >= $this->new_width) { $x = ($height / $this->new_height); $this->new_width = ($width / $x); } } else if ($bigger_image) { if ($this->new_width >= $width) { $x = ($this->new_width / $width); $this->new_height = ($height * $x); } else if ($this->new_height >= $height) { $x = ($this->new_height / $height); $this->new_width = ($width * $x); } } } $type = substr(strrchr($mime, '/'), 1); switch ($type) { case 'jpeg': $image_create_func = 'ImageCreateFromJPEG'; $image_save_func = 'ImageJPEG'; $new_image_ext = 'jpg'; break; case 'png': $image_create_func = 'ImageCreateFromPNG'; $image_save_func = 'ImagePNG'; $new_image_ext = 'png'; break; case 'bmp': $image_create_func = 'ImageCreateFromBMP'; $image_save_func = 'ImageBMP'; $new_image_ext = 'bmp'; break; case 'gif': $image_create_func = 'ImageCreateFromGIF'; $image_save_func = 'ImageGIF'; $new_image_ext = 'gif'; break; case 'vnd.wap.wbmp': $image_create_func = 'ImageCreateFromWBMP'; $image_save_func = 'ImageWBMP'; $new_image_ext = 'bmp'; break; case 'xbm': $image_create_func = 'ImageCreateFromXBM'; $image_save_func = 'ImageXBM'; $new_image_ext = 'xbm'; break; default: $image_create_func = 'ImageCreateFromJPEG'; $image_save_func = 'ImageJPEG'; $new_image_ext = 'jpg'; } // New Image $image_c = ImageCreateTrueColor($this->new_width, $this->new_height); $new_image = $image_create_func($this->image_to_resize); ImageCopyResampled($image_c, $new_image, 0, 0, 0, 0, $this->new_width, $this->new_height, $width, $height); if ($this->save_folder) { if ($this->new_image_name) { $new_name = $this->new_image_name . '.' . $new_image_ext; } else { $new_name = $this->new_thumb_name(basename($this->image_to_resize)) . '_resized.' . $new_image_ext; } $save_path = $this->save_folder . $new_name; } else { /* Show the image without saving it to a folder */ header("Content-Type: " . $mime); $image_save_func($image_c); $save_path = ''; } $process = $image_save_func($image_c, $save_path); return array('result' => $process, 'new_file_path' => $save_path); }} 

/ * Функциональный вызов * /

 $resize_image = new Image_Aspect_Ratio_Resize; $new_width = (int) $_POST['new_width']; $new_height = (int) $_POST['new_height']; $resize_image->new_width = $new_width; $resize_image->new_height = $new_height; $resize_image->image_to_resize = $image; // Full Path to the file $resize_image->ratio = true; // Keep aspect ratio // Name of the new image (optional) - If it's not set a new will be added automatically $resize_image->new_image_name = 'water_lilies_thumbnail'; /* Path where the new image should be saved. If it's not set the script will output the image without saving it */ $resize_image->save_folder = 'thumbs/'; $process = $resize_image->resize(); // Output image 

Вам нужно «поддерживать» соотношение ширина / высота. Первоначально у вас есть изображение размера ( 500x1000 ) 500x1000 , это соотношение ширина / высота равно 0.5 . Предполагая, что вы меняете 1000 до 768 в высоту, ваша ширина результата будет 0.5 * 768 = 384 .

Другой пример: 1800 x 1200 а ваша новая высота – 200 , тогда ваша новая ширина 300 потому что 300/2001.5 и 1800/12001.5 .

Удачи.