C#图片压缩与缩略图生成的三种实现方案

Hazel
Hazel
发布时间:2026-10-14 | 6人浏览过
原创

在Web应用开发中,用户提交的高清大图往往会导致页面加载缓慢及存储浪费。针对C#环境下的图片处理需求,核心目标是降低文件体积并生成符合尺寸的缩略图。本文将解析两种主流技术路径:一是利用GDI+原生接口进行按比例缩放以保持视觉比例;二是通过获取JPEG编码器信息并设置Quality参数,实现更大幅度的文件体积压缩。

高质量等比缩放算法

在进行图片缩放时,直接指定固定宽高容易导致图片变形。合理的做法是计算源图片与目标容器的长宽比率,选取较小者作为基准进行等比缩放,并在绘制时使用高质量插值模式以保留细节。

第1步:计算缩放比例与裁剪中心

目的:确保生成的缩略图不产生拉伸失真,且若尺寸不符则自动居中显示。

  • 参数说明:源图像 mg(Bitmap类型)、目标尺寸 newSize(Size类型)。
  • 算法逻辑:分别计算宽度和高度的缩放倍率,取较大倍率(即较严格的那个维度)作为基准 ratio。据此反推实际缩略后的宽高 myThumbWidth 和 myThumbHeight。
public Bitmap GetImageThumb(Bitmap mg, Size newSize)
{
    double ratio = 0d;
    double myThumbWidth = 0d;
    double myThumbHeight = 0d;
    int x = 0; // 绘图起始X坐标
    int y = 0; // 绘图起始Y坐标

    // 判断哪个方向先达到限制
    if ((mg.Width / Convert.ToDouble(newSize.Width)) > (mg.Height / Convert.ToDouble(newSize.Height)))
        ratio = Convert.ToDouble(mg.Width) / Convert.ToDouble(newSize.Width);
    else
        ratio = Convert.ToDouble(mg.Height) / Convert.ToDouble(newSize.Height);

    // 计算等比缩放后的实际尺寸
    myThumbHeight = Math.Ceiling(mg.Height / ratio);
    myThumbWidth = Math.Ceiling(mg.Width / ratio);

    // 创建最终画布
    Size thumbSize = new Size((int)newSize.Width, (int)newSize.Height);
    Bitmap bp = new Bitmap(newSize.Width, newSize.Height);

    // 计算居中位置,使图片在画布中央
    x = (newSize.Width - thumbSize.Width) / 2;
    y = (newSize.Height - thumbSize.Height); 

    using (Graphics g = Graphics.FromImage(bp))
    {
        // 启用高质量绘制选项
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;

        Rectangle rect = new Rectangle(x, y, thumbSize.Width, thumbSize.Height);
        // 将源图像绘制到目标矩形区域
        g.DrawImage(mg, rect, 0, 0, mg.Width, mg.Height, GraphicsUnit.Pixel);
    }
    return bp;
}

此方法生成的图片虽然尺寸正确且无损变形,但若原图为PNG格式或默认保存为PNG,文件体积缩减效果有限(例如从200K可能仅降至160K左右)。为了显著减小文件体积,必须在保存环节介入。

基于JPEG Quality参数的深度压缩

C#的 System.Drawing.Imaging 命名空间提供了对JPEG压缩因子的控制权。通过修改 Encoder.Quality 参数,可以在肉眼可接受的质量损失下,将图片体积缩小至原来的几分之一。

第2步:配置ImageCodecInfo与EncoderParameters

目的:找到系统中的JPEG编码器实例,并绑定自定义的质量等级(通常范围1-100,数值越小文件越小)。

  1. 获取编码器列表:调用 ImageCodecInfo.GetImageEncoders() 遍历系统已注册的图像处理接口。
  2. 筛选JPEG编码器:查找 FormatDescription 为 "JPEG" 的项,记录其对象引用。
  3. 设置压缩参数:创建 EncoderParameter 对象,传入 System.Drawing.Imaging.Encoder.Quality 和期望的质量值数组(long类型)。
/// <summary>
/// 根据路径保存图片并进行压缩
/// </summary>
/// <param name="sFile">源图片路径</param>
/// <param name="outPath">输出图片路径</param>
/// <param name="flag">压缩质量参数 1-100,值越低压缩率越高</param>
public static bool GetPicThumbnail(string sFile, string outPath, int flag)
{
    System.Drawing.Image iSource = System.Drawing.Image.FromFile(sFile);
    ImageFormat tFormat = iSource.RawFormat;

    // 初始化压缩参数容器
    EncoderParameters ep = new EncoderParameters(1);
    long[] qy = new long[1];
    qy[0] = flag; // 设置压缩比例
    EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
    ep.Param[0] = eParam;

    try
    {
        // 查找JPEG编码器
        ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
        ImageCodecInfo jpegICIinfo = null;
        for (int x = 0; x < arrayICI.Length; x++)
        {
            if (arrayICI[x].FormatDescription.Equals("JPEG"))
            {
                jpegICIinfo = arrayICI[x];
                break;
            }
        }

        if (jpegICIinfo != null)
        {
            // 使用指定的编码器和参数保存,实现大幅度压缩
            iSource.Save(outPath, jpegICIinfo, ep);
        }
        else
        {
            // 如果找不到JPEG编码器(极少情况),按原格式保存
            iSource.Save(outPath, tFormat);
        }
        return true;
    }
    catch
    {
        return false;
    }
    finally
    {
        if (iSource != null)
        {
            iSource.Dispose();
        }
    }
}

第3步:组合调用策略

在实际工程中,建议将上述两个步骤结合:先调用 GetImageThumb 进行几何层面的缩放,再将生成的 Bitmap 转化为流或临时文件,最后通过 GetPicThumbnail 将其以 JPEG 格式高质量低体积分盘保存。这能有效解决用户上传高清照片后网页打开慢、服务器带宽占用高等问题。

注意事项与排错

  • GDI+资源释放:在处理图片的过程中,务必确保 Graphics、Image 对象在适当时机被 Dispose,避免内存泄漏,尤其是在高并发的Web服务环境中。
  • 非JPEG格式支持:上述 Encoder 方案主要针对JPEG。如果必须保存为PNG或GIF,则无法使用Quality参数控制体积,此时主要依赖前面的缩放算法来减少像素总量从而间接减小体积。
  • 中文路径问题:部分旧版Windows环境下,Image.FromFile 可能对包含特殊字符的路径支持不佳,建议使用UTF-8编码或检查文件名合法性。

以上就是C#图片压缩的详细实现方案与代码示例,更多关于ASP.NET前端性能优化的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表