使用MaxHeight和MaxWidth约束按比例调整图像大小


124

使用System.Drawing.Image

如果图像的宽度或高度超过最大值,则需要按比例调整大小。调整大小后,需要确保宽度或高度均不超过限制。

宽度和高度将自动调整大小,直到不超过最大值和最小值(可能的最大尺寸),并保持该比例。


@Sarawut Positwinyu-但是您想要什么宽高比?
Bibhu 2011年

如果无法将图像大小调整为高度和宽度的最大值和最小值并且保持宽高比,该怎么办?
康拉德·弗里克斯

@Bibhu有多种长宽比类型吗?我对此一无所知。我只希望图像比例与原始图像比例相似。
砂拉越Positwinyu

@Sarawut Positwinyu-请查看此Wiki链接以获取更多有关宽高比的信息。en.wikipedia.org/wiki/Aspect_ratio_%28image%29
Bibhu 2011年

1
@Sarawut Positwinyu您没有滥用术语纵横比。或者,如果您做的是好的公司,
康拉德·弗里克斯

Answers:


300

像这样?

public static void Test()
{
    using (var image = Image.FromFile(@"c:\logo.png"))
    using (var newImage = ScaleImage(image, 300, 400))
    {
        newImage.Save(@"c:\test.png", ImageFormat.Png);
    }
}

public static Image ScaleImage(Image image, int maxWidth, int maxHeight)
{
    var ratioX = (double)maxWidth / image.Width;
    var ratioY = (double)maxHeight / image.Height;
    var ratio = Math.Min(ratioX, ratioY);

    var newWidth = (int)(image.Width * ratio);
    var newHeight = (int)(image.Height * ratio);

    var newImage = new Bitmap(newWidth, newHeight);

    using (var graphics = Graphics.FromImage(newImage))
        graphics.DrawImage(image, 0, 0, newWidth, newHeight);

    return newImage;
}

7
@Alex对Math.Min的使用很好(我一直都忘了那个)
Conrad Frix

5
我建议您至少在Graphics对象上使用using语句以节省一些资源:)
Schalk

我只是在考虑一种情况,我不确定在乘以比率后宽度或高度是否仍可能大于最大宽度或最大高度。
砂拉越Positwinyu

4
如果使用asp.net,也请确保使用的是System.Drawing.Image。
Induster

1
@Smith-如果不需要保存图像,请不要运行Save方法。这正是我的ScaleImage方法所做的-返回图像而不保存它。
亚历克斯·阿扎

5

工作方案:

调整大小小于100Kb的图像

WriteableBitmap bitmap = new WriteableBitmap(140,140);
bitmap.SetSource(dlg.File.OpenRead());
image1.Source = bitmap;

Image img = new Image();
img.Source = bitmap;
WriteableBitmap i;

do
{
    ScaleTransform st = new ScaleTransform();
    st.ScaleX = 0.3;
    st.ScaleY = 0.3;
    i = new WriteableBitmap(img, st);
    img.Source = i;
} while (i.Pixels.Length / 1024 > 100);

有关更多参考,请访问http://net4attack.blogspot.com/


5

解决方案长得多,但是考虑了以下情况:

  1. 图像是否小于边框?
  2. 图像和边界框是否正方形?
  3. 图片是正方形,边框不是吗
  4. 图像是否比边界框宽且高
  5. 图像是否比边界框宽
  6. 图片比边框高吗

    private Image ResizePhoto(FileInfo sourceImage, int desiredWidth, int desiredHeight)
    {
        //throw error if bouning box is to small
        if (desiredWidth < 4 || desiredHeight < 4)
            throw new InvalidOperationException("Bounding Box of Resize Photo must be larger than 4X4 pixels.");            
        var original = Bitmap.FromFile(sourceImage.FullName);
    
        //store image widths in variable for easier use
        var oW = (decimal)original.Width;
        var oH = (decimal)original.Height;
        var dW = (decimal)desiredWidth;
        var dH = (decimal)desiredHeight;
    
        //check if image already fits
        if (oW < dW && oH < dH)
            return original; //image fits in bounding box, keep size (center with css) If we made it bigger it would stretch the image resulting in loss of quality.
    
        //check for double squares
        if (oW == oH && dW == dH)
        {
            //image and bounding box are square, no need to calculate aspects, just downsize it with the bounding box
            Bitmap square = new Bitmap(original, (int)dW, (int)dH);
            original.Dispose();
            return square;
        }
    
        //check original image is square
        if (oW == oH)
        {
            //image is square, bounding box isn't.  Get smallest side of bounding box and resize to a square of that center the image vertically and horizontally with Css there will be space on one side.
            int smallSide = (int)Math.Min(dW, dH);
            Bitmap square = new Bitmap(original, smallSide, smallSide);
            original.Dispose();
            return square;
        }
    
        //not dealing with squares, figure out resizing within aspect ratios            
        if (oW > dW && oH > dH) //image is wider and taller than bounding box
        {
            var r = Math.Min(dW, dH) / Math.Min(oW, oH); //two dimensions so figure out which bounding box dimension is the smallest and which original image dimension is the smallest, already know original image is larger than bounding box
            var nH = oH * r; //will downscale the original image by an aspect ratio to fit in the bounding box at the maximum size within aspect ratio.
            var nW = oW * r;
            var resized = new Bitmap(original, (int)nW, (int)nH);
            original.Dispose();
            return resized;
        }
        else
        {
            if (oW > dW) //image is wider than bounding box
            {
                var r = dW / oW; //one dimension (width) so calculate the aspect ratio between the bounding box width and original image width
                var nW = oW * r; //downscale image by r to fit in the bounding box...
                var nH = oH * r;
                var resized = new Bitmap(original, (int)nW, (int)nH);
                original.Dispose();
                return resized;
            }
            else
            {
                //original image is taller than bounding box
                var r = dH / oH;
                var nH = oH * r;
                var nW = oW * r;
                var resized = new Bitmap(original, (int)nW, (int)nH);
                original.Dispose();
                return resized;
            }
        }
    }

1
我认为有几种错别字,您正在使用该比率来计算调整大小后的图像的新高度。正确var nH = oH * r; 不正确:var nH = oW * r;
wloescher '17

固定,只是从未发表评论。
瑞安·曼
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.