版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
在发布的图片上添加水印,已经成为保护图片版权的手段之一。水印可以是一段文字或是一张图片,通常情况下为了不影响图片本身的显示,往往使用半透明的水印。其实这就是对颜色中的透明度进行处理,即Color结构ARGB中的A分量(Alpha)进行处理。
【例 17.59 】【项目:code17-037】文字水印。
在本例中,在图像上绘制文字使用的是DrawString方法,其中Brush参数可以设置颜色,只需要使用带有透明度分量的颜色即可实现半透明的文字水印。
Bitmap sourceImg;
private void Form1_Load(object sender, EventArgs e)
{
picSource.SizeMode = PictureBoxSizeMode.StretchImage;
picDest.SizeMode = PictureBoxSizeMode.StretchImage;
//透明度从0-255
nudAlpha.Minimum = 0;
nudAlpha.Maximum = 255;
//默认不透明
nudAlpha.Value = 255;
sourceImg = (Bitmap)Image.FromFile("c:\\lessons\\zg.jpg");
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
picSource.Image = sourceImg;
}
private void btnDraw_Click(object sender, EventArgs e)
{
int logoOpacity = (int)nudAlpha.Value;
string logoText = txtString.Text;
Font logoFont =new Font(new FontFamily("隶书"), 60, FontStyle.Bold);
//绘制文字的默认颜色为白色
SolidBrush logoBrush =new SolidBrush(Color.FromArgb(logoOpacity, 255, 255, 255));
//绘制文字的起始位置
int logoLeft = 10;
int logoTop = 10;
Bitmap imgDest = (Bitmap)sourceImg.Clone();
Graphics g = Graphics.FromImage(imgDest);
g.DrawString(logoText, logoFont, logoBrush, logoLeft, logoTop);
g.Dispose();
picDest.Image = imgDest;
}
运行结果如下图所示:
\
图17-69 添加文字水印
【例 17.60 】【项目:code17-038】图片水印。
本例提供过了三种生成图片水印的方法:
一是像素处理方式。先读取水印图像的所有像素颜色,然后颜色上加上Alpha分量值,最后将每个像素绘制到目标图像指定的位置。由于既要处理像素透明,又要考虑在目标图像中定位,代码难度较大,可以考虑先处理像素生成半透明水印图像,再将此图像绘制到目标图像指定位置。
二是使用内存处理方式。在使用Bitmap.LockBits方法时,format参数使用Format32bppArgb成员,确保包含Alpha分量值,修改Alpha分量的值即可。**注意:**此时透明度、红色、绿色和蓝色四个分量的排列顺序为BGRA,同种分量在数组中的间隔为3。
三是使用颜色矩阵处理。在第17.3.4.1节已经学习使用颜色矩阵的基本知识。其中矩阵[R G B A W] 中A表示透明度,不透明时的值为255。而对应的5×5的矩阵中,只需要将(3,3)位置的数值设置为透明度值/255,最终得到的A'即透明度值:
图17-70 矩阵变换:透明度
R'=R*1+G*0+B*0+A*0+W*0 =R
G'=R*0+G*1+B*0+A*0+W*0 =G
B'=R*0+G*0+B*1+A*0+W*0 =B
A'=R*0+G*0+B*0+255*( Alpha/255) +W*0 =Alpha
W'=R*0+G*0+B*0+A*0+W*1 =W
由以上公式可见,R、G、B分量的值并没有改变,A分量的值变为设定的Alpha值,W值也不会影响透明度、红色、绿色和蓝色四个分量的值。
具体代码如下:
Bitmap imgsource;
private void Form1_Load(object sender, EventArgs e)
{
picSource.SizeMode = PictureBoxSizeMode.StretchImage;
picDest.SizeMode = PictureBoxSizeMode.StretchImage;
//透明度从0-255
nudAlpha.Minimum = 0;
nudAlpha.Maximum = 255;
//默认透明度为120
nudAlpha.Value = 120;
imgsource = (Bitmap)Image.FromFile("c:\\lessons\\zg.jpg");
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
picSource.Image = imgsource;
}
private void btnDraw_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "图片文件|*.jpg;*.png";
if (ofd.ShowDialog() == DialogResult.Cancel)
return;
Bitmap logoImg = (Bitmap)Image.FromFile(ofd.FileName);
int logoOpacity = (int)nudAlpha.Value;
int logoLeft = 10;
int logoTop = 10;
if(rbByPixel.Checked)
DrawLogo1(logoOpacity, logoImg, logoLeft, logoTop);
if( rbByMemory.Checked)
DrawLogo2(logoOpacity, logoImg, logoLeft, logoTop);
if(rbByMatrix.Checked)
DrawLogo3(logoOpacity, logoImg, logoLeft, logoTop);
}
//像素处理
private void DrawLogo1(int logoOpacity , Bitmap logoImg , int logoLeft, int logoTop)
{
Bitmap imgDest = (Bitmap)imgsource.Clone();
Graphics g = Graphics.FromImage(imgDest);
Bitmap imgLogoDest = new Bitmap(logoImg.Width, logoImg.Height);
Color c;
for(int i = 0;i< logoImg.Width;i++)
{
for(int j = 0;j< logoImg.Height;j++)
{
//获取每个像素的颜色
c = logoImg.GetPixel(i, j);
//将颜色加上A分量,最终生成半透明水印图像
imgLogoDest.SetPixel(i, j, Color.FromArgb(logoOpacity, c));
}
}
g.DrawImage(imgLogoDest, logoLeft, logoTop);
g.Dispose();
picDest.Image = imgDest;
}
//内存处理
private void DrawLogo2(int logoOpacity, Bitmap logoImg, int logoLeft, int logoTop)
{
Bitmap imgDest = (Bitmap)imgsource.Clone();
Graphics g = Graphics.FromImage(imgDest);
Bitmap logoDestImg = new Bitmap(logoImg.Width, logoImg.Height, PixelFormat.Format32bppArgb);
logoDestImg = (Bitmap)logoImg.Clone();
//注意:这里使用的是Format32bppArgb,确保有A分量
BitmapData destData = logoDestImg.LockBits(new Rectangle(0, 0, logoDestImg.Width, logoDestImg.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
IntPtr pSource = destData.Scan0;
int allBytes = destData.Stride * destData.Height;
byte[] rgbvalues = new byte[allBytes];
Marshal.Copy(pSource, rgbvalues, 0, allBytes);
int pos = 0;
int A = logoOpacity;
for(int j = 0;j< destData.Height;j++)
{
for(int i = 0;i< destData.Width;i++)
{
//只需要每隔4位,设置为A分量值
rgbvalues[pos + 3] = (byte)A;
pos = pos + 4;
}
pos = pos + destData.Stride - destData.Width * 4;
}
IntPtr pDest = destData.Scan0;
Marshal.Copy(rgbvalues, 0, pDest, allBytes);
logoDestImg.UnlockBits(destData);
g.DrawImage(logoDestImg, logoLeft, logoTop);
g.Dispose();
picDest.Image = imgDest;
}
//矩阵处理
private void DrawLogo3(int logoOpacity, Bitmap logoImg, int logoLeft, int logoTop)
{
Bitmap imgDest = (Bitmap)imgsource.Clone();
Graphics g = Graphics.FromImage(imgDest);
float Opacity = (float)logoOpacity / 255;
//进行变换的矩阵
float[][] matrixArray = {
new float[] { 1, 0, 0, 0, 0},
new float[] { 0, 1, 0, 0, 0},
new float[] { 0, 0, 1, 0, 0},
new float[] { 0, 0, 0, Opacity, 0},
new float[] { 0, 0, 0, 0, 1} };
ColorMatrix cMatrix = new ColorMatrix(matrixArray);
ImageAttributes imgAttr = new ImageAttributes();
imgAttr.SetColorMatrix(cMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
Rectangle recDest =new Rectangle(logoLeft, logoTop, logoImg.Width, logoImg.Height);
g.DrawImage(logoImg, recDest, 0, 0, logoImg.Width, logoImg.Height, GraphicsUnit.Pixel, imgAttr);
g.Dispose();
picDest.Image = imgDest;
}
运行结果如下图所示:
图17-71 添加图片水印
学习更多vb.net知识,请参看vb.net 教程 目录
学习更多C#知识,请参看C#教程 目录