C#中基于GDI+(Graphics)图像处理系列之高质量缩略图
2017-01-05 22:34
591 查看
简介
生成图片缩略图的功能在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格式,不能进一步控制质量,仔细观察,在笔触边缘有虚化的现象。//方法1 image. .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)图像处理系列之前言》
相关文章推荐
- C#中基于GDI+(Graphics)图像处理系列之UEditor上传图片自动压缩优化(添加水印)
- C#中基于GDI+(Graphics)图像处理系列之图片压缩优化
- C#中基于GDI+(Graphics)图像处理系列之任意角度旋转图像
- C#中基于GDI+(Graphics)图像处理系列之文字或者图片水印(透明、任意角度旋转)
- C#中基于GDI+(Graphics)图像处理系列之前言
- C#处理图像-缩略图,图像翻转
- 基于VC.NET的GDI+图像处理
- C#下PICTRUEBOX拖动残影,双缓存无效!——接( 图像处理(旋转)_基于EMGUCV(一))
- 基于VC.NET的GDI+图像处理(1) --http://blog.csdn.net/oskycar/archive/2008/04/01/2242151.aspx
- C#GDI+图像处理
- 基于GDI+的图像处理软件制作(VC)
- 基于VC.NET的GDI+图像处理(1)
- 基于Gdi+的图像读存图像处理
- C#GDI+图像处理
- C# (GDI+相关) 图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果) (转)
- 【转】C#GDI+图像处理
- FPGA图像处理系列——基于ZEDBoard构建图像处理通路(Block Ram版本)
- 网站中的缩略图是如何生成的?(C#处理图像)
- 基于VC.NET的GDI+图像处理
- 基于VC.NET的GDI+图像处理(2)