您的位置:首页 > 编程语言 > C#

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)图像处理系列之前言》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息