首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

C# 圖片等比縮放算法:按最大寬高計算最佳尺寸

     編輯:更多程式設計知識

在上傳頭像、商品圖、內容插圖等場景,需將任意尺寸原圖縮放至指定最大寬高範圍內,且保持長寬比不變形。本文提供一個纯静态方法 NewSize,輸入原圖寬高與目標最大寬高,輸出計算後的最佳 Size,代碼極簡、無依賴、單元測試友好。

核心代碼

using System.Drawing;

public static class ImageHelper {
    /// 
    /// 計算等比縮放後的尺寸
    /// 
    /// 目標最大寬度
    /// 目標最大高度
    /// 原圖寬度
    /// 原圖高度
    /// 縮放後的 Size (寬, 高)
    public static Size NewSize(int maxWidth, int maxHeight, int width, int height) {
        double w = 0, h = 0;
        double sw = width, sh = height, mw = maxWidth, mh = maxHeight;

        if (sw < mw && sh < mh) {
            // 原圖已在目標框內,不放大
            w = sw; h = sh;
        }
        else if ((sw / sh) > (mw / mh)) {
            // 原圖較寬,以寬度為基準縮放
            w = mw;
            h = (w * sh) / sw;
        }
        else {
            // 原圖較高,以高度為基準縮放
            h = mh;
            w = (h * sw) / sh;
        }
        return new Size((int)Math.Round(w), (int)Math.Round(h));
    }
}

算法邏輯圖解

目標框: 300x300
原圖 600x400 (寬高比 1.5)  > 目標框比 1.0  → 以寬為基準 → 300x200
原圖 400x600 (寬高比 0.67) < 目標框比 1.0  → 以高為基準 → 200x300
原圖 200x150 (均小於目標)                  → 不縮放 → 200x150

配合 Graphics 高質量繪圖

public static void SaveThumbnail(string srcPath, string destPath, int maxW, int maxH, long quality = 85) {
    using (var img = Image.FromFile(srcPath)) {
        Size newSize = NewSize(maxW, maxH, img.Width, img.Height);
        using (var bmp = new Bitmap(newSize.Width, newSize.Height))
        using (var g = Graphics.FromImage(bmp)) {
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(img, new Rectangle(0, 0, newSize.Width, newSize.Height),
                        0, 0, img.Width, img.Height, GraphicsUnit.Pixel);

            // JPEG 編碼器質量設置
            var encoder = ImageCodecInfo.GetImageEncoders()
                              .First(c => c.FormatDescription == "JPEG");
            var ep = new EncoderParameters(1);
            ep.Param[0] = new EncoderParameter(Encoder.Quality, quality);
            bmp.Save(destPath, encoder, ep);
        }
    }
}

單元測試用例 (xUnit)

[Theory]
[InlineData(300, 300, 600, 400, 300, 200)]
[InlineData(300, 300, 400, 600, 200, 300)]
[InlineData(300, 300, 200, 150, 200, 150)]
[InlineData(100, 200, 400, 300, 100, 75)]
public void NewSize_ShouldKeepAspectRatio(int maxW, int maxH, int w, int h, int expW, int expH) {
    var size = ImageHelper.NewSize(maxW, maxH, w, h);
    Assert.Equal(expW, size.Width);
    Assert.Equal(expH, size.Height);
}

常見變體需求

  • 強制填滿並裁剪:以較大比例縮放,再居中裁剪至目標尺寸 (用於封面圖)。
  • 補白 (Letterbox):等比縮放後,在短邊填充指定顏色至目標尺寸 (用於商品主圖統一比例)。
  • 最小邊限制:縮放後若任意邊小于閾值 (如 50px),則按閥值反向放大。

可在 NewSize 基礎上擴展參數 mode (Enum: Fit / Fill / Pad) 實現上述變體,核心數學邏輯不變。

將此方法放入 ImageHelper,所有圖片處理入口統一調用,確保縮略圖生成邏輯一致、可測試、可維護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved