C#給圖片加水印,可設置透明度,設置水印的位置可以看一下上一篇哈
/// <summary> /// Creating a Watermarked Photograph with GDI+ for .NET /// </summary> /// <param name="rSrcImgPath">原始圖片的物理路徑</param> /// <param name="rMarkImgPath">水印圖片的物理路徑</param> /// <param name="rMarkText">水印文字(不顯示水印文字設為空串)</param> /// <param name="rDstImgPath">輸出合成后的圖片的物理路徑</param> public void BuildWatermark(string rSrcImgPath, string rMarkImgPath, string rMarkText, string rDstImgPath) { //以下(代碼)從一個指定文件創建了一個Image 對象,然后為它的 Width 和 Height定義變量。 //這些長度待會被用來建立一個以24 bits 每像素的格式作為顏色數據的Bitmap對象。 Image imgPhoto = Image.FromFile(rSrcImgPath); int phWidth = imgPhoto.Width; int phHeight = imgPhoto.Height; Bitmap bmPhoto = new Bitmap(phWidth, phHeight, PixelFormat.Format24bppRgb); bmPhoto.SetResolution(72, 72); Graphics grPhoto = Graphics.FromImage(bmPhoto); //這個代碼載入水印圖片,水印圖片已經被保存為一個BMP文件,以綠色(A=0,R=0,G=255,B=0)作為背景顏色。 //再一次,會為它的Width 和Height定義一個變量。 Image imgWatermark = new Bitmap(rMarkImgPath); int wmWidth = imgWatermark.Width; int wmHeight = imgWatermark.Height; //這個代碼以100%它的原始大小繪制imgPhoto 到Graphics 對象的(x=0,y=0)位置。 //以后所有的繪圖都將發生在原來照片的頂部。 grPhoto.SmoothingMode = SmoothingMode.AntiAlias; grPhoto.DrawImage( imgPhoto, new Rectangle(0, 0, phWidth, phHeight), 0, 0, phWidth, phHeight, GraphicsUnit.Pixel); //為了最大化版權信息的大小,我們將測試7種不同的字體大小來決定我們能為我們的照片寬度使用的可能的最大大小。 //為了有效地完成這個,我們將定義一個整型數組,接着遍歷這些整型值測量不同大小的版權字符串。 //一旦我們決定了可能的最大大小,我們就退出循環,繪制文本 int[] sizes = new int[] { 16, 14, 12, 10, 8, 6, 4 }; Font crFont = null; SizeF crSize = new SizeF(); for (int i = 0;i < 7;i++) { crFont = new Font("arial", sizes[i], FontStyle.Bold); crSize = grPhoto.MeasureString(rMarkText, crFont); if ((ushort)crSize.Width < (ushort)phWidth) break; } //因為所有的照片都有各種各樣的高度,所以就決定了從圖象底部開始的5%的位置開始。 //使用rMarkText字符串的高度來決定繪制字符串合適的Y坐標軸。 //通過計算圖像的中心來決定X軸,然后定義一個StringFormat 對象,設置StringAlignment 為Center。 int yPixlesFromBottom = (int)(phHeight * .05); float yPosFromBottom = ((phHeight - yPixlesFromBottom) - (crSize.Height / 2)); float xCenterOfImg = (phWidth / 2); StringFormat StrFormat = new StringFormat(); StrFormat.Alignment = StringAlignment.Center; //現在我們已經有了所有所需的位置坐標來使用60%黑色的一個Color(alpha值153)創建一個SolidBrush 。 //在偏離右邊1像素,底部1像素的合適位置繪制版權字符串。 //這段偏離將用來創建陰影效果。使用Brush重復這樣一個過程,在前一個繪制的文本頂部繪制同樣的文本。 SolidBrush semiTransBrush2 = new SolidBrush(Color.FromArgb(153, 0, 0, 0)); grPhoto.DrawString(rMarkText, crFont, semiTransBrush2, new PointF(xCenterOfImg + 1, yPosFromBottom + 1), StrFormat); SolidBrush semiTransBrush = new SolidBrush( Color.FromArgb(153, 255, 255, 255)); grPhoto.DrawString(rMarkText, crFont, semiTransBrush, new PointF(xCenterOfImg, yPosFromBottom), StrFormat); //根據前面修改后的照片創建一個Bitmap。把這個Bitmap載入到一個新的Graphic對象。 Bitmap bmWatermark = new Bitmap(bmPhoto); bmWatermark.SetResolution( imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution); Graphics grWatermark = Graphics.FromImage(bmWatermark); //通過定義一個ImageAttributes 對象並設置它的兩個屬性,我們就是實現了兩個顏色的處理,以達到半透明的水印效果。 //處理水印圖象的第一步是把背景圖案變為透明的(Alpha=0, R=0, G=0, B=0)。我們使用一個Colormap 和定義一個RemapTable來做這個。 //就像前面展示的,我的水印被定義為100%綠色背景,我們將搜到這個顏色,然后取代為透明。 ImageAttributes imageAttributes = new ImageAttributes(); ColorMap colorMap = new ColorMap(); colorMap.OldColor = Color.FromArgb(255, 0, 255, 0); colorMap.NewColor = Color.FromArgb(0, 0, 0, 0); ColorMap[] remapTable = { colorMap }; //第二個顏色處理用來改變水印的不透明性。 //通過應用包含提供了坐標的RGBA空間的5x5矩陣來做這個。 //通過設定第三行、第三列為0.3f我們就達到了一個不透明的水平。結果是水印會輕微地顯示在圖象底下一些。 imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap); float[][] colorMatrixElements = { 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, 0.3f, 0.0f}, new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f} }; ColorMatrix wmColorMatrix = new ColorMatrix(colorMatrixElements); imageAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); //隨着兩個顏色處理加入到imageAttributes 對象,我們現在就能在照片右手邊上繪制水印了。 //我們會偏離10像素到底部,10像素到左邊。 int markWidth; int markHeight; //mark比原來的圖寬 if (phWidth <= wmWidth) { markWidth = phWidth - 10; markHeight = (markWidth * wmHeight) / wmWidth; } else if (phHeight <= wmHeight) { markHeight = phHeight - 10; markWidth = (markHeight * wmWidth) / wmHeight; } else { markWidth = wmWidth; markHeight = wmHeight; } int xPosOfWm = ((phWidth - markWidth) - 10); int yPosOfWm = 10; grWatermark.DrawImage(imgWatermark, new Rectangle(xPosOfWm, yPosOfWm, markWidth, markHeight), 0, 0, wmWidth, wmHeight, GraphicsUnit.Pixel, imageAttributes); //最后的步驟將是使用新的Bitmap取代原來的Image。 銷毀兩個Graphic對象,然后把Image 保存到文件系統。 imgPhoto = bmWatermark; grPhoto.Dispose(); grWatermark.Dispose(); imgPhoto.Save(rDstImgPath, ImageFormat.Jpeg); imgPhoto.Dispose(); imgWatermark.Dispose(); }