天天看点

c# ImageHelper 图片水印等操作

using System;

using System.Collections.Generic;

using System.Drawing;

using System.Drawing.Imaging;

using System.IO;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

namespace Common

{

    public class ImageHelper

    {

        /// <summary>

        /// 生成图片,采用等比例压缩方式

        /// </summary>

        /// <param name="imgBytes">源图片字节流</param>

        /// <param name="width">新图片宽度</param>

        /// <param name="height">新图片高度</param>

        /// <param name="makeMode">生成模式</param>

        /// <returns>生成后的图片流</returns>

        public static byte[] MakeImage(byte[] imgBytes, int width, int height, ImageMakeMode makeMode)

        {

            return MakeImage(BytesToImage(imgBytes), width, height, makeMode);

        }

        /// <summary>

        /// 生成图片,采用等比例压缩方式

        /// </summary>

        /// <param name="originalImage">源图片</param>

        /// <param name="width">新图片宽度</param>

        /// <param name="height">新图片高度</param>

        /// <param name="makeMode">生成模式</param>

        /// <returns>生成后的图片流</returns>

        public static byte[] MakeImage(Image originalImage, int width, int height, ImageMakeMode makeMode)

        {

            byte[] bytes;

            // 生成的新图实际宽度及高度

            int towidth = width;

            int toheight = height;

            //新图在画布上的位置

            int x = 0;

            int y = 0;

            //要绘制的原图宽高

            int ow = originalImage.Width;

            int oh = originalImage.Height;

            if (makeMode == ImageMakeMode.KeepRatio)

            {

                ImageSize size = GetImageSize(originalImage.Width, originalImage.Height, width, height);

                towidth = (int)size.ImageWidth;

                toheight = (int)size.ImageHeight;

            }

            else

            {

                // 根据原图及欲生成的新图尺寸,计算新图的实际尺寸及其在"画布"上的位置       

                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;

                }

            }

            Image bitmap = new System.Drawing.Bitmap(towidth, toheight);

            Graphics g = System.Drawing.Graphics.FromImage(bitmap);

            try

            {

                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                g.Clear(Color.Transparent);

                g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),

                   new Rectangle(x, y, ow, oh),

                   GraphicsUnit.Pixel);

                using (MemoryStream ms = new MemoryStream())

                {

                    bitmap.Save(ms, originalImage.RawFormat);

                    bytes = ms.ToArray();

                }

            }

            catch (System.Exception e)

            {

                throw e;

            }

            finally

            {

                originalImage.Dispose();

                bitmap.Dispose();

                g.Dispose();

            }

            return bytes;

        }

        /// <summary>

        /// 生成图片,采用等比例压缩方式

        /// </summary>

        /// <param name="sourceImgPath">源图片路径</param>

        /// <param name="saveImgPath">新图片路径</param>

        /// <param name="width">新图片宽度</param>

        /// <param name="height">新图片高度</param>

        /// <param name="makeMode">生成模式</param>

        /// <returns></returns>

        public static bool MakeImage(string sourceImgPath, string saveImgPath, int width, int height, ImageMakeMode makeMode)

        {

            byte[] bytes = MakeImage(Image.FromFile(sourceImgPath), width, height, makeMode);

            using (FileStream stream = new FileStream(saveImgPath, FileMode.Create))

            {

                stream.Write(bytes, 0, bytes.Length);

            }

            bytes = null;

            return true;

        }

        /// <summary>

        /// 图片转换 Byte[] to Image

        /// </summary>

        /// <param name="buffer">byte[]</param>

        /// <returns></returns>

        public static Image BytesToImage(byte[] buffer)

        {

            Image image = null;

            if (buffer != null)

            {

                using (MemoryStream ms = new MemoryStream(buffer))

                {

                    image = System.Drawing.Image.FromStream(ms);

                }

            }

            return image;

        }

        /// <summary>

        /// 图片转换 Image to Byte[]

        /// </summary>

        /// <param name="img">Image</param>

        /// <returns></returns>

        public static Byte[] ImageToBytes(Image img)

        {

            byte[] bytes;

            using (MemoryStream ms = new MemoryStream())

            {

                img.Save(ms, img.RawFormat);

                bytes = ms.ToArray();

            }

            return bytes;

        }

        /// <summary>

        /// 获取一个图片按等比例缩小后的大小。

        /// </summary>

        /// <param name="imgWidth"></param>

        /// <param name="imgHeight"></param>

        /// <param name="maxWidth"></param>

        /// <param name="maxHeight"></param>

        /// <returns></returns>

        public static ImageSize GetImageSize(double imgWidth, double imgHeight, double maxWidth, double maxHeight)

        {

            ImageSize size = new ImageSize();

            double exportWidth = imgWidth;

            double exportHeight = imgHeight;

            if (imgWidth > imgHeight)  //如果宽度超过高度以宽度为准来压缩

            {

                if (imgWidth > maxWidth)  //如果图片宽度超过限制

                {

                    exportWidth = maxWidth;   //图片压缩后的宽度

                    exportHeight = imgHeight / (double)(imgWidth / exportWidth); //图片压缩后的高度

                }

            }

            else

            {

                if (imgHeight > maxHeight)

                {

                    exportHeight = maxHeight;

                    exportWidth = imgWidth / (double)(imgHeight / exportHeight);

                }

            }

            size.ImageWidth = exportWidth;

            size.ImageHeight = exportHeight;

            return size;

        }

        /// <summary>

        /// 图片转换

        /// </summary>

        /// <param name="imagepath">图片路径</param>

        /// <returns>byte[]二进制流</returns>

        public static byte[] GetPictureData(string imagepath)

        {

            try

            {

                using (FileStream fs = new FileStream(imagepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))

                {

                    byte[] byData = new byte[fs.Length];

                    fs.Read(byData, 0, byData.Length);

                    fs.Close();

                    fs.Dispose();

                    return byData;

                }

            }

            catch (Exception ex)

            {

                //图片转换异常

                throw ex;

            }

        }

        /// <summary>

        /// 图片(流)加水印

        /// </summary>

        /// <param name="by">图片二进制流</param>

        /// <param name="markText">水印文本</param>

        /// <returns></returns>

        public byte[] WaterMark(byte[] by, string markText)

        {

            MemoryStream ms = new MemoryStream(by);

            Bitmap bitmap = (Bitmap)Image.FromStream(ms);

            ms.Close();

            WaterMark(bitmap, new ImageWaterMarkContext(markText)

            {

                Margin = new Padding(5),

                TextBackColor = Color.Black,

                TextForeColor = Color.AntiqueWhite,

                TextBorderColor = Color.Transparent,

                Opacity = 0.3F

            });

            MemoryStream mstream = new MemoryStream();

            bitmap.Save(mstream, System.Drawing.Imaging.ImageFormat.Bmp);

            bitmap.Dispose();

            bitmap = null;

            byte[] bytes = mstream.GetBuffer();

            mstream.Close();

            return bytes;

        }

        /// <summary>

        /// 图片(流)加水印

        /// </summary>

        /// <param name="by">原图二进制流</param>

        /// <param name="markImage">水印图二进制流</param>

        /// <returns>byte[]二进制图片流</returns>

        public byte[] WaterMark(byte[] by, byte[] markImage)

        {

            //原图(流转图像)

            MemoryStream ms = new MemoryStream(by);

            Bitmap bitmap = (Bitmap)Image.FromStream(ms);

            ms.Close();

            //水印图(流转图像)

            MemoryStream markms = new MemoryStream(markImage);

            Bitmap markbitmap = (Bitmap)Image.FromStream(markms);

            markms.Close();

            WaterMark(bitmap, new ImageWaterMarkContext(markbitmap)

            {

                Margin = new Padding(5),

                TextBackColor = Color.Black,

                TextForeColor = Color.AntiqueWhite,

                TextBorderColor = Color.Transparent,

                Opacity = 0.3F

            });

            MemoryStream mstream = new MemoryStream();

            bitmap.Save(mstream, System.Drawing.Imaging.ImageFormat.Bmp);

            bitmap.Dispose();

            bitmap = null;

            byte[] bytes = mstream.GetBuffer();

            mstream.Close();

            return bytes;

        }

        /// <summary>

        /// 为图像加上水印(忽略gif格式)注:直接在原始图像上做处理。

        /// </summary>

        /// <param name="bitmap">需要处理的图像</param>

        /// <param name="context">水印上下文实例</param>

        public static void WaterMark(Bitmap bitmap, ImageWaterMarkContext context)

        {

            if (bitmap == null || context == null)

                return;

            //Gif不加水印的

            if (bitmap.RawFormat == ImageFormat.Gif)

                return;

            float width;//水印宽

            float height;//水印高

            float x = 0F;//坐标.x

            float y = 0F;//坐标.y

            Graphics g = Graphics.FromImage(bitmap);

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            Bitmap image = null;

            if (context.Image != null)

            {

                //图像水印

                width = context.Image.Width;

                height = context.Image.Height;

                image = context.Image;

            }

            else

            {

                //文本水印

                if (context.TextFont == null)

                    context.TextFont = ImageWaterMarkContext.DefaultTextFont;

                SizeF size = g.MeasureString(context.Text, context.TextFont);

                width = size.Width + 6F;

                height = size.Height + 6F;

                image = new Bitmap((int)width, (int)height, PixelFormat.Format32bppArgb);

                Graphics g2 = Graphics.FromImage(image);

                g2.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                if (context.TextBackColor == null)

                    context.TextBackColor = ImageWaterMarkContext.DefaultTextBackColor;

                if (context.TextForeColor == null)

                    context.TextForeColor = ImageWaterMarkContext.DefaultTextForeColor;

                if (context.TextBorderColor == null)

                    context.TextBorderColor = ImageWaterMarkContext.DefaultBorderColor;

                g2.Clear(context.TextBackColor);

                g2.DrawRectangle(new Pen(context.TextBorderColor, 1F), 0F, 0F, width - 2F, height - 2F);

                g2.DrawString(context.Text, context.TextFont, new SolidBrush(context.TextForeColor), 3, 3);

                g2.Dispose();

                g2 = null;

            }

            //水印超出范围

            if (width >= bitmap.Width || height >= bitmap.Height)

                return;

            //推算坐标

            switch (context.Location)

            {

                case ImageWaterMarkLocation.TopLeft:

                    x = context.Margin.Left;

                    y = context.Margin.Top;

                    break;

                case ImageWaterMarkLocation.TopCenter:

                    x = (bitmap.Width - width) / 2; y = context.Margin.Top;

                    break;

                case ImageWaterMarkLocation.TopRight:

                    x = bitmap.Width - context.Margin.Right - width; y = context.Margin.Top;

                    break;

                case ImageWaterMarkLocation.MiddleLeft:

                    x = context.Margin.Left; y = (bitmap.Height - height) / 2;

                    break;

                case ImageWaterMarkLocation.MiddleCenter:

                    x = (bitmap.Width - width) / 2; y = (bitmap.Height - height) / 2;

                    break;

                case ImageWaterMarkLocation.MiddleRight:

                    x = bitmap.Width - context.Margin.Right - width; y = (bitmap.Height - height) / 2;

                    break;

                case ImageWaterMarkLocation.BottomLeft:

                    x = context.Margin.Left; y = bitmap.Height - height - context.Margin.Bottom;

                    break;

                case ImageWaterMarkLocation.BottomCenter:

                    x = (bitmap.Width - width) / 2; y = bitmap.Height - height - context.Margin.Bottom;

                    break;

                case ImageWaterMarkLocation.BottomRight:

                    x = bitmap.Width - context.Margin.Right - width; y = bitmap.Height - height - context.Margin.Bottom;

                    break;

            }

            //图像水印

            image.SetResolution(bitmap.HorizontalResolution, bitmap.VerticalResolution);

            ImageAttributes imageAttributes = new ImageAttributes();

            imageAttributes.SetRemapTable(new ColorMap[]{

                    new ColorMap(){

                        OldColor= Color.FromArgb(255,0,255,0),

                        NewColor= Color.FromArgb(0,0,0,0),

                    }

                }, ColorAdjustType.Bitmap);

            if (context.Opacity < 0F || context.Opacity > 1F)

                context.Opacity = 0.51F;

            imageAttributes.SetColorMatrix(new ColorMatrix(new float[][]{

                    new float[]{1.0F,0.0F,0.0F,0.0F,0.0F},

                    new float[]{0.0F,1.0F,0.0F,0.0F,0.0F},

                    new float[]{0.0F,0.0F,1.0F,0.0F,0.0F},

                    new float[]{0.0F,0.0F,0.0F,context.Opacity,0.0F},//65透明度

                    new float[]{0.0F,0.0F,0.0F,0.0F,1.0F},

                }), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

            g.DrawImage(image, new Rectangle((int)x, (int)y, (int)width, (int)height), 0, 0, width, height, GraphicsUnit.Pixel, imageAttributes);

            g.Dispose();

            g = null;

            if (context.Image == null)

            {

                image.Dispose();

                image = null;

            }

        }

    }

    /// <summary>

    /// 等比率生成图片模式

    /// </summary>

    public enum ImageMakeMode

    {

        /// <summary>

        /// 固定尺寸,按照指定宽高生成

        /// </summary>

        KeepSize = 0,

        /// <summary>

        /// 固定比例,按照原图比例生成,新图宽高在指定宽高范围内

        /// </summary>

        KeepRatio = 1

    }

    /// <summary>

    /// 图像水印位置集

    /// </summary>

    public enum ImageWaterMarkLocation

    {

        /// <summary>

        /// 上-左

        /// </summary>

        TopLeft,

        /// <summary>

        /// 上-中

        /// </summary>

        TopCenter,

        /// <summary>

        /// 上-右

        /// </summary>

        TopRight,

        /// <summary>

        /// 中-左

        /// </summary>

        MiddleLeft,

        /// <summary>

        /// 中-中

        /// </summary>

        MiddleCenter,

        /// <summary>

        /// 中-右

        /// </summary>

        MiddleRight,

        /// <summary>

        /// 下-左

        /// </summary>

        BottomLeft,

        /// <summary>

        /// 下-中

        /// </summary>

        BottomCenter,

        /// <summary>

        /// 下-右

        /// </summary>

        BottomRight,

    }

    /// <summary>

    /// 图片尺寸

    /// </summary>

    public class ImageSize

    {

        /// <summary>

        /// 宽

        /// </summary>

        public double ImageWidth { get; set; }

        /// <summary>

        /// 高

        /// </summary>

        public double ImageHeight { get; set; }

    }

    /// <summary>

    /// 水印上下文类

    /// </summary>

    public class ImageWaterMarkContext

    {

        /// <summary>

        /// 默认边缘距离(5像素)

        /// </summary>

        public static readonly Padding DefaultMargin = new Padding(5);

        /// <summary>

        /// 默认文本字体(Arial,18号,粗体)

        /// </summary>

        public static readonly Font DefaultTextFont = new Font("楷体", 18F, FontStyle.Regular, GraphicsUnit.Pixel);

        /// <summary>

        /// 默认文本背景颜色(Color.WhiteSmoke,雾白色)

        /// </summary>

        public static readonly Color DefaultTextBackColor = Color.WhiteSmoke;

        /// <summary>

        /// 默认文本前景颜色(Color.Black,黑色)

        /// </summary>

        public static readonly Color DefaultTextForeColor = Color.Black;

        /// <summary>

        /// 默认文本边框颜色(Color.DimGray,暗灰色)

        /// </summary>

        public static readonly Color DefaultBorderColor = Color.DimGray;

        /// <summary>

        /// 水印位置

        /// </summary>

        public ImageWaterMarkLocation Location { get; set; }

        /// <summary>

        /// 边缘距离(单位:像素)

        /// </summary>

        public Padding Margin { get; set; }

        /// <summary>

        /// 文本水印

        /// </summary>

        public string Text { get; private set; }

        /// <summary>

        /// 文本字体

        /// </summary>

        public Font TextFont { get; set; }

        /// <summary>

        /// 文本背景颜色

        /// </summary>

        public Color TextBackColor { get; set; }

        /// <summary>

        /// 文本前景颜色

        /// </summary>

        public Color TextForeColor { get; set; }

        /// <summary>

        /// 文本边框颜色

        /// </summary>

        public Color TextBorderColor { get; set; }

        /// <summary>

        /// 透明度,默认是 0.51,即51的透明度,有效值0.00F-1.00F,值越大越不透明。

        /// </summary>

        public float Opacity { get; set; }

        /// <summary>

        /// 图像水印

        /// </summary>

        public Bitmap Image { get; private set; }

        /// <summary>

        /// 创建水印上下文实例(文本水印)

        /// </summary>

        /// <param name="text">文本水印</param>

        /// <param name="location">水印位置,默认为下-右</param>

        public ImageWaterMarkContext(string text, ImageWaterMarkLocation location = ImageWaterMarkLocation.BottomRight)

            : this(location)

        {

            if (string.IsNullOrEmpty(text))

                throw new ArgumentNullException("text", "文本水印内容不能为null或“”。");

            Text = text;

        }

        /// <summary>

        /// 创建水印上下文实例(图像水印)

        /// </summary>

        /// <param name="image">图像水印</param>

        /// <param name="location">水印位置,默认为下-右</param>

        public ImageWaterMarkContext(Bitmap image, ImageWaterMarkLocation location = ImageWaterMarkLocation.BottomRight)

            : this(location)

        {

            if (image == null)

                throw new ArgumentNullException("image", "图像水印不能为null。");

            Image = image;

        }

        /// <summary>

        /// 默认值

        /// </summary>

        /// <param name="location">水印位置</param>

        private ImageWaterMarkContext(ImageWaterMarkLocation location)

        {

            Location = location;

            Margin = DefaultMargin;

            TextFont = DefaultTextFont;

            TextBackColor = TextBackColor;

            TextForeColor = DefaultTextForeColor;

            TextBorderColor = DefaultBorderColor;

            Opacity = 0.51F;

        }

    }

}