How can I crop/scale user images so I can display fixed sized thumbnails without skewing and stretching?

余生颓废 提交于 2019-12-24 00:35:05

问题


I'm working on allowing users to upload profile pictures for my site. The classic example of what I'm trying to avoid is plentyoffish.com where each users image is skewed and looks very ugly:

So, how can I progmatically crop/create standard sized versions of an image without the skewing demonstrated above?


回答1:


Well, you must have a maximum height and width, lets assume the image size you have available is square, say 100x100.

When a user uploads an image get the dimensions of it, then work out which is greater, the height or the width.

Then take the greatest measurement and get the ratio of that measurement to your target measurement, then use that ratio to scale both the height and width.

So if the user uploads a picture of 500 height and 450 width, as the height is greatest you'd divide 100 by 500, your thumbnail size. This gives us .2 as the ratio. which means the width will become 90, so you would shrink to 100x90, and no distortion would occur.




回答2:


Here's some code (C#) I used to do a resize, similar to the method suggested by blowdart. Just replace the "300"s with the maximum size of one side in your case:

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



回答3:


OR: If you would still like fixed dimensions, you follow blowdart's instructions but calculate the greatest ratio instead: 100px / 450px = .22..

  • width: 100px
  • height: 111.11..px -> crop from floor((111.11 - 100) / 2) on top and 100px down.

EDIT: Or let the user select how to crop the greatest dimension.




回答4:


Use ImageMagick. On the command line use:

convert -thumbnail geometry



回答5:


I made this function for PHP a while ago that works great for this and some other scenarios:

<?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');

?>



回答6:


Here's a bash command I threw together to accomplish this using ImageMagick's convert tool. For a set of images sitting in the parent directory, some portrait, some landscape, to create images in the current directory scaled to 600x400, cropping portrait images from the centre and simply scaling the landscape images:

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;


来源:https://stackoverflow.com/questions/991587/how-can-i-crop-scale-user-images-so-i-can-display-fixed-sized-thumbnails-without

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!