Как я могу обрезать / масштабировать пользовательские изображения, чтобы отображать миниатюры фиксированного размера без перекоса и растяжения? - PullRequest
2 голосов
/ 14 июня 2009

Я работаю над тем, чтобы позволить пользователям загружать изображения профиля для моего сайта. Классический пример того, чего я пытаюсь избежать, это lentyoffish.com , где изображение каждого пользователя искажено и выглядит очень некрасиво:

alt text

Итак, как я могу постепенно обрезать / создавать версии изображения стандартного размера без перекоса, показанного выше?

Ответы [ 6 ]

5 голосов
/ 14 июня 2009

Ну, у вас должны быть максимальная высота и ширина, давайте предположим, что размер имеющегося у вас изображения квадратный, скажем, 100x100.

Когда пользователь загружает изображение, получает его размеры, а затем решает, что больше: высота или ширина.

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

Таким образом, если пользователь загружает изображение высотой 500 и шириной 450, а высота наибольшая, вы делите 100 на 500 - размер миниатюры. Это дает нам 0,2 как соотношение. это означает, что ширина станет 90, поэтому вы уменьшите ее до 100x90, и никаких искажений не произойдет.

1 голос
/ 14 июня 2009

Вот код (C #), который я использовал для изменения размера, аналогично методу, предложенному blowdart. Просто замените «300» с максимальным размером одной стороны в вашем случае:

 private Bitmap ScaleImage(Image oldImage)
    {
        double resizeFactor = 1;

        if (oldImage.Width > 300 || oldImage.Height > 300)
        {
            double widthFactor = Convert.ToDouble(oldImage.Width) / 300;
            double heightFactor = Convert.ToDouble(oldImage.Height) / 300;
            resizeFactor = Math.Max(widthFactor, heightFactor);

        }
        int width = Convert.ToInt32(oldImage.Width / resizeFactor);
        int height = Convert.ToInt32(oldImage.Height / resizeFactor);
        Bitmap newImage = new Bitmap(width, height);
        Graphics g = Graphics.FromImage(newImage);
        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        g.DrawImage(oldImage, 0, 0, newImage.Width, newImage.Height);
        return newImage;
    }
0 голосов
/ 19 ноября 2009

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

for f in ../*jpg; do
    echo $f; 
    size=`identify $f|cut -d' ' -f 3`; 
    w=`echo $size|cut -dx -f 1`; 
    h=`echo $size|cut -dx -f 2`; 
    if [ $w -gt $h ]; then 
        convert $f -thumbnail 600x400 `basename $f`; 
    else 
        convert $f -scale 600x -crop 600x400+0+`echo "((600*($h/$w))/2)" | bc | sed 's/\..*//'` `basename $f`; 
    fi;
done;
0 голосов
/ 30 июля 2009

Я сделал эту функцию для PHP некоторое время назад, которая отлично работает для этого и некоторых других сценариев:

<?php

function Image($source, $crop = null, $resize = null)
{
    $source = ImageCreateFromString(file_get_contents($source));

    if (is_resource($source) === true)
    {
        $width = imagesx($source);
        $height = imagesy($source);

        if (isset($crop) === true)
        {
            $crop = array_filter(explode('/', $crop), 'is_numeric');

            if (count($crop) == 2)
            {
                if (($width / $height) > ($crop[0] / $crop[1]))
                {
                    $width = $height * ($crop[0] / $crop[1]);
                    $crop = array((imagesx($source) - $width) / 2, 0);
                }

                else if (($width / $height) < ($crop[0] / $crop[1]))
                {
                    $height = $width / ($crop[0] / $crop[1]);
                    $crop = array(0, (imagesy($source) - $height) / 2);
                }
            }

            else
            {
                $crop = array(0, 0);
            }
        }

        else
        {
            $crop = array(0, 0);
        }

        if (isset($resize) === true)
        {
            $resize = array_filter(explode('*', $resize), 'is_numeric');

            if (count($resize) >= 1)
            {
                if (empty($resize[0]) === true)
                {
                    $resize[0] = round($resize[1] * $width / $height);
                }

                else if (empty($resize[1]) === true)
                {
                    $resize[1] = round($resize[0] * $height / $width);
                }
            }

            else
            {
                $resize = array($width, $height);
            }
        }

        else
        {
            $resize = array($width, $height);
        }

        $result = ImageCreateTrueColor($resize[0], $resize[1]);

        if (is_resource($result) === true)
        {
            ImageCopyResampled($result, $source, 0, 0, $crop[0], $crop[1], $resize[0], $resize[1], $width, $height);
            ImageDestroy($source);

            header('Content-Type: image/jpeg');

            ImageJPEG($result, null, 90);
            ImageDestroy($result);
        }
    }

    return false;
}

Image('/path/to/your/image.jpg', '1/1', '100*');
Image('/path/to/your/image.jpg', '1/1', '100*100');
Image('/path/to/your/image.jpg', '1/1', '100*500');

?>
0 голосов
/ 14 июня 2009

Использование ImageMagick . В командной строке используйте:

convert -thumbnail geometry
0 голосов
/ 14 июня 2009

ИЛИ: если вам все еще нужны фиксированные размеры, вы следуете инструкциям blowdart, но вместо этого рассчитываете наибольшее соотношение: 100px / 450px = .22 ..

  • ширина: 100px
  • высота: 111.11..px -> обрезка с пола ((111.11 - 100) / 2) сверху и 100px вниз.

РЕДАКТИРОВАТЬ : или позволить пользователю выбрать способ обрезки наибольшего размера.

...