【问题标题】:Resize image proportionally with MaxHeight and MaxWidth constraints使用 MaxHeight 和 MaxWidth 约束按比例调整图像大小
【发布时间】:2011-09-24 00:19:33
【问题描述】:

使用System.Drawing.Image

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

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

【问题讨论】:

  • @Sarawut Positwinyu - 但是你想要什么纵横比?
  • 如果图像无法调整到最大和最小的高度和宽度并且保持纵横比,您希望发生什么?
  • @Bibhu 有多种纵横比吗?我不知道。我只是希望图像比例尽可能与原始图像比例广告相似。
  • @Sarawut Positwinyu - 查看此 wiki 链接以了解有关纵横比的更多信息。 en.wikipedia.org/wiki/Aspect_ratio_%28image%29
  • @Sarawut Positwinyu 您没有滥用术语纵横比。或者如果你这样做了,你在good company

标签: c# .net winforms image-processing gdi+


【解决方案1】:

像这样?

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

【讨论】:

  • @Alex 很好地使用了 Math.Min(我总是忘记那个)
  • 我建议你在 Graphics 对象上使用 using 语句至少可以节省一些资源:)
  • 我只是在考虑一个案例,我不确定在乘以比率后宽度或高度是否可能仍然大于最大宽度或最大高度。
  • 如果使用 asp.net,还要确保使用 System.Drawing.Image。
  • @Smith - 如果您不需要保存图像,请不要运行 Save 方法。这正是我的 ScaleImage 方法所做的 - 返回图像而不保存它。
【解决方案2】:

更长的解决方案,但考虑到以下场景:

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

【讨论】:

  • 我认为有几个拼写错误,您使用比率来计算调整大小图像的新高度。正确的 var nH = oH * r;不正确:var nH = oW * r;
  • 已修复,只是从未评论过。
【解决方案3】:

工作解决方案:

用于调整大小小于 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/

【讨论】:

    猜你喜欢
    • 2011-08-04
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 2011-07-15
    • 2010-10-21
    • 1970-01-01
    相关资源
    最近更新 更多