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

来源:互联网 发布:公司淘宝店注册流程 编辑:程序博客网 时间:2024/06/14 03:47

简介

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

动手前先解决两个问题

获取高质量的Graphics

 /// <summary> /// 获取高清的Graphics /// </summary> /// <param name="img"></param> /// <returns></returns> 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,图片会比其他几种模糊,当然,这种模糊要有好的显示器和对比才能看出来,请仔细对比下面三张图片。
这里写图片描述
这里写图片描述
这里写图片描述

保存Image时进一步控制质量

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

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

我推荐采用下面的方法

//方法2/// <summary>/// 将Image实例保存到文件,注意此方法不执行 img.Dispose()/// 图片保存时本可以直接使用destImage.Save(path, ImageFormat.Jpeg),但是这种方法无法进行进一步控制图片质量/// </summary>/// <param name="path"></param>/// <param name="img"></param>/// <param name="quality">1~100整数,无效值,则取默认值95</param>/// <param name="mimeType"></param>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生成的效果差不多。

生成高质量的缩略图

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

/// <summary>/// 生成高质量缩略图(固定宽高),不一定保持原宽高比/// </summary>/// <param name="destPath">目标保存路径</param>/// <param name="srcPath">源文件路径</param>/// <param name="width">生成缩略图的宽度,设置为0,则与源图比处理</param>/// <param name="height">生成缩略图的高度,设置为0,则与源图等比例处理</param>/// <param name="quality">1~100整数,无效值则取默认值95</param>/// <param name="mimeType">如 image/jpeg</param>    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)图像处理系列之前言》

0 0
原创粉丝点击