Подтвердить что ты не робот

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

$ratio = $originalWidth / $originalHeight

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

$targetWidth = $targetHeight * $ratio

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

$targetHeight = $targetWidth / $ratio

Ответ 3

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

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)

Ответ 4

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

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

Ответ 5

Проверьте код 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'>";

Ответ 6

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

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

Удачи.

Ответ 7

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

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

Ответ 8

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

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

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

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

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

Ответ 9

Этот пример уменьшит изображение, чтобы он соответствовал определенному размеру пикселя (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;
    }    
}

Ответ 10

Если максимальная высота или ширина заданы или нет, используя логику @(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);

Ответ 11

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 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 not set the script will output the image without saving it */
$resize_image->save_folder = 'thumbs/';
$process = $resize_image->resize(); // Output image

Ответ 12

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

double ratio = imageWidth/imageHeight;
int newHeight = Math.min(displayHeight, displayWidth / ratio); 
int newWidth =  Math.min(displayWidth, displayHeight * ratio);