图片压缩之处理小图片压缩策略

在进行图片压缩的时候。有时候会碰到要压缩的图片尺寸小于指定的压缩尺寸,若直接压缩会导致图片失真。

当然。最好的方式是挑选合适尺寸图片进行上传。

这里给出的方法是:对不足尺寸部分进行空白填充。

详细參见下面代码

using System;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace CommonLib
{
    public class ImageUtils
    {

        /// <summary>
        /// 创建缩略图像,缩略图是一个正方型的小图片
        /// </summary>
        /// <param name="thumbnilWidth">缩略图的宽度</param>
        /// <param name="inputFileName">原始图像文件名称</param>
        /// <param name="outputFileName">输出的所略图文件名称</param>
        public static void Thumbnil(int thumbnilWidth, string inputFileName, string outputFileName)
        {

            Image src = Image.FromFile(inputFileName);
            Image pThumbnail = Thumbnil(thumbnilWidth, src);
            pThumbnail.Save(outputFileName);
        }

        public static void Thumbnil(int thumbnilWidth, string inputFileName, string outputFileName, ImageFormat format)
        {

            Image src = Image.FromFile(inputFileName);
            Image pThumbnail = Thumbnil(thumbnilWidth, src);
            SaveImage(outputFileName, format, pThumbnail, (long)98);

        }

        /// <summary>
        /// 创建缩略图像,缩略图是一个正方型的小图片
        /// </summary>
        /// <param name="thumbnilWidth"></param>
        /// <param name="inputStream"></param>
        /// <param name="outputFileName"></param>
        /// <param name="format"></param>
        public static void Thumbnil(int thumbnilWidth, Stream inputStream, string outputFileName, ImageFormat format)
        {
            Image src = Image.FromStream(inputStream);
            Image pThumbnail = Thumbnil(thumbnilWidth, src);
            SaveImage(outputFileName, format, pThumbnail, (long)98);
        }

        /// <summary>
        /// 创建缩略图像,缩略图是一个正方型的小图片
        /// </summary>
        /// <param name="thumbnilWidth"></param>
        /// <param name="inputStream"></param>
        /// <param name="outputFileName"></param>
        public static void Thumbnil(int thumbnilWidth, Stream inputStream, string outputFileName)
        {
            Image src = Image.FromStream(inputStream);
            Image pThumbnail = Thumbnil(thumbnilWidth, src);
            pThumbnail.Save(outputFileName);
            src.Dispose();
            pThumbnail.Dispose();
        }

        /// <summary>
        /// 缩略图
        /// </summary>
        /// <param name="maxWidth">最大宽度</param>
        /// <param name="maxHeight">最大的高度</param>
        /// <param name="inputStream">图片流</param>
        /// <param name="outputFileName">输出路径</param>
        public static void Thumbnil(int maxWidth, int maxHeight, Stream inputStream, string outputFileName)
        {
            string fileDirectory = Path.GetDirectoryName(outputFileName);
            if (!Directory.Exists(fileDirectory))
            {
                DirectoryInfo di = Directory.CreateDirectory(fileDirectory);//创建一个文件
            }
            System.Drawing.Image img = System.Drawing.Image.FromStream(inputStream);
            if (img.Width > maxWidth || img.Height > maxHeight)
            {
                int pwidth = 0;
                if (img.Height / maxHeight > img.Width / maxWidth)
                {
                    pwidth = Convert.ToInt16(((decimal)img.Width) * maxHeight / img.Height);
                }
                else
                {
                    pwidth = maxWidth;
                }
                Thumbnil(pwidth, inputStream, outputFileName);
            }
            else
            {
                Thumbnil(img.Width, inputStream, outputFileName);
            }
            img.Dispose();
        }

        public static void Thumbnil(int thumbnilWidth, Stream inputStream, Stream outputStream, ImageFormat format)
        {
            Image src = Image.FromStream(inputStream);
            Image pThumbnail = Thumbnil(thumbnilWidth, src);
            SaveImage(outputStream, format, pThumbnail, (long)98);
        }

        public static Image Thumbnil(int thumbnilWidth, Image src)
        {
            int width_heigh = src.Width;
            if (src.Height < src.Width)
                width_heigh = src.Height;

            RectangleF sourceRect = new RectangleF((src.Width - width_heigh) / 2,
                (src.Height - width_heigh) / 2, width_heigh, width_heigh);

            RectangleF destinationRect = new RectangleF(0, 0, thumbnilWidth, thumbnilWidth);
            Image pThumbnail = new Bitmap(thumbnilWidth, thumbnilWidth);
            Graphics g = Graphics.FromImage(pThumbnail);
            g.InterpolationMode = InterpolationMode.High;
            g.DrawImage(src, destinationRect, sourceRect, GraphicsUnit.Pixel);
            return pThumbnail;
        }

        private static void SaveImage(string outputFileName, ImageFormat format, Image image)
        {
            SaveImage(outputFileName, format, image, (long)95);
        }

        private static void SaveImage(string outputFileName, ImageFormat format, Image image, long qualityValue)
        {
            if (format == ImageFormat.Jpeg)
            {
                EncoderParameters ep = new EncoderParameters();
                ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualityValue);

                ImageCodecInfo ici = null;
                ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
                foreach (ImageCodecInfo codec in codecs)
                {
                    if (codec.MimeType == "image/jpeg")
                    {
                        ici = codec;
                        break;
                    }
                }

                if (ici != null)
                    image.Save(outputFileName, ici, ep);
                else
                    image.Save(outputFileName, format);
            }
            else
                image.Save(outputFileName, format);
        }

        private static void SaveImage(Stream outputStream, ImageFormat format, Image image)
        {
            SaveImage(outputStream, format, image, (long)95);
        }

        private static void SaveImage(Stream outputStream, ImageFormat format, Image image, long qualityValue)
        {
            if (format == ImageFormat.Jpeg)
            {
                EncoderParameters ep = new EncoderParameters();
                ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualityValue);

                ImageCodecInfo ici = null;
                ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
                foreach (ImageCodecInfo codec in codecs)
                {
                    if (codec.MimeType == "image/jpeg")
                    {
                        ici = codec;
                        break;
                    }
                }

                if (ici != null)
                    image.Save(outputStream, ici, ep);
                else
                    image.Save(outputStream, format);
            }
            else
                image.Save(outputStream, format);
        }

        /// <summary>
        /// 按图片原始比例创建缩略图像
        /// </summary>
        public static void ScaleImage(int maxPixel, string inputFileName, string outputFileName, string waterMarkText, InterpolationMode interpolationMode, ImageFormat imageFormat)
        {
            Image src = Image.FromFile(inputFileName);
            int src_height = src.Height;
            int src_width = src.Width;
            int destW = maxPixel;
            int destH = maxPixel;

            double wh_Ratio = src_width * 1.0 / src_height * 1.0;

            if (src_height <= maxPixel && src_width <= maxPixel)
            {
                File.Copy(inputFileName, outputFileName);
                src.Dispose();
                return;
            }
            else if (wh_Ratio <= 1)
            {
                destW = (int)Math.Round(destH * wh_Ratio);
                if (destW == 0)
                    destW = 1;
            }
            else if (wh_Ratio > 1)
            {
                destH = (int)Math.Round(destW / wh_Ratio);
                if (destH == 0)
                    destH = 1;
            }

            RectangleF sourceRect = new RectangleF(0, 0, src_width, src_height);
            RectangleF destinationRect = new RectangleF(0, 0, destW, destH);

            Image destImg = new Bitmap(destW, destH);

            Graphics g = Graphics.FromImage(destImg);

            if (interpolationMode == InterpolationMode.Bilinear)
                interpolationMode = InterpolationMode.High;

            g.InterpolationMode = interpolationMode;
            g.DrawImage(src, destinationRect, sourceRect, GraphicsUnit.Pixel);

            #region 增加水印的算法
            //WaterMark(destImg, GetWaterMarkImage());
            WaterMarkText(destImg, waterMarkText);
            #endregion

            long qulityValue = 95;
            if (destW < 200 || destH < 200)
                qulityValue = 98;

            //destImg.Save(outputFileName, imageFormat);
            SaveImage(outputFileName, imageFormat, destImg, qulityValue);

            destImg.Dispose();
            src.Dispose();
            g.Dispose();
            return;
        }

        /// <summary>
        /// 按图片原始比例创建缩略图像
        /// </summary>
        public static void ScaleImage(int maxPixel, Stream inputStream, string outputFileName, string waterMarkText, InterpolationMode interpolationMode, ImageFormat imageFormat)
        {
            Image src = Image.FromStream(inputStream);
            int src_height = src.Height;
            int src_width = src.Width;
            int destW = maxPixel;
            int destH = maxPixel;

            double wh_Ratio = src_width * 1.0 / src_height * 1.0;

            if (src_height <= maxPixel && src_width <= maxPixel)
            {
                src.Save(outputFileName, imageFormat);
                src.Dispose();
                return;
            }
            else if (wh_Ratio <= 1)
            {
                destW = (int)Math.Round(destH * wh_Ratio);
            }
            else if (wh_Ratio > 1)
            {
                destH = (int)Math.Round(destW / wh_Ratio);
            }

            RectangleF sourceRect = new RectangleF(0, 0, src_width, src_height);
            RectangleF destinationRect = new RectangleF(0, 0, destW, destH);

            Image destImg = new Bitmap(destW, destH);

            Graphics g = Graphics.FromImage(destImg);

            if (interpolationMode == InterpolationMode.Bilinear)
                interpolationMode = InterpolationMode.High;

            g.InterpolationMode = interpolationMode;
            g.DrawImage(src, destinationRect, sourceRect, GraphicsUnit.Pixel);

            #region 增加水印的算法
            //WaterMark(destImg, GetWaterMarkImage());
            WaterMarkText(destImg, waterMarkText);
            #endregion

            //默认处理。大图片就减少一些画质
            long qulityValue = 95;
            if (destW < 200 || destH < 200)
                qulityValue = 98;
            //destImg.Save(outputFileName, imageFormat);
            SaveImage(outputFileName, imageFormat, destImg, qulityValue);

            destImg.Dispose();
            src.Dispose();
            g.Dispose();
            return;
        }

        /// <summary>
        /// 图片压缩
        /// </summary>
        /// <param name="maxWidth">最大宽度</param>
        /// <param name="maxHeight">最大高度</param>
        /// <param name="inputStream">图片流</param>
        /// <param name="outputFileName">输出路径</param>
        /// <param name="waterMarkText">水印文字</param>
        /// <param name="interpolationMode">生成格式</param>
        /// <param name="imageFormat">图片格式化</param>
        public static void ScaleImage(int maxWidth, int maxHeight, Stream inputStream, string outputFileName, string waterMarkText, InterpolationMode interpolationMode, ImageFormat imageFormat)
        {
            string fileDirectory = Path.GetDirectoryName(outputFileName);
            if (!Directory.Exists(fileDirectory))
            {
                DirectoryInfo di = Directory.CreateDirectory(fileDirectory);//创建一个文件
            }
            System.Drawing.Image img = System.Drawing.Image.FromStream(inputStream);
            if (img.Width > 770 || img.Height > 560)
            {
                int pwidth = 0;
                if (img.Height / maxHeight > img.Width / maxWidth)
                {
                    pwidth = Convert.ToInt16(((decimal)img.Width) * maxHeight / img.Height);
                }
                else
                {
                    pwidth = maxWidth;
                }
                ScaleImage(pwidth, inputStream, outputFileName, waterMarkText, interpolationMode, imageFormat);
            }
            else
            {
                ScaleImage(img.Width, inputStream, outputFileName, waterMarkText, interpolationMode, imageFormat);
            }
            img.Dispose();
        }

        public static void WaterMarkText(Image srcImg, string waterMarkText)
        {
            try
            {
                if (string.IsNullOrEmpty(waterMarkText))
                    return;

                if (srcImg.Width <= 100)
                    return;

                int waterMarkWidth = srcImg.Width;
                int waterMarkHeight = 20; //px;

                WaterMarkText(srcImg, waterMarkText, 0, srcImg.Height - waterMarkHeight, waterMarkHeight, waterMarkWidth, new Font("微软雅黑", 12, GraphicsUnit.Pixel));
            }
            catch
            {
                throw;
            }

        }


        public static void WaterMarkText(Image srcImg, string waterMarkText, int left, int top, int waterMarkHeight, int waterMarkWidth, Font font)
        {
            try
            {

                Graphics g = Graphics.FromImage(srcImg);

                Rectangle rect = new Rectangle(left, top, waterMarkWidth, waterMarkHeight);

                //画半透明确色底色
                Brush brush = new SolidBrush(Color.FromArgb(99, Color.White));
                g.FillRectangle(brush, rect);

                //画文字
                rect.Width = rect.Width - 10;
                rect.Y = rect.Y + 2;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                StringFormat sf = new StringFormat();
                sf.Alignment = StringAlignment.Far;
                g.DrawString(waterMarkText, font, Brushes.Black, rect, sf);

                //存盘
                g.Save();
                #region 释放此函数创建的GDI+资源
                brush.Dispose();
                font.Dispose();
                sf.Dispose();

                g.Dispose();
                #endregion
            }
            catch
            {
                throw;
            }

        }

        private static void WaterMark(Image srcImg, Image waterMarkImage)
        {
            if (waterMarkImage == null)
                return;

            if (waterMarkImage.Width > (srcImg.Width - 20))
                return;

            if (waterMarkImage.Height > (srcImg.Height - 20))
                return;

            //水印在右下角。距离边6px位置
            Rectangle rect = new Rectangle(0, 0, waterMarkImage.Width, waterMarkImage.Height);

            #region 生成一个暂时Image
            Image tempImage = new Bitmap(waterMarkImage.Width, waterMarkImage.Height);

            float[][] ptsArray ={ 
				new float[] {1, 0, 0, 0, 0},
				new float[] {0, 1, 0, 0, 0},
				new float[] {0, 0, 1, 0, 0},
				new float[] {0, 0, 0, 0.5f, 0}, //注意:此处为0.5f,图像为半透明
				new float[] {0, 0, 0, 0, 1}};

            ColorMatrix clrMatrix = new ColorMatrix(ptsArray);
            Graphics tempGraphics = Graphics.FromImage(tempImage);

            //将原图的要被水印覆盖的位置copy到暂时Image
            Rectangle srcRect = new Rectangle(srcImg.Width - waterMarkImage.Width - 6, srcImg.Height - waterMarkImage.Height - 6,
                waterMarkImage.Width, waterMarkImage.Height);

            tempGraphics.DrawImage(srcImg, rect, srcRect, GraphicsUnit.Pixel);

            ImageAttributes tempImgAttributes = new ImageAttributes();
            tempImgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.SkipGrays, ColorAdjustType.Bitmap);

            //将水印图片贴到暂时区,跳过gray颜色。

白色也是一种gray。将是透明色 tempGraphics.DrawImage(waterMarkImage, rect, 0, 0, waterMarkImage.Width, waterMarkImage.Height, GraphicsUnit.Pixel, tempImgAttributes); tempGraphics.Save(); #endregion #region 将暂时Image以透明贴图的方式绘至原图 ImageAttributes imgAttributes = new ImageAttributes(); imgAttributes.SetColorKey(Color.White, Color.White); //绘图像 Graphics g = Graphics.FromImage(srcImg); //srcRect 是原图要覆盖的区域,此时作为目标区域 g.DrawImage(tempImage, srcRect, 0, 0, tempImage.Width, tempImage.Height, GraphicsUnit.Pixel, imgAttributes); g.Save(); #endregion #region 释放此函数创建的资源 g.Dispose(); tempGraphics.Dispose(); tempImage.Dispose(); #endregion } private static Image waterMarkImage = null; public static Image GetWaterMarkImage() { return waterMarkImage; } public static void SetWaterMarkImage(Image image) { waterMarkImage = image; } } /// <summary> /// 图片处理:缩略图片 /// </summary> public class ImageDealLib { /// <summary> /// 图片保存类型 /// JPEG:.jpg格式; /// GIF:.gif格式; /// PNG:.png格式; /// </summary> public enum ImageType { JPEG, GIF, PNG } /// <summary> /// 水印模式 /// Center:中间; /// CenterUp:中上; /// CenterDown:中下; /// LeftUp:左上; /// LeftDown:左下; /// RightUp:右上; /// RightDown:右下; /// Random:随机; /// </summary> public enum WaterType { Center, CenterUp, CenterDown, LeftUp, LeftDown, RightUp, RightDown, Random } /// <summary> /// 缩略模式 /// X--按宽度缩放,高着宽比例; /// Y--按高度缩放,宽着宽比例; /// XY--按给定mwidth,mheight(此模式mwidth,mheight为必须值)进行缩略; /// </summary> public enum ResizeType { X, Y, XY } /// <summary> /// 文件检測模式 /// M:不检測文件是否存在,返回ServerMapPath; /// C:检測文件是否存在,返回ServerMapPath; /// </summary> public enum FileCheckModel { M, C } /// <summary> /// 原图文件是否保存 /// Delete:保存 /// Save:不保存,删除 /// </summary> public enum FileCache { Save, Delete } /// <summary> /// 依据指定:缩略宽、高,缩略图片并保存 /// 返回图片虚拟路径,和一个警告信息,可依据此信息获取图片合成信息 /// </summary> /// <param name="picpath">原图路径</param> /// <param name="model">缩略模式[X,Y,XY](默认XY模式)</param> /// <param name="spath">文件保存路径(默认跟路径)</param> /// <param name="imgtype">图片保存类型</param> /// <param name="mwidth">缩略宽度(默认原图高度)</param> /// <param name="mheight">缩略高度(默认原图高度)</param> /// <param name="filecache">原文件处理方式</param> /// <param name="warning">处理警告信息</param> /// <returns>错误,返回错误信息;成功,返回图片路径</returns> public static string Resizepic(double? mwidth, double?

mheight, string picpath, string spath, ResizeType model, ImageType imgtype, FileCache filecache, out string warning) { //反馈信息 System.Text.StringBuilder checkmessage = new System.Text.StringBuilder(); //原图路径 if (string.IsNullOrWhiteSpace(picpath)) { checkmessage.Append("请输入原图路径。"); warning = checkmessage.ToString().TrimEnd(';'); return string.Empty; } //文件保存路径 if (string.IsNullOrWhiteSpace(spath)) { checkmessage.Append("请输入保存路径。"); warning = checkmessage.ToString().TrimEnd(';'); return string.Empty; } else { string fileDirectory = Path.GetDirectoryName(spath); if (!Directory.Exists(fileDirectory)) { DirectoryInfo di = Directory.CreateDirectory(fileDirectory);//创建一个文件 } } //缩略宽度 double swidth = mwidth.HasValue ?

double.Parse(mwidth.ToString()) : 0; //缩略高度 double sheight = mheight.HasValue ? double.Parse(mheight.ToString()) : 0; //从指定源图片,创建image对象 string _sourceimg_common_mappath = ""; //检測源文件 bool checkfile = false; checkfile = System.IO.File.Exists(picpath);//FileExistMapPath(picpath, FileCheckModel.C, out _sourceimg_common_mappath); System.Drawing.Image _sourceimg_common = null; System.Drawing.Bitmap _currimg_common = null; System.Drawing.Graphics _g_common = null; if (checkfile) { //从源文件创建imgage _sourceimg_common = System.Drawing.Image.FromFile(picpath); #region 缩略模式 //缩略模式 switch (model) { case ResizeType.X: #region X模式 //依据给定尺寸,获取绘制比例 double _width_scale = swidth / _sourceimg_common.Width; //高着比例 sheight = _sourceimg_common.Height * _width_scale; #endregion ; break; case ResizeType.Y: #region Y模式 //依据给定尺寸,获取绘制比例 double _height_scale = sheight / _sourceimg_common.Height; //宽着比例 swidth = _sourceimg_common.Width * _height_scale; #endregion ; break; case ResizeType.XY: #region XY模式 //当选择XY模式时,mwidth,mheight为必须值 if (swidth < 0 || sheight < 0) { checkmessage.Append("error:XY模式,mwidth,mheight为必须值;"); } #endregion ; break; default: #region 默认XY模式 //当默认XY模式时,mwidth,mheight为必须值 if (swidth < 0 || sheight < 0) { checkmessage.Append("error:你当前未选择缩略模式,系统默认XY模式,mwidth,mheight为必须值;"); } ; break; #endregion } #endregion } else { checkmessage.Append("error:未能找到缩略原图片," + picpath + ";"); } if (string.IsNullOrEmpty(checkmessage.ToString())) { //创建bitmap对象 _currimg_common = new System.Drawing.Bitmap((int)swidth, (int)sheight); _g_common = Graphics.FromImage(_currimg_common); //画半透明确色底色 Brush brush = new SolidBrush(Color.FromArgb(99, Color.White)); _g_common.FillRectangle(brush, 0, 0, (float)swidth, (float)sheight); //设置画笔 _g_common.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; _g_common.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; _g_common.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; int left = Math.Max(0, ((int)swidth - _sourceimg_common.Width) / 2);//图片左距离 int top = Math.Max(0, ((int)sheight - _sourceimg_common.Height) / 2);//图片上距离 int des_width = (int)swidth; int des_height = (int)sheight; int s_width = _sourceimg_common.Width; int s_height = _sourceimg_common.Height; if (des_width < s_width) { des_width = s_width; } if (des_height < s_height) { des_height = s_height; } //绘制图片 _g_common.DrawImage(_sourceimg_common, new Rectangle(left, top, Math.Min(_sourceimg_common.Width, (int)swidth), Math.Min(_sourceimg_common.Height, (int)sheight)), new Rectangle(0, 0, _sourceimg_common.Width, _sourceimg_common.Height), GraphicsUnit.Pixel); //保存图片 string _spath_common_mappath = ""; //获取图片类型的hashcode值,生成图片后缀名 int extro = imgtype.GetHashCode(); string extend = extro == 0 ? ".jpg" : (extro == 1 ?

".gif" : (extro == 2 ?

".png" : ".jpg")); //全局文件名称 // spath = spath + Guid.NewGuid().ToString() + extend; // FileExistMapPath(spath, FileCheckModel.M, out _spath_common_mappath); switch (imgtype) { case ImageType.JPEG: _currimg_common.Save(spath, System.Drawing.Imaging.ImageFormat.Jpeg); break; case ImageType.GIF: _currimg_common.Save(spath, System.Drawing.Imaging.ImageFormat.Gif); break; case ImageType.PNG: _currimg_common.Save(spath, System.Drawing.Imaging.ImageFormat.Png); break; } //释放 _sourceimg_common.Dispose(); _currimg_common.Dispose(); _g_common.Dispose(); //处理原文件 int filecachecode = filecache.GetHashCode(); //文件缓存方式:Delete,删除原文件 if (filecachecode == 1) { System.IO.File.Delete(picpath); } //返回相对虚拟路径 warning = ""; return spath; } //释放 if (_sourceimg_common != null) { _sourceimg_common.Dispose(); } if (_currimg_common != null) { _currimg_common.Dispose(); } if (_g_common != null) { _g_common.Dispose(); } warning = checkmessage.ToString().TrimEnd(';'); return ""; } } }


调用实例:

 ImageDealLib.Resizepic(
                        480,
                        480,
                        goodPicPath,
                        thumbPath,
                        CommonLib.ImageDealLib.ResizeType.X,
                        CommonLib.ImageDealLib.ImageType.JPEG,
                        CommonLib.ImageDealLib.FileCache.Save,
                        out warning);


 

原文地址:https://www.cnblogs.com/wgwyanfs/p/6814205.html