首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 高品質縮圖產生:Graphics 高品質插值 + JPEG 壓縮

     編輯:關於C#

問題背景

Bitmap.GetThumbnailImage 產生的縮圖品質較差(預設低品質雙線性插值)。若直接用 Graphics.DrawImage 配合 HighQualityBicubic 雖畫質佳,但輸出未壓縮的 JPEG 體積過大。解決方案:**高品質繪製 + Encoder 參數指定 JPEG 品質**。

三種作法比較

方法API畫質檔案大小適用場景
1. 內建縮圖GetThumbnailImage低小快速預覽、不在意畫質
2. 高品質繪製Graphics.InterpolationMode = HighQualityBicubic高大 (無壓縮)列印、後續再處理
3. 高品質 + 壓縮方法 2 + Encoder.Quality高小 (約原圖 1/10)Web 縮圖、儲存空間敏感

完整實作 (Console 應用程式)

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

class Program
{
    const int TargetW = 190, TargetH = 190;

    static void Main()
    {
        string src = @"G:\photoes\20060725\Picture 057.jpg";
        string dir = @"E:\Diary\Test\thumbnail";
        Directory.CreateDirectory(dir);

        // 方法 1:內建
        MakeThumb1(src, Path.Combine(dir, "th_1.jpg"));
        // 方法 2:高品質繪製
        MakeThumb2(src, Path.Combine(dir, "th_2.jpg"));
        // 方法 3:高品質 + JPEG 壓縮 (品質 75)
        MakeThumb3(src, Path.Combine(dir, "th_3.jpg"), 75L);

        Console.WriteLine("完成,請比較三個檔案大小與畫質。");
        Console.ReadKey();
    }

    // 共用:計算保持長寬比的目標尺寸
    static Size CalcSize(Image src)
    {
        if (src.Width > src.Height)
            return new Size(TargetW, (int)(src.Height * (double)TargetW / src.Width));
        else
            return new Size((int)(src.Width * (double)TargetH / src.Height), TargetH);
    }

    // 方法 1
    static void MakeThumb1(string srcPath, string destPath)
    {
        using (var src = new Bitmap(srcPath))
        using (var thumb = src.GetThumbnailImage(CalcSize(src).Width, CalcSize(src).Height, null, IntPtr.Zero))
            thumb.Save(destPath);
    }

    // 方法 2
    static void MakeThumb2(string srcPath, string destPath)
    {
        using (var src = new Bitmap(srcPath))
        {
            var sz = CalcSize(src);
            using (var bmp = new Bitmap(sz.Width, sz.Height))
            using (var g = Graphics.FromImage(bmp))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.Clear(Color.White);
                g.DrawImage(src, 0, 0, sz.Width, sz.Height);
            }
            bmp.Save(destPath); // 預設無壓縮
        }
    }

    // 方法 3:核心差異在 EncoderParameters
    static void MakeThumb3(string srcPath, string destPath, long quality)
    {
        // 1. 取得 JPEG Encoder
        var jpegCodec = ImageCodecInfo.GetImageEncoders()
            .FirstOrDefault(c => c.FormatDescription == "JPEG");
        if (jpegCodec == null) throw new InvalidOperationException("系統未安裝 JPEG 編碼器");

        // 2. 設定品質參數 (0~100)
        var ep = new EncoderParameters(1);
        ep.Param[0] = new EncoderParameter(Encoder.Quality, quality);

        using (var src = new Bitmap(srcPath))
        {
            var sz = CalcSize(src);
            using (var bmp = new Bitmap(sz.Width, sz.Height))
            using (var g = Graphics.FromImage(bmp))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.Clear(Color.White);
                g.DrawImage(src, 0, 0, sz.Width, sz.Height);
            }
            bmp.Save(destPath, jpegCodec, ep); // 關鍵:指定編碼器與參數
        }
    }
}

關鍵點總結

  1. InterpolationMode.HighQualityBicubic:雙三次插值,縮放畫質最佳。
  2. Encoder.Quality (0~100):75 是畫質/大小平衡甜點;>90 體積激增、<50 明顯失真。
  3. ImageCodecInfo.GetImageEncoders():必須在執行時查詢,避免硬編碼 CLSID。
  4. 長寬比保持:以長邊為基準等比縮放,避免變形。
  5. 背景填白:g.Clear(Color.White) 避免透明背景存成 JPEG 變黑。

進階擴充

  • 支援 PNG 輸出:改用 Encoder.Compression + Png codec。
  • 批次處理:搭配 Parallel.ForEach 多核心加速。
  • 記憶體優化:大圖分塊處理或使用 Image.GetThumbnailImageAbort 回調取消。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved