生成缩略图时报GDI+中发生一般性错误
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成缩略图时报GDI+中发生一般性错误相关的知识,希望对你有一定的参考价值。
最近由于业务需要要写一个生成缩略图并能设置图片质量的功能,本来这是一件so easy的事,以前也干过,可是却遇到了问题。话不多说先看代码
/// <summary> /// 等比生成缩略图 /// </summary> /// <param name="originalImagePath">源图路径(物理路径)</param> /// <param name="thumbnailPath">缩略图路径(物理路径)</param> /// <param name="width">缩略图最大宽度</param> /// <param name="height">缩略图最大高度</param> /// <param name="imageQualityValue">图片要保存的压缩质量,该参数的值为1至100的整数,数值越大,保存质量越好</param> public static void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, int imageQualityValue) { //原图名称 string imgName = originalImagePath.Substring(originalImagePath.LastIndexOf("\\\\") + 1); //根目录 string path1 = System.Web.HttpContext.Current.Server.MapPath("~/Upload/"); //将原图移动到根目录下 File.Move(originalImagePath, path1 + imgName); //获取移动后的原图路径 string newpath = path1 + imgName; //读取图片信息 System.Drawing.Image originalImage = System.Drawing.Image.FromFile(newpath); #region 获取缩略图宽高 int w = 0;//最终缩略图的宽 int h = 0;//最终缩略图的高 if (originalImage.Width > width && originalImage.Height < height) { w = width; h = width * originalImage.Height / originalImage.Width; } else if (originalImage.Width < width && originalImage.Height > height) { h = height; w = height * originalImage.Width / originalImage.Height; } else if (originalImage.Width > width && originalImage.Height > height) { if ((double)originalImage.Width / (double)originalImage.Height > (double)width / (double)height) {//如果原图的宽高比 > 缩略图的宽高比 宽缩放 w = width; h = width * originalImage.Height / originalImage.Width; } else {//如果原图的宽高比 <= 缩略图的宽高比 高缩放 h = height; w = originalImage.Width * h / originalImage.Height; } } #endregion if (w == 0 || h == 0) { return; } //新建一个bmp图片 System.Drawing.Image bitmap = new System.Drawing.Bitmap(towidth, toheight); //新建一个画板 System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap); //设置高质量插值法 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; //设置高质量,低速度呈现平滑程度 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //清空画布并以透明背景色填充 g.Clear(System.Drawing.Color.Transparent); //在指定位置并且按指定大小绘制原图片的指定部分 g.DrawImage(originalImage, new System.Drawing.Rectangle(0, 0, towidth, toheight), new System.Drawing.Rectangle(x, y, ow, oh), System.Drawing.GraphicsUnit.Pixel); //以下代码为保存图片时,设置压缩质量 EncoderParameters encoderParameters = new EncoderParameters(); EncoderParameter encoderParameter = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100); encoderParameters.Param[0] = encoderParameter; ImageCodecInfo[] ImageCodecInfoArray = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegImageCodecInfo = null; for (int i = 0; i < ImageCodecInfoArray.Length; i++) { if (ImageCodecInfoArray[i].FormatDescription.Equals("PNG")) { jpegImageCodecInfo = ImageCodecInfoArray[i]; break; } } try { bitmap.Save(thumbnailPath, jpegImageCodecInfo, encoderParameters); } catch (System.Exception e) { throw e; } finally { encoderParameters.Dispose(); encoderParameter.Dispose(); originalImage.Dispose(); bitmap.Dispose(); g.Dispose(); File.Delete(path1 + imgName); } GC.Collect(); }
乍一看,代码没有如何问题,那就运行起来吧
TMD竟然报错了,什么原因呢,然后就摆渡了,网上各种方法各种试,都不好使!猫了眯的,怎么回事?最后开始问朋友,朋友也没辙,而且我写的方法在他那不报错,神了。难道老天针对我!神经病啊,不对,再问朋友的过程中朋友一句话点醒了我,你为什么要移动图片啊!哦哦哦,这才想起来这个方法一些没用,后来改了一次就是为了让他报错的,然后我就屁颠屁颠的去掉了最开始的那几行移动图片的代码,不出意外的通过了,运行良好。感谢天感谢地终于写好了,修改过后的代码如下
1 /// <summary> 2 /// 等比生成缩略图 3 /// </summary> 4 /// <param name="originalImagePath">源图路径(物理路径)</param> 5 /// <param name="thumbnailPath">缩略图路径(物理路径)</param> 6 /// <param name="width">缩略图最大宽度</param> 7 /// <param name="height">缩略图最大高度</param> 8 /// <param name="imageQualityValue">图片要保存的压缩质量,该参数的值为1至100的整数,数值越大,保存质量越好</param> 9 public static void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, int imageQualityValue) 10 { 11 //原图名称 12 //读取图片信息 13 System.Drawing.Image originalImage = System.Drawing.Image.FromFile(originalImagePath); 14 #region 获取缩略图宽高 15 int w = 0;//最终缩略图的宽 16 int h = 0;//最终缩略图的高 17 if (originalImage.Width > width && originalImage.Height < height) 18 { 19 w = width; 20 h = width * originalImage.Height / originalImage.Width; 21 } 22 else if (originalImage.Width < width && originalImage.Height > height) 23 { 24 h = height; 25 w = height * originalImage.Width / originalImage.Height; 26 } 27 else if (originalImage.Width > width && originalImage.Height > height) 28 { 29 if ((double)originalImage.Width / (double)originalImage.Height > (double)width / (double)height) 30 {//如果原图的宽高比 > 缩略图的宽高比 宽缩放 31 w = width; 32 h = width * originalImage.Height / originalImage.Width; 33 } 34 else 35 {//如果原图的宽高比 <= 缩略图的宽高比 高缩放 36 h = height; 37 w = originalImage.Width * h / originalImage.Height; 38 } 39 } 40 #endregion 41 if (w == 0 || h == 0) 42 { 43 return; 44 } 45 //新建一个bmp图片 46 System.Drawing.Image bitmap = new System.Drawing.Bitmap(w, h); 47 //获取高清的Graphics 48 System.Drawing.Graphics g = GetGraphics(bitmap); 49 //清空画布并以透明背景色填充 50 g.Clear(System.Drawing.Color.Transparent); 51 //在指定位置并且按指定大小绘制原图片的指定部分 52 g.DrawImage(originalImage, new System.Drawing.Rectangle(0, 0, w, h), new System.Drawing.Rectangle(0, 0, originalImage.Width, originalImage.Height), System.Drawing.GraphicsUnit.Pixel); 53 if (originalImagePath == thumbnailPath) 54 { 55 originalImage.Dispose(); 56 } 57 //保存到文件,同时进一步控制质量 58 SaveImage2File(thumbnailPath, bitmap, imageQualityValue); 59 60 //bitmap.Save(thumbnailPath, jpegImageCodecInfo, encoderParameters); 61 if (originalImage != null) 62 { 63 originalImage.Dispose(); 64 } 65 bitmap.Dispose(); 66 g.Dispose(); 67 GC.Collect(); 68 }
1 /// <summary> 2 /// 将Image实例保存到文件,注意此方法不执行 img.Dispose() 3 /// 图片保存时本可以直接使用destImage.Save(path, ImageFormat.Jpeg),但是这种方法无法进行进一步控制图片质量 4 /// </summary> 5 /// <param name="path"></param> 6 /// <param name="img"></param> 7 /// <param name="quality">1~100整数,无效值,则取默认值95</param> 8 /// <param name="mimeType"></param> 9 public static void SaveImage2File(string path, Image destImage, int quality, string mimeType = "image/jpeg") 10 { 11 if (quality <= 0 || quality > 100) quality = 95; 12 //创建保存的文件夹 13 FileInfo fileInfo = new FileInfo(path); 14 if (!Directory.Exists(fileInfo.DirectoryName)) 15 { 16 Directory.CreateDirectory(fileInfo.DirectoryName); 17 } 18 //设置保存参数,保存参数里进一步控制质量 19 EncoderParameters encoderParams = new EncoderParameters(); 20 long[] qua = new long[] { quality }; 21 EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality); 22 encoderParams.Param[0] = encoderParam; 23 //获取指定mimeType的mimeType的ImageCodecInfo 24 var codecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(ici => ici.MimeType == mimeType); 25 try 26 { 27 destImage.Save(path, codecInfo, encoderParams); 28 } 29 catch (Exception) 30 { 31 throw; 32 } 33 finally 34 { 35 fileInfo = null; 36 encoderParams.Dispose(); 37 encoderParam.Dispose(); 38 } 39 } 40 /// <summary> 41 /// 获取高清的Graphics 42 /// </summary> 43 /// <param name="img"></param> 44 /// <returns></returns> 45 public static Graphics GetGraphics(Image img) 46 { 47 var g = Graphics.FromImage(img); 48 //设置质量 49 g.SmoothingMode = SmoothingMode.HighQuality; 50 g.CompositingQuality = CompositingQuality.HighQuality; 51 //InterpolationMode不能使用High或者HighQualityBicubic,如果是灰色或者部分浅色的图像是会在边缘处出一白色透明的线 52 //用HighQualityBilinear却会使图片比其他两种模式模糊(需要肉眼仔细对比才可以看出) 53 g.InterpolationMode = InterpolationMode.Default; 54 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; 55 return g; 56 }
真是有时候蠢起来连自己都怕
以上是关于生成缩略图时报GDI+中发生一般性错误的主要内容,如果未能解决你的问题,请参考以下文章
GDI+ 中发生一般性错误。 究竟是啥问题不是一般性的图片上传出错。
System.Runtime.InteropServices.ExternalException: GDI+ 中发生一般性错误