Пропорциональное изменение размера изображения - PullRequest
31 голосов
/ 22 сентября 2008

У меня возникла небольшая проблема с масштабированием изображений до предварительно определенного размера. Мне было интересно - поскольку это чисто математика, есть ли какой-то общий логический алгоритм, который работает на каждом языке (PHP, ActionScript, Javascript и т. Д.) Для пропорционального масштабирования изображений.

Я сейчас использую это:

var maxHeight   = 300;
var maxWidth    = 300;

var ratio:Number    =   height / width;

if (height > maxHeight) {
    height = maxHeight;
    width = Math.round(height / ratio);
} 

else if(width > maxWidth) {
    width = maxWidth;
    height = Math.round(width * ratio);
}

Но это не работает должным образом. Конечно, изображения пропорционально масштабируются, но размер не установлен на 300 (ни по ширине, ни по высоте). Это имеет смысл, но мне было интересно, есть ли надежный и простой способ пропорционального масштабирования изображений.

Ответы [ 6 ]

64 голосов
/ 22 сентября 2008
ratio = MIN( maxWidth / width, maxHeight/ height );
width = ratio * width;
height = ratio * height;

Убедитесь, что все деления с плавающей точкой.

4 голосов
/ 22 сентября 2008

У Темного Шикари это есть. Ваше решение, как указано в вопросе, терпит неудачу, потому что вы сначала не устанавливаете, какое отношение размера размерности к максимальному больше, и затем сокращает оба измерения на это большее соотношение.

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

Также обратите внимание, что если вы хотите повысить масштаб изображений, ваше текущее решение не будет работать, и Dark Shikari снова будет.

2 голосов
/ 22 сентября 2008

Я бы рекомендовал не писать этот код самостоятельно; Есть множество деталей на уровне пикселей, которые требуют серьезного времени, чтобы получить право. Используйте ImageMagick, это лучшая графическая библиотека.

1 голос
/ 29 февраля 2012

Вот как я это делаю:

+ (NSSize) scaleHeight:(NSSize)origSize 
             newHeight:(CGFloat)height {

    NSSize newSize = NSZeroSize;
    if ( origSize.height == 0 ) return newSize;

    newSize.height = height;
    CGFloat factor = ( height / origSize.height );
    newSize.width  = (origSize.width * factor );

    return newSize;
}

+ (NSSize) scaleWidth:(NSSize)origSize 
             newWidth:(CGFloat)width {

    NSSize newSize = NSZeroSize;
    if ( origSize.width == 0 ) return newSize;

    newSize.width  = width;
    CGFloat factor = ( width / origSize.width );
    newSize.height = (origSize.height * factor );

    return newSize;
}
0 голосов
/ 22 января 2012

я сделал эту функцию для пропорционального масштабирования, она использует заданную ширину, высоту и, необязательно, максимальную ширину / высоту, которую вы хотите (зависит от заданной ширины и высоты)

   function scaleProportional($img_w,$img_h,$max=50)
   {
       $w = 0;
       $h = 0;

       $img_w > $img_h ? $w = $img_w / $img_h : $w = 1;
       $img_h > $img_w ? $h = $img_h / $img_w : $h = 1;

       $ws = $w > $h ? $ws = ($w / $w) * $max : $ws = (1 / $h) * $max;
       $hs = $h > $w ? $hs = ($h / $h) * $max : $hs = (1 / $w) * $max;

       return array(
           'width'=>$ws,
           'height'=>$hs
       );
   }

использование:

            $getScale = scaleProportional(600,200,500);
            $targ_w = $getScale['width']; //returns 500
            $targ_h = $getScale['height']; //returns 16,6666667
0 голосов
/ 13 октября 2011

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

Он выполняет не только обработку изображений, но и другие вещи - Пожалуйста, удалите все ненужное .

<?php

$thumb_width    = 500;
$thumb_height   = 500;

if ($handle = opendir('to-do')) {
    echo "Directory handle: $handle<br />";
    echo "Files:<br /><br />";

    /* This is the correct way to loop over the directory. */
    while (false !== ($file = readdir($handle))) {

        if ( ($file != ".") && ($file != "..") ){
            echo "$file";

            $original_path = "to-do/" . $file;

            $source_image = ImageCreateFromJPEG( $original_path );
            $thumb_width = $thumb_width;
            $thumb_height = $thumb_height;

            // Create the image, of the required size
            $thumbnail = imagecreatetruecolor($thumb_width, $thumb_height);
            if($thumbnail === false) {
                //creation failed -- probably not enough memory
                return null;
            }

            // Fill the image with a white 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($thumbnail, 255, 255, 255);
            imagefill($thumbnail, 0, 0, $fill);

            // Compute resize ratio
            $hratio = $thumb_height / imagesy($source_image);
            $wratio = $thumb_width / imagesx($source_image);
            $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($source_image) * $ratio);
            $sx = floor(imagesx($source_image) * $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(($thumb_height - $sy) / 2);
            $m_x = floor(($thumb_width - $sx) / 2);

            // Copy the image data, and resample
            // If you want a fast and ugly thumbnail, replace imagecopyresampled with imagecopyresized
            if (!imagecopyresampled($thumbnail, $source_image,
                $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($source_image), imagesy($source_image)) //src w, h (the full size of the original)
            ) {
                //copy failed
                imagedestroy($thumbnail);
                return null;
            }

            /* Set the new file name */
            $thumbnail_file_name = $file;

            /* Apply changes on the original image and write the result on the disk */
            ImageJPEG( $thumbnail, $complete_path . "done/" . $thumbnail_file_name );
            unset($source_image);
            unset($thumbnail);
            unset($original_path);
            unset($targeted_image_size);

            echo " done<br />";

        }

    }

    closedir($handle);
}

?>
...