zoukankan      html  css  js  c++  java
  • 我记录网站综合系统 技术原理解析[2:C# 水印和验证码的制作]

    代码位置:wojilu\Drawing\Watermark.cs

    水印的定义:水印一般是指在图片上的一些版权信息文字,或者为了某种目的而对原始图片上附加一些图形或者文字。

    水印的基本制作方法就是使用GDI+的方法在图片的制定位置上绘制文字或者图片。

    说到GDI+,一般用于Winform对于GUI的绘制,例如文本编辑器的制作,就是使用GDI函数绘制文字在窗体表面。其实GDI不仅可以绘制窗体,它可以绘制一切的Drawable的表面。

    我记录的水印制作就是利用GDI函数,进行原图和水印图片的合并,或者在原图上绘制文字。

    关键GDI函数:(System.Drawing.Graphics 类的方法)

    DrawImage  绘制图片

    DrawString  绘制文字

    这两个函数有大量的重载,具体请查阅MSDN。


     水印图片:

        水印图片一般是使用纯绿或者纯蓝背景色的图片,就和拍摄电影一样,在拍摄的时候,演员在绿色背景里面演戏,在后期制作的时候,绿色的背景都会被透明色所取代掉。在C#里面,我们使用SetRemapTable这个图像特性来完成这个工作。它的作用是让图片上面某个颜色被另一种颜色所替换掉。OldColor 就是要被取代掉的颜色,NewColor则是新的颜色。5-10行则是完成这样的操作。

         接下来就是将图片的所有点的透明度下降为原来的30%。这里将使用ColorMatrix来做。矩阵,在很多地方被大量使用,特别是变换的地方,例如图片的拉伸,缩放等等,都是利用了矩阵乘法的快速运算。这里也使用了矩阵来进行全像素的高速变换。仔细观察12行的矩阵的对角线上的数字:1,1,1,0.3,1 这些是倍数运算因子。对应则RGBAW的变换倍数。RGB不变,透明度为原来的0.3倍。W也不变。通过这种方法,就将图片的透明度降低了。

        这些颜色变换,在Draw方法执行时候,才进行变换。

     1         private static ImageAttributes getImageAttributes() {
     2 
     3             ImageAttributes imgAttr = new ImageAttributes();
     4 
     5             ColorMap colorMap = new ColorMap();
     6             colorMap.OldColor = Color.FromArgb( 25502550 );
     7             colorMap.NewColor = Color.FromArgb( 0000 );
     8             ColorMap[] remapTable = { colorMap };
     9 
    10             imgAttr.SetRemapTable( remapTable, ColorAdjustType.Bitmap );
    11 
    12             float[][] colorMatrixElements = { 
    13                new float[] {1.0f,  0.0f,  0.0f,  0.0f0.0f},
    14                new float[] {0.0f,  1.0f,  0.0f,  0.0f0.0f},
    15                new float[] {0.0f,  0.0f,  1.0f,  0.0f0.0f},
    16                new float[] {0.0f,  0.0f,  0.0f,  0.3f0.0f},
    17                new float[] {0.0f,  0.0f,  0.0f,  0.0f1.0f}
    18             };
    19 
    20             ColorMatrix wmColorMatrix = new ColorMatrix( colorMatrixElements );
    21             imgAttr.SetColorMatrix( wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap );
    22 
    23             return imgAttr;
    24         }

    水印绘制的地方,也没有必要贴全部代码了

    1             ImageAttributes imgAttr = getImageAttributes();
    2             Rectangle rect = getPicPoint( src, wm, wp );
    3 
    4             g.DrawImage( wm, rect, 00, wm.Width, wm.Height, GraphicsUnit.Pixel, imgAttr );

    第一行,取得刚才那个变换规则

    第二行,取得绘制水印的矩形:我们可以指定水印的位置,比如左上角,右下角等等。通过位置的指定,获得不同的绘制区域的矩形。不过,getPicPoint 这个方法名称不好,让人误以为返回一个Point对象,其实是一个矩阵对象。建议换为getPicPosition或者getPicRect

    第三行就是绘制,在指定地方,使用指定颜色变换,绘制指定图片。

    绘制水印文字就相当简单了,使用一个透明的笔刷在图片上绘制水印即可。

      FontAndSize fs = FontAndSize.GetValue( g, words, "arial", fontSize, src.Width );
      PointF p 
    = getTextPoint( src, fs.size, wp );
      StringFormat sf 
    = getStringFormat();

      drawText( g, words, fs.font, p, sf );

    当然,这里我记录用了两种颜色绘制出文字,达到具有阴影效果文字特效。可以看出作者非常用心在开发我记录啊。。。。

    1         private static void drawText( Graphics g, String wmText, Font font, PointF p, StringFormat format ) {
    2 
    3             SolidBrush brush = new SolidBrush( Color.FromArgb( 153255255255 ) );
    4             g.DrawString( wmText, font, brush, p, format );
    5 
    6             SolidBrush brush2 = new SolidBrush( Color.FromArgb( 153000 ) );
    7             g.DrawString( wmText, font, brush2, new PointF( p.X + 1, p.Y + 1 ), format );
    8         }

    当然,代码里面的注释太少了,可能是非核心类,所以没有注释。当然,我们会在以后逐渐把注释补足的。作为一个服务大众的项目,注释是不能缺少的,让每个人看得懂的代码,是我们的目标。

    验证码的制作在 wojilu\Drawing\ValidationCode.cs

    验证码的制作可以分为3个步骤

    1.绘制一个带有噪点的背景

    2.绘制验证码

    3.最上层再绘制一些噪点

     1         public Image CreateImage( String code, int width, int height, String fontFamily ) {
     2 
     3             Bitmap bm = new Bitmap( width, height );
     4 
     5             using (Graphics g = Graphics.FromImage( bm )) {
     6 
     7                 g.SmoothingMode = SmoothingMode.AntiAlias;
     8 
     9                 HatchBrush brush = new HatchBrush( HatchStyle.SmallConfetti, Color.LightGray, Color.White );
    10                 Rectangle rect = new Rectangle( 00, width, height );
    11                 g.FillRectangle( brush, rect );
    12 
    13                 int fontsize = rect.Height + 1;
    14                 FontAndSize size = FontAndSize.GetValue( g, code, fontFamily, fontsize, bm.Width );
    15 
    16                 GraphicsPath gpath = getGraphicsPath( code, size.font, rect );
    17 
    18                 Color brushColor = ColorTranslator.FromHtml( "#000000" );
    19                 brush = new HatchBrush( HatchStyle.Divot, brushColor, Color.DarkGray );
    20                 g.FillPath( brush, gpath );
    21 
    22                 addRandomNoise( g, rect );
    23 
    24             }
    25             return bm;
    26         }
    27 
    28         private void addRandomNoise( Graphics g, Rectangle rect ) {
    29 
    30             HatchBrush brush = new HatchBrush( HatchStyle.Weave, Color.LightGray, Color.White );
    31 
    32             int m = Math.Max( rect.Width, rect.Height );
    33             for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) {
    34                 int x = rd.Next( rect.Width );
    35                 int y = rd.Next( rect.Height );
    36                 g.FillEllipse( brush, x, y, 23 );
    37             }
    38         }

          这里使用的是一个比较特别的笔刷HatchBrush,这个笔刷可以绘制出一些比较特别的效果,例如绘制验证码背景时候用到的HatchStyle.SmallConfetti ,绘制最上层噪点用的HatchStyle.Weave。灵活运用这些花纹的话,可以绘制出各种效果的验证码。当然wojilu的源代码并不是没有任何问题的,毕竟只有一个人在开发。这里的m这个变量看不出什么意义。

    关于我记录系统的验证码,已经做了很好的封装了,您可以直接使用,具体的使用方法参见官网文档:

    http://www.wojilu.com/Common/Page/71

    MSDN参考:

    ImageAttributes:

    http://msdn.microsoft.com/zh-cn/library/system.drawing.imaging.imageattributes.aspx

    ImageAttributes.SetRemapTable:

    http://msdn.microsoft.com/zh-cn/library/system.drawing.imaging.imageattributes.setremaptable.aspx

    ColorMatrix :

    http://msdn.microsoft.com/en-us/library/system.drawing.imaging.colormatrix.aspx

    我记录网址 http://www.wojilu.com/

    欢迎大家加入我记录开发团队

  • 相关阅读:
    BZOJ3752 : Hack
    XIV Open Cup named after E.V. Pankratiev. GP of SPb
    XIII Open Cup named after E.V. Pankratiev. GP of Ukraine
    BZOJ2087 : [Poi2010]Sheep
    BZOJ2080 : [Poi2010]Railway
    BZOJ2082 : [Poi2010]Divine divisor
    Moscow Pre-Finals Workshop 2016. National Taiwan U Selection
    XIII Open Cup named after E.V. Pankratiev. GP of Asia and South Caucasus
    XIII Open Cup named after E.V. Pankratiev. GP of Azov Sea
    XIII Open Cup named after E.V. Pankratiev. GP of SPb
  • 原文地址:https://www.cnblogs.com/TextEditor/p/2078606.html
Copyright © 2011-2022 走看看