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

<p>у меня есть определенная фиксированная ширина и высота, чтобы изменить размер изображения. тем не менее, у меня есть проблема с этим, потому что изображение может иметь любое соотношение размеров (это может быть<strong> вертикальный </strong>или<strong> горизонтальный </strong>). в этом случае фиксированная ширина и высота вызывают проблемы. я хочу рассчитать<strong> ширину и высоту </strong>умнее.</p><p>например, допустим, я определил<strong> ширина 1024px и высота 768px </strong>. и я хочу изменить размер изображения по вертикали<strong> (высота 1100px и ширина 200px) </strong>. так что в моем случае он будет изменен до фиксированного размера<strong> (1024x768) </strong>, поэтому ширина будет увеличена с<strong> 100px до 768px </strong>, и это будет очень некрасиво. аналогично, если изображение имеет высоту меньше<strong> 768px </strong>, оно увеличит высоту силой до<strong> 768px </strong>.</p><p>поэтому я хотел бы рассчитать новый размер изображения на основе исходного размера изображения. скажем, если размер приведенного выше примера должен быть изменен до максимальной высоты<strong> 768px </strong>, но как насчет ширины? это уже меньше моей "максимальной ширины", которая равна<strong> 200px </strong>, поэтому ширина должна оставаться неизменной? или это должно быть далее уменьшено?</p><p>аналогично, если изображение имеет<strong> высоту 200px, а ширину 1100px </strong>. таким образом, ширина должна быть<strong> уменьшена до 1024px </strong>, но как насчет высоты?</p><p>третья проблема состоит в том, что, давайте предположим, что если высота и ширина больше максимальной высоты и максимальной ширины, скажем,<strong> ширина: 1100 пикселей и высота: 4000 пикселей </strong>. теперь, когда ширина и высота больше максимальной ширины и максимальной высоты, но изображение вертикальное, оно будет горизонтальным. так как же я могу проверить, нужно ли в этом случае изменять размер изображения в соответствии с максимальной высотой или максимальной шириной?</p><p>я ценю любую помощь с этим.</p>

<p>вот код из моей личной сумки с кодом изменения размера изображения. сначала данные, которые вам нужны:</p><pre><code>list($originalwidth, $originalheight) = getimagesize($imagefile); $ratio = $originalwidth / $originalheight; </code></pre><p>затем этот алгоритм наилучшим образом вписывает изображение в целевой размер, сохраняя исходное соотношение сторон, не растягивая изображение больше исходного:</p><pre><code>$targetwidth = $targetheight = min($size, max($originalwidth, $originalheight)); if ($ratio < 1) { $targetwidth = $targetheight * $ratio; } else { $targetheight = $targetwidth / $ratio; } $srcwidth = $originalwidth; $srcheight = $originalheight; $srcx = $srcy = 0; </code></pre><p>это обрезает изображение, чтобы полностью заполнить целевой размер, не растягивая его:</p><pre><code>$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; } </code></pre><p>и это делает фактическое изменение размера:</p><pre><code>$targetimage = imagecreatetruecolor($targetwidth, $targetheight); imagecopyresampled($targetimage, $originalimage, 0, 0, $srcx, $srcy, $targetwidth, $targetheight, $srcwidth, $srcheight); в этом случае $size</code> - это просто одно число для ширины и высоты (квадратный размер цели). я уверен, что вы можете изменить его, чтобы использовать не квадратные цели. он также должен вдохновить вас на то, какие другие алгоритмы изменения размера вы можете использовать.</p>

<pre><code>$ratio = $originalwidth / $originalheight если вы хотите изменить высоту:$targetwidth = $targetheight  $ratio </code></pre><p>если вы хотите изменить ширину:</p><pre><code>$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'>"; </code></pre>

<p>что вам нужно, так это «поддерживать» соотношение ширины и высоты. изначально у вас есть изображение размером (wxh) <code>500x1000</code>, это соотношение ширины и высоты <code>0.5</code>. предполагая, что вы меняете <code>1000</code> на <code>768</code> по высоте, ваша ширина результата будет <code>0.5 * 768 = 384</code>. </p><p>другой пример: <code>1800 x 1200</code> и ваш<em> новый </em>height равен <code>200</code>, тогда ваш<em> новый </em>width равен <code>300</code>, поскольку <code>300/200</code> равен <code>1.5</code>, а <code>1800/1200</code> также <code>1.5</code>.</p><p>удачи.</p>

<p>как насчет этого:</p><pre><code>double ratio = imagewidth/imageheight; int newheight = math.min(displayheight, displaywidth / ratio); int newwidth = math.min(displaywidth, displayheight * ratio); </code></pre>

<p>если указана максимальная высота или ширина или нет, используется логика @ (jilles de wit)</p><p><strong> соображения: они уже должны быть определены! </strong></p><pre><code>$mh = given height limit; //optional $mw = given width limit; //optional $height = $nh =[your original height]; $width = $nw =[your original width]; </code></pre><p>код</p><pre><code>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; } <strong> повторная выборка </strong>$dst\_img = imagecreatetruecolor($nw,$nh); imagecopyresampled ($dst_img, $image, 0, 0, 0, 0, $nw, $nh, $width , $height); </code></pre>

<p>вы должны изменить его размер в зависимости от того, какое свойство находится дальше от максимального значения. затем рассчитайте соотношение.</p><pre><code>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)); } </code></pre>

<pre><code>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 

я дошел до этого вопроса и не нашел подходящего ответа, поэтому я сам решил ответить на вопрос.я начал с некоторой базовой логики, и после консультации с моим другом, который немного лучше в математике, это то, что мы придумали.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; } этот фрагмент кода можно использовать многократно, так что вырубитесь. просто передайте ему максимально допустимый наименьший размер, и он рассчитает наибольший размер стороны, так что вы получите обратно правильно масштабированное измерение, в котором вы можете затем центрировать обрезку, что приведет к правильно уменьшенному и обрезанному квадратному изображению изображения. это полезно для таких вещей, как изображения профиля и миниатюры.благодарность моему другу <a href="https://stackoverflow.com/users/3991729/justin">джастину джиллетту за его блестящее предложение перекрестного умножения. 

в этом примере изображение будет уменьшено до соответствия идеальному соотношению сторон изображения (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); </code></pre><p>проходите по коэффициентам, пока оба размера не станут меньше исходного размера изображения</p><pre><code>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; } } </code></pre>