水印的定義:水印一般是指在圖片上的一些版權信息文字,或者為了某種目的而對原始圖片上附加一些圖形或者文字。
水印的基本制作方法就是使用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( 255, 0, 255, 0 );
7 colorMap.NewColor = Color.FromArgb( 0, 0, 0, 0 );
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.0f, 0.0f},
14 new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
15 new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
16 new float[] {0.0f, 0.0f, 0.0f, 0.3f, 0.0f},
17 new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.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, 0, 0, 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( 153, 255, 255, 255 ) );
4 g.DrawString( wmText, font, brush, p, format );
5
6 SolidBrush brush2 = new SolidBrush( Color.FromArgb( 153, 0, 0, 0 ) );
7 g.DrawString( wmText, font, brush2, new PointF( p.X + 1, p.Y + 1 ), format );
8 }
當然,代碼裡面的注釋太少了,可能是非核心類,所以沒有注釋。當然,我們會在以後逐漸把注釋補足的。作為一個服務大眾的項目,注釋是不能缺少的,讓每個人看得懂的代碼,是我們的目標。
驗證碼的制作在 wojiluDrawingValidationCode.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( 0, 0, 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 &nbs