当前位置: 爱符号 - 所有分类 - 桌面应用 - C# - C# 图像水印你做到什么程度了? 文本水印也玩透明!
C# 图像水印你做到什么程度了? 文本水印也玩透明! C# TuXiangShuiYinNiZuoDaoShiMeChengDuLiao? WenBenShuiYinYeWanTouMing!
符号空间 发表于:2013-07-17 14:59:43 阅读(12228)
关键词:C# C# 图像水印 图像水印 Image Image WaterMark WaterMark 文本水印 文本水印 透明 透明
摘要:此演示程序界面上的功能: 1.Location,水印的位置,可以定义6个位置点; 2.Margin,不知道各位研究过.NET的控件没有,都有这个属性,表示边距的意思,总不可能贴到边上去了吧 可定制的,不懂的可以多研究一个.NET控件这个属性,这是 System.Windows.Forms.Padding 类型 实际效果就是水印的位置会有一些变化 最终封装时,我是单独写了一个跟它完全一样的struct,因为不是所有时候都可以引用System.Windows.Forms的

最近本站会员提出要求,能否对上传的图片加上水印效果?

说心里话,以前就听过这个东西,也知道不麻烦,但是一直没有这类似的需求,也就没有去研究它。

今天,终于问题来了,我想是时候要研究它了。


网上找了很多代码,发现大部分是这样的:

1.针对图像类型的水印有透明处理

2.针对文本水印很弱无透明效果

3.有的是要求传入图像文件,并非Bitmap对象

4.有的输出直接到文件

5.有的调用参数众多,反之却可控制的参数很少


综合以上问题,我做了一个研究顺序:

1.实现图像类型的水印

2.实现文本类型的水印

3.为图像类型的水印加上透明效果

4.解决文本类型的水印无透明效果问题

5.参数众多,做到可控制,且调用简单


如何实现的就不具体写了,一开始我就解决的第5条,将参数写在一个类中,如:ImageWaterMarkContext,以后再多参数都放得下,调用的时候只有一个此类的实例。


下面贴出最终的核心代码:

    /// <summary>
    /// 图像水印扩展类
    /// </summary>
    public static class ImageWaterMarkExtensions {
        /// <summary>
        /// 为图像加上水印(忽略gif格式),直接在原始图像上做处理。
        /// </summary>
        /// <param name="bitmap">需要处理的图像</param>
        /// <param name="context">水印上下文实例</param>
        public static void WaterMark(this 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 + 10F;
                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;
            }

        }

    }



以下是运行效果图:



此演示程序界面上的功能:

1.Location,水印的位置,可以定义6个位置点

2.Margin,不知道各位研究过.NET的控件没有,都有这个属性,表示边距的意思,总不可能贴到边上去了吧

  可定制的,不懂的可以多研究一个.NET控件这个属性,这是 System.Windows.Forms.Padding 类型

  实际效果就是水印的位置会有一些变化

  最终封装时,我是单独写了一个跟它完全一样的struct,因为不是所有时候都可以引用System.Windows.Forms

3.Opacity,透明度,水印出现的透明度,解决文本水印时,我想了一个特殊的办法,网上仅此一例(如果还有别的地方有,就是巧合了,我反正是没有找到)

4.Color,点灰色的框,可以定义文本水印的边框颜色,点文字是文字的颜色,点中间部分是整体的背景

5.text 按钮,点击后就是演示文本水印效果

6.image  按钮,点击后就是演示图像类型的水印效果



程序代码 ImageWaterMarkDemo.zip



欢迎跟贴!!!


声明:以上内容仅代表作者观点,不代表爱符号赞成此内容或立场