PHP Изменить размер изображения и обрезать их, чтобы предотвратить растягивание [дублировать]

Шаг 1 Сначала вам нужно загрузить и установить последнюю версию Git Windows Credential Manager.

Вот ссылка на него на GitHub. https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases/latest

Шаг 2 Перезагрузите компьютер.

Шаг 3 Введите команду git в командной строке, и вам будет предложено снова войти в систему.

Шаг 4 Если вы по-прежнему получаете такую ​​же фатальную ошибку, вам нужно будет обновить Git, загрузив последнюю версию здесь : https://git-scm.com/downloads

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

42
задан Bogidon 9 September 2014 в 00:20
поделиться

12 ответов

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

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 представляет собой только одно число для ширины и высоты (квадратный размер цели). Я уверен, что вы можете изменить его, чтобы использовать не-квадратные цели. Это также должно дать вам вдохновение в отношении того, какие другие алгоритмы изменения размера вы можете использовать.

68
ответ дан deceze 27 August 2018 в 14:54
поделиться
$ratio = $originalWidth / $originalHeight

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

$targetWidth = $targetHeight * $ratio

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

$targetHeight = $targetWidth / $ratio
45
ответ дан Azylak 27 August 2018 в 14:54
поделиться

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

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));
}
0
ответ дан hakre 27 August 2018 в 14:54
поделиться
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
0
ответ дан JF Meier 27 August 2018 в 14:54
поделиться

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

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)
12
ответ дан jilles de wit 27 August 2018 в 14:54
поделиться

Этот пример уменьшит изображение, чтобы он соответствовал идеальному соотношению пикселей (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;
    }    
}
0
ответ дан JPickup 27 August 2018 в 14:54
поделиться

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

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);
    }
6
ответ дан kestas 27 August 2018 в 14:54
поделиться

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

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

$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);
0
ответ дан Miguel 27 August 2018 в 14:54
поделиться

Проверьте код 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'>";
1
ответ дан palmplam 27 August 2018 в 14:54
поделиться

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

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

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;
}

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

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

0
ответ дан r3wt 27 August 2018 в 14:54
поделиться

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

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

Удачи.

0
ответ дан user3284463 27 August 2018 в 14:54
поделиться

Как насчет этого:

double ratio = imageWidth/imageHeight;
int newHeight = Math.min(displayHeight, displayWidth / ratio); 
int newWidth =  Math.min(displayWidth, displayHeight * ratio); 
0
ответ дан Yaza 27 August 2018 в 14:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: