生成缩略图时报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+ 中发生一般性错误。 究竟是啥问题不是一般性的图片上传出错。

GDI+中发生一般性错误(asp.net(C#))

GDI+中发生一般性错误

System.Runtime.InteropServices.ExternalException: GDI+ 中发生一般性错误

ASP.NET 保存图片(GDI+ 中发生一般性错误)

GDI+中发生一般性错误的解决办法