C#中基于GDI+(Graphics)图像处理系列之高质量缩略图

简介

生成图片缩略图的功能在Web开发的工作是经常遇到的,比如用户上传一张图片作为用户头像,根据业务的需要生成若干不同尺寸的缩略图,不同的功能使用不同尺寸的图片等等。
大家知道Image类有一个GetThumbnailImage的方法来生成缩略图,但是这货表现得非常不稳定,笔者就曾经掉了它的坑中被狠狠地坑了一把,所以决定自己实现生成缩略图的功能。
本文将重点向大家介绍怎么使用GDI+(Graphics)实现生成缩略图功能,同时提醒大家要想获得高质量的缩略图需要做的设置。

动手前先解决两个问题

获取高质量的Graphics

 /// 
 /// 获取高清的Graphics
 /// 
 /// 
 /// 
 public Graphics GetGraphics(Image img)
 {
      var g = Graphics.FromImage(img);
      //设置质量
      g.SmoothingMode = SmoothingMode.HighQuality;
      g.CompositingQuality = CompositingQuality.HighQuality;
      //InterpolationMode不能使用High或者HighQualityBicubic,如果是灰色或者部分浅色的图像是会在边缘处出一白色透明的线
      //用HighQualityBilinear却会使图片比其他两种模式模糊(需要肉眼仔细对比才可以看出)
      g.InterpolationMode = InterpolationMode.Default;
      g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
      return g;
}

注意InterpolationMode的值为Default,之前我在设置这个值的时候,毫不犹豫的选择了High,在实际项目中发现,对于灰色的图片,会在图片边缘由于插值会画上透明的白线,采用HighQualityBicubic也会有类似的情况;而使用HighQualityBilinear,图片会比其他几种模糊,当然,这种模糊要有好的显示器和对比才能看出来,请仔细对比下面三张图片。
C#中基于GDI+(Graphics)图像处理系列之高质量缩略图_第1张图片
C#中基于GDI+(Graphics)图像处理系列之高质量缩略图_第2张图片
C#中基于GDI+(Graphics)图像处理系列之高质量缩略图_第3张图片

保存Image时进一步控制质量

通常我们在保存图片时使用下面的代码,这种方法就是将图片直接保存成jpeg格式,不能进一步控制质量,仔细观察,在笔触边缘有虚化的现象。

//方法1
image. .Save("1.jpg", ImageFormat.Jpeg);

我推荐采用下面的方法

//方法2
/// 
/// 将Image实例保存到文件,注意此方法不执行 img.Dispose()
/// 图片保存时本可以直接使用destImage.Save(path, ImageFormat.Jpeg),但是这种方法无法进行进一步控制图片质量
/// 
/// 
/// 
/// 1~100整数,无效值,则取默认值95
/// 
public void SaveImage2File(string path, Image destImage, int quality, string mimeType = "image/jpeg")
{
     if (quality <= 0 || quality > 100) quality = 95;
     //创建保存的文件夹
     FileInfo fileInfo = new FileInfo(path);
     if (!Directory.Exists(fileInfo.DirectoryName))
     {
          Directory.CreateDirectory(fileInfo.DirectoryName);
     }
     //设置保存参数,保存参数里进一步控制质量
     EncoderParameters encoderParams = new EncoderParameters();
     long[] qua = new long[] { quality };           
     EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
     encoderParams.Param[0] = encoderParam;
     //获取指定mimeType的mimeType的ImageCodecInfo
     var codecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(ici => ici.MimeType == mimeType);
     destImage.Save(path, codecInfo, encoderParams);            
}

使用时传入quality值(1~100),我个人认为95已经很好了,93足够,如采用方法1生成的图片效果跟第二种方法quality=70生成的效果差不多。

生成高质量的缩略图

下面是生成全部源码,代码中的详细的注释,这里不再赘述

/// 
/// 生成高质量缩略图(固定宽高),不一定保持原宽高比
/// 
/// 目标保存路径
/// 源文件路径
/// 生成缩略图的宽度,设置为0,则与源图比处理
/// 生成缩略图的高度,设置为0,则与源图等比例处理
/// 1~100整数,无效值则取默认值95
/// 如 image/jpeg    
public bool GetThumbnailImage(string destPath, string srcPath, int destWidth, int destHeight, int quality, out string error, string mimeType = "image/jpeg")
{
     bool retVal = false;
     error = string.Empty;
     //宽高不能小于0
     if (destWidth < 0 || destHeight < 0)
     {
           error = "目标宽高不能小于0";
           return retVal;
     }
     //宽高不能同时为0
     if (destWidth == 0 && destHeight == 0)
     {
          error = "目标宽高不能同时为0";
          return retVal;
     }            
     Image srcImage = null;
     Image destImage = null;
     Graphics graphics = null;
     try
     {
          //获取源图像
          srcImage = Image.FromFile(srcPath, false);
          //计算高宽比例
          float d = (float)srcImage.Height / srcImage.Width;
          //如果输入的宽为0,则按高度等比缩放
          if (destWidth == 0)
          {
               destWidth = Convert.ToInt32(destHeight / d);
          }
          //如果输入的高为0,则按宽度等比缩放
          if (destHeight == 0)
          {
              destHeight = Convert.ToInt32(destWidth * d);
          }
          //定义画布
          destImage = new Bitmap(destWidth, destHeight);
          //获取高清Graphics
          graphics = GetGraphics(destImage);
          //将源图像画到画布上,注意最后一个参数GraphicsUnit.Pixel
          graphics.DrawImage(srcImage, new Rectangle(0, 0, destWidth, destHeight), new Rectangle(0, 0, srcImage.Width, srcImage.Height), GraphicsUnit.Pixel);             
         //如果是覆盖则先释放源资源
         if (destPath == srcPath)
         {
              srcImage.Dispose();
         }
         //保存到文件,同时进一步控制质量
         SaveImage2File(destPath, destImage, quality, mimeType);
         retVal = true;
    }
    catch (Exception ex)
    {
         error = ex.Message;
    }
    finally
    {
          if (srcImage != null)
              srcImage.Dispose();
          if (destImage != null)
              destImage.Dispose();
          if (graphics != null)
              graphics.Dispose();
    }
    return retVal;
}

完整示例程序源码

http://download.csdn.net/detail/lhtzbj12/9730116

示例程序截图

C#中基于GDI+(Graphics)图像处理系列之高质量缩略图_第4张图片
如果想查阅本系列其他文章,请移步《C#中基于GDI+(Graphics)图像处理系列之前言》

你可能感兴趣的:(C#,.Net,C#,Graphics,缩略图,压缩,高质量)