首页新闻找找看学习计划

C#压缩图片出现失真,就是颜色没有原图鲜艳

0
悬赏园豆:180 [待解决问题]

代码:

/// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="img"></param>
        /// <param name="scale"></param>
        private Image Thumnail(Image img, int scale)
        {
            int h = (int)(img.Height * (scale / 100f));
            int w = (int)(img.Width * (scale / 100f));

            Bitmap thumbnailImage = new Bitmap(w, h);
            using (Graphics g = Graphics.FromImage(thumbnailImage))
            {
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.DrawImage(img, new Rectangle(0, 0, w, h), new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
            }

            return thumbnailImage;
        }

 

求C#高质量压缩图片的算法!

C#
问题补充:

注意,颜色是鲜红色的。有些笔记本显示器可能偏色。

Jesong的主页 Jesong | 初学一级 | 园豆:4
提问于:2012-12-07 10:36
< >
分享
所有回答(6)
0

这是我经常使用的一种高质量算法,很不错的说

//求C#高质量压缩图片的算法!
    public class ThumbnailMaker
    {
        //private static ThumbnailMaker instance;
        //public static ThumbnailMaker Instance
        //{
        //    get
        //    {
        //        lock (typeof(ThumbnailMaker))
        //        {
        //            if (instance == null)
        //                instance = new ThumbnailMaker();
        //            return instance;
        //        }
        //    }
        //}


        public static void CreateDirectory(string path)
        {
            if (path == "") return;
            string head = path.Substring(0, path.IndexOf("\\"));  //d:
            string weibu = path.Substring(head.Length + 1);  //       \1\2
            string hpath = head;
            while (weibu.IndexOf("\\") != -1)
            {
                string p = hpath + "\\" + weibu.Substring(0, weibu.IndexOf("\\"));
                hpath = p;
                if (!Directory.Exists(p))
                    Directory.CreateDirectory(p);
                int ix = weibu.IndexOf("\\") + 1;
                weibu = weibu.Substring(ix);
            }

        }

        /// <summary>
        /// 制作图片的缩略图
        /// </summary>
        /// <param name="originalImage">原图</param>
        /// <param name="width">缩略图的宽(像素)</param>
        /// <param name="height">缩略图的高(像素)</param>
        /// <param name="mode">缩略方式</param>
        /// <returns>缩略图</returns>
        /// <remarks>
        ///        <paramref name="mode"/>///            <para>HW:指定的高宽缩放(可能变形)</para>
        ///            <para>HWO:指定高宽缩放(可能变形)(过小则不变)</para>
        ///            <para>W:指定宽,高按比例</para>
        ///            <para>WO:指定宽(过小则不变),高按比例</para>
        ///            <para>H:指定高,宽按比例</para>
        ///            <para>HO:指定高(过小则不变),宽按比例</para>
        ///            <para>CUT:指定高宽裁减(不变形)</para>
        /// </remarks>
        public static Image MakeThumbnail(Image originalImage, int width, int height, ThumbnailMode mode)
        {
            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;


            switch (mode)
            {
                case ThumbnailMode.UsrHeightWidth: //指定高宽缩放(可能变形)
                    break;
                case ThumbnailMode.UsrHeightWidthBound: //指定高宽缩放(可能变形)(过小则不变)
                    if (originalImage.Width <= width && originalImage.Height <= height)
                    {
                        return originalImage;
                    }
                    if (originalImage.Width < width)
                    {
                        towidth = originalImage.Width;
                    }
                    if (originalImage.Height < height)
                    {
                        toheight = originalImage.Height;
                    }
                    break;
                case ThumbnailMode.UsrWidth: //指定宽,高按比例
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case ThumbnailMode.UsrWidthBound: //指定宽(过小则不变),高按比例
                    if (originalImage.Width <= width)
                    {
                        return originalImage;
                    }
                    else
                    {
                        toheight = originalImage.Height * width / originalImage.Width;
                    }
                    break;
                case ThumbnailMode.UsrHeight: //指定高,宽按比例
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case ThumbnailMode.UsrHeightBound: //指定高(过小则不变),宽按比例
                    if (originalImage.Height <= height)
                    {
                        return originalImage;
                    }
                    else
                    {
                        towidth = originalImage.Width * height / originalImage.Height;
                    }
                    break;
                case ThumbnailMode.Cut: //指定高宽裁减(不变形)
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }

            //新建一个bmp图片
            Image bitmap = new Bitmap(towidth, toheight);

            //新建一个画板
            Graphics g = Graphics.FromImage(bitmap);

            //设置高质量插值法
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = SmoothingMode.HighQuality;
          
            //清空画布并以透明背景色填充
            //g.Clear(Color.Transparent);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                        new Rectangle(x, y, ow, oh),
                        GraphicsUnit.Pixel);
            g.Dispose();
            return bitmap;
        }

        /// <summary>
        /// 制作图片的缩略图
        /// </summary>
        /// <param name="originalStream">原图</param>
        /// <param name="thumbnailPath">保存缩略图的路径</param>
        /// <param name="width">缩略图的宽(像素)</param>
        /// <param name="height">缩略图的高(像素)</param>
        /// <param name="mode">缩略方式,参见<seealso cref="MakeThumbnail(Image, int, int, string)"/></param>
        public static void MakeThumbnail(Stream originalStream, string thumbnailPath, int width, int height, ThumbnailMode mode)
        {
            Image originalImage = Image.FromStream(originalStream);
            try
            {
                MakeThumbnail(originalImage, thumbnailPath, width, height, mode);
            }
            finally
            {
                originalImage.Dispose();
            }
        }

        /// <summary>
        /// 制作图片的缩略图
        /// </summary>
        /// <param name="originalImage">原图</param>
        /// <param name="thumbnailPath">保存缩略图的路径</param>
        /// <param name="width">缩略图的宽(像素)</param>
        /// <param name="height">缩略图的高(像素)</param>
        /// <param name="mode">缩略方式,参见<seealso cref="MakeThumbnail(Image, int, int, string)"/></param>
        public static void MakeThumbnail(Image originalImage, string thumbnailPath, int width, int height, ThumbnailMode mode)
        {
            Image bitmap = MakeThumbnail(originalImage, width, height, mode);
            try
            {
                //以jpg格式保存缩略图
                bitmap.Save(thumbnailPath, ImageFormat.Jpeg);
            }
            finally
            {
                bitmap.Dispose();
            }
        }

        /// <summary>
        /// 制作图片的缩略图
        /// </summary>
        /// <param name="originalImagePath">原图的路径</param>
        /// <param name="thumbnailPath">保存缩略图的路径</param>
        /// <param name="width">缩略图的宽(像素)</param>
        /// <param name="height">缩略图的高(像素)</param>
        /// <param name="mode">缩略方式,参见<seealso cref="MakeThumbnail(Image, int, int, string)"/></param>
        public static void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, ThumbnailMode mode)
        {
            Image originalImage = Image.FromFile(originalImagePath);
            try
            {
              MakeThumbnail(originalImage, thumbnailPath, width, height, mode);                              
            }
            finally
            {
                originalImage.Dispose();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="img"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mode"></param>
        public static byte[] MakeThumbnail(byte[] img, int width, int height, ThumbnailMode mode)
        {
            Stream byteStream = new MemoryStream(img);

            Image originalImage = Image.FromStream(byteStream);

            try
            {
                Image _img = MakeThumbnail(originalImage, width, height, mode);

                MemoryStream imgStream = new MemoryStream();

                _img.Save(imgStream, ImageFormat.Jpeg);

                return imgStream.ToArray();
            }
            finally
            {
                originalImage.Dispose();
            }
        }
        /// <summary>
        /// 产生高清缩略图 固定大小
        /// </summary>
        /// <param name="original_image_file">源文件</param>
        /// <param name="object_width">缩略图宽度</param>
        /// <param name="object_height">缩略图高度</param>
        public static void MakeHighQualityThumbnail(string original_image_file, string output, int object_width, int object_height)
        {


            int actual_width = 0;
            int actual_heigh = 0;
            string outputfilename = output; //original_image_file + ".jpg";

            System.Drawing.Bitmap original_image = new Bitmap(original_image_file);//读取源文件           
            actual_width = original_image.Width;
            actual_heigh = original_image.Height;

            Bitmap img = new Bitmap(object_width, object_height);
            img.SetResolution(108f, 108f);
            Graphics gdiobj = Graphics.FromImage(img);
            gdiobj.CompositingQuality = CompositingQuality.HighQuality;
            gdiobj.SmoothingMode = SmoothingMode.HighQuality;
            gdiobj.InterpolationMode = InterpolationMode.HighQualityBicubic;
            gdiobj.PixelOffsetMode = PixelOffsetMode.HighQuality;

            gdiobj.FillRectangle(new SolidBrush(Color.White), 0, 0, object_width, object_height);
            Rectangle destrect = new Rectangle(0, 0, object_width, object_height);

            gdiobj.DrawImage(original_image, destrect, 0, 0, actual_width, actual_heigh, GraphicsUnit.Pixel);

            System.Drawing.Imaging.EncoderParameters ep = new System.Drawing.Imaging.EncoderParameters(1);
            ep.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100);

            System.Drawing.Imaging.ImageCodecInfo ici = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[0];

            if (ici != null)
            {
                if (File.Exists(outputfilename))
                    File.Delete(outputfilename);
                img.Save(outputfilename, ici, ep);

            }
            else
            {
                img.Save(outputfilename, System.Drawing.Imaging.ImageFormat.Jpeg);
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="img"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mode"></param>
        public static byte[] MakeThumbnail(byte[] img, int width, int height)
        {
            return MakeThumbnail(img, width, height, ThumbnailMode.UsrHeightBound);
        }
    }



    //<para>HW:指定的高宽缩放(可能变形)</para>
    //<para>HWO:指定高宽缩放(可能变形)(过小则不变)</para>
    //<para>W:指定宽,高按比例</para>
    //<para>WO:指定宽(过小则不变),高按比例</para>
    //<para>H:指定高,宽按比例</para>
    //<para>HO:指定高(过小则不变),宽按比例</para>
    //<para>CUT:指定高宽裁减(不变形)</para>
    public enum ThumbnailMode
    {
        UsrHeightWidth,
        UsrHeightWidthBound,
        UsrWidth,
        UsrWidthBound,
        UsrHeight,
        UsrHeightBound,
        Cut,
        NONE,
    }

调用示例:

  ThumbnailMaker.MakeThumbnail("需要转换的图片名", 要保存的路径+ "\\"+Guid.NewGuid().ToString()+原图的扩展名, 宽, 高, ThumbnailMode.Cut);

田麦成 | 园豆:1982 (小虾三级) | 2012-12-07 10:42

抱歉,兄弟,你的代码和我上面粘出来的结果一样:颜色偏暗。

支持(1) 反对(0) Jesong | 园豆:4 (初学一级) | 2012-12-07 11:08
0

围观,学习下.

又要压缩,又要不失真,好像挺难的.

C#有时候就是这个样子,很多细节点很难控制,毕竟好多东西都是微软封装好的,

只会造轮子 | 园豆:2448 (老鸟四级) | 2012-12-07 16:44

你可以不用微软实现好的东西.自己去实现更符合需求的东西.c#在实现上没障碍.

支持(0) 反对(0) 暗香浮动 | 园豆:361 (菜鸟二级) | 2012-12-13 11:28
0

压缩之后自然就会变暗,因为像素少了,那就提亮。。。。

羽商宫 | 园豆:2493 (老鸟四级) | 2012-12-07 20:36

希望图片缩小后还是24位真彩色,不能提亮,因为并不是所有的图片都会暗,全部提亮有些图片就会泛白。

支持(0) 反对(0) Jesong | 园豆:4 (初学一级) | 2012-12-08 21:49
0

这个建议借助第三方的图片压缩才能够做到不失真。

不是几百行代码就搞定的事情。

我晕 昨天记得回复的既然没保存下来,

楼主看下http://www.dotnetperls.com/png

借组一些专业的库来解决这些问题。

````` | 园豆:14268 (专家六级) | 2012-12-09 10:15
0

有的时候我也觉得很蛋疼,

等待是一生最初的苍老 | 园豆:6 (初学一级) | 2012-12-10 10:11
0

Image本身就有获取thumbnail的方法。

不能用么?

还有就是new一个Image的时候可以用另一个做原始图片。

这些内置方法应该都可以搞定啊。

undefined | 园豆:698 (小虾三级) | 2012-12-10 14:02
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册