Изменение размера / обрезка / наложение изображения на фиксированный размер

Мне нужно изменить размер изображения до фиксированного размера. Но он должен поддерживать факторы между шириной и высотой.

Скажем, я хочу изменить размер изображения с 238 (w) X 182 (h) до 210 / 150

Что я сейчас делаю:

 Original width / target width = 1.333333 Original Height / target Height = 1.213333 

Теперь я беру наименьший фактор.

Теперь у меня всегда есть правая ширина с 238 / 1.333333 = 210 . Но высота еще 160 .

Как получить высоту до 160 не разрушая рис?

Нужно ли обрезать? Если да, то как?

Это решение в основном такое же, как Can Berk Güder, но после того, как я потратил некоторое время на то, чтобы писать и комментировать, мне нравилось размещать сообщения.

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

 function thumbnail_box($img, $box_w, $box_h) { //create the image, of the required size $new = imagecreatetruecolor($box_w, $box_h); if($new === false) { //creation failed -- probably not enough memory return null; } //Fill the image with a light grey color //(this will be visible in the padding around the image, //if the aspect ratios of the image and the thumbnail do not match) //Replace this with any color you want, or comment it out for black. //I used grey for testing =) $fill = imagecolorallocate($new, 200, 200, 205); imagefill($new, 0, 0, $fill); //compute resize ratio $hratio = $box_h / imagesy($img); $wratio = $box_w / imagesx($img); $ratio = min($hratio, $wratio); //if the source is smaller than the thumbnail size, //don't resize -- add a margin instead //(that is, dont magnify images) if($ratio > 1.0) $ratio = 1.0; //compute sizes $sy = floor(imagesy($img) * $ratio); $sx = floor(imagesx($img) * $ratio); //compute margins //Using these margins centers the image in the thumbnail. //If you always want the image to the top left, //set both of these to 0 $m_y = floor(($box_h - $sy) / 2); $m_x = floor(($box_w - $sx) / 2); //Copy the image data, and resample // //If you want a fast and ugly thumbnail, //replace imagecopyresampled with imagecopyresized if(!imagecopyresampled($new, $img, $m_x, $m_y, //dest x, y (margins) 0, 0, //src x, y (0,0 means top left) $sx, $sy,//dest w, h (resample to this size (computed above) imagesx($img), imagesy($img)) //src w, h (the full size of the original) ) { //copy failed imagedestroy($new); return null; } //copy successful return $new; } 

Пример использования:

 $i = imagecreatefromjpeg("img.jpg"); $thumb = thumbnail_box($i, 210, 150); imagedestroy($i); if(is_null($thumb)) { /* image creation or copying failed */ header('HTTP/1.1 500 Internal Server Error'); exit(); } header('Content-Type: image/jpeg'); imagejpeg($thumb); 

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

 $w = 210; $h = 150; $orig_w = imagesx($original); $orig_h = imagesy($original); $w_ratio = $orig_w / $w; $h_ratio = $orig_h / $h; $ratio = $w_ratio > $h_ratio ? $w_ratio : $h_ratio; $dst_w = $orig_w / $ratio; $dst_h = $orig_h / $ratio; $dst_x = ($w - $dst_w) / 2; $dst_y = ($h - $dst_h) / 2; $thumbnail = imagecreatetruecolor($w, $h); imagecopyresampled($thumbnail, $original, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $orig_w, $orig_h); 

У вас есть Imagick ? Если это так, вы можете загрузить изображение с ним и сделать что-то вроде thumbnailimage()

Там вы можете пропустить любой из параметров (высота или ширина), и он будет правильно изменен.

Возможно, посмотрите на PHPThumb (он работает с GD и ImageMagick)

Просто подсказка для высококачественной генерации быстрых миниатюр из больших изображений: ( с сайта php.net )

Если вы создадите миниатюру в два этапа:

  1. От исходного до промежуточного изображения с удвоенными конечными размерами, используя быстрое изменение размера
  2. От промежуточного изображения до финального эскиза с использованием высококачественного повторного образца

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

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

Изменение размера изображений с веб-страницы, основанной на PHP, может быть проблематичным. Большие изображения (приближающиеся к 2 + МБ на диске) могут быть настолько большими, что им требуется более 32 МБ памяти для обработки.

По этой причине я, как правило, делаю это из сценария на основе CLI, доступного для него до 128 МБ или стандартной командной строки, которая также использует столько, сколько ему нужно.

 # where to put the original file/image. It gets resized back # it was originally found (current directory) SAFE=/home/website/PHOTOS/originals # no more than 640x640 when finished, and always proportional MAXSIZE=640 # the larger image is in /home/website/PHOTOS/, moved to .../originals # and the resized image back to the parent dir. cd $SAFE/.. && mv "$1" "$SAFE/$1" && \ convert "$SAFE/$1" -resize $MAXSIZE\x$MAXSIZE\> "$1" 

«convert» является частью инструментов командной строки ImageMagick.

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

Я думаю, что есть небольшая путаница. Если вы хотите изменить размер, сохраняя исходное соотношение, правильная операция:

 $ratio = $originalWidth / $originalHeight; if(//you start from the width, and want to find the height){ $newWidth = $x; $newHeight = $x / $ratio; }else if(//you start from the height, and want to find the width){ $newHeight = $x; $newWidth = $x * $ratio; } 

Иначе, если префикс newWidth и newHeight не может быть изменен, а соотношение большого пальца отличается от исходного соотношения, единственный способ – обрезать или добавить границы большого пальца.

Если вы собираетесь идти по этому пути, эта функция может вам помочь (я написал несколько лет назад через 5 минут, возможно, вам нужно некоторое улучшение .. оно работает только с jpg, например;):

  function thumb_cut($nomeimage, $source_path, $destination_path, $new_width, $new_height){ list($width, $height, $type, $attr) = getimagesize($source_path.$nomeimage); if($type == 2){ if($width > $new_width){ $new_width = $width; $new_height = $height; } $compression = 100; $destimg = imagecreatetruecolor($new_width,$new_height) or die("Problems creating the image"); $srcimg = ImageCreateFromJPEG($source_path.$nomeimage) or die("problem opening the image"); $w = ImageSX($srcimg); $h = ImageSY($srcimg); $ro = $new_width/$new_height; $ri = $w/$h; if($ro<$ri){ $par = "h"; }else{ $par = "w"; } if($par == "h"){ $ih = $h; $conv = $new_width/$new_height; $iw = $conv*$ih; $cw = ($w/2)-($iw/2); $ch = ($h/2)-($ih/2); }else if($par == "w"){ $iw = $w; $conv = $new_height/$new_width; $ih = $conv*$iw; $cw = ($w/2)-($iw/2); $ch = ($h/2)-($ih/2); } ImageCopyResampled($destimg,$srcimg,0,0,$cw,$ch,$new_width,$new_height,$iw,$ih) or die("problems with resize"); ImageJPEG($destimg,$destination_path.$nomeimage,$compression) or die("problems with storing new image"); } } 

Этот метод заключается в следующем:

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

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

 SourceWidth / SourceHeight = DestinationWidth / DestinationHeight 

Если вы знаете три параметра, вы можете легко вычислить четвертый.

Я написал статью об этом:
Crop-To-Fit изображение с использованием ASP / PHP

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

Действительно, вы должны иметь ширину или высоту цели, а затем настроить другое измерение на ту же пропорцию.