Login Gblog  
简单点~~~
 
文章全文
Goberl 发表于 2008-10-3 3:21:36

引言
   当我们在网站上展示发布的图片时,通常有必要在图片上打上水印或者版权信息,比如提供一些关于图片属于哪个组织或者个人的版权信息。如果通过手工给这些图片添加这类信息,通常会耗费时间并且不能使所有图片保持一致。这里可以用C#和GDI轻松完成这个程序。


概述
  下面将展示给你处理图像的各种技术,以下展示了部分列表:
    1.嵌在图片上的文本的位置与图像的尺寸相关。
    2.选择System.Drawing.Font中的合适字体尺寸以便于阅读。
    3.操作不透明的文本字符串。
    4.通过特定颜色的位图替换来实现透明。
    5.通过5×5的矩阵像素来改变图片的透明度。

定义图像



  这个程序的第一步是加载一个需要应用水印的图片。图片可以是任何尺寸和分辨率。在我们这个例子中,我们将用一个449×346,分辨列为72dpi的图片。
  要实现这个实例,我们先定义两个字符串。第一个String指明图片的输入输出所在的文件夹路径;第二个String用来存储我们应用到水印中的版权信息。

来自Goberl,转载请注明出处

string WorkingDirectory = @"C:\Projects\WaterMark";
string Copyright = "Copyright © 2002     - AP Photo/David Zalubowski";


  接下来,我们为需要打水印的图片创建一个Image对象,并定义两个变量存储这张图片的宽度和高度,他们将用于创建一个24 bits/像素的Bitmap对象,接着利用Bitmap对象创建一个 Graphics对象。

Image imgPhoto = Image.FromFile(WorkingDirectory +
         "\\watermark_photo.jpg");
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);

  下面这段代码载入一张背景颜色为绿色(A=0,R=0,G=255,B=0)格式为BMP的水印图片(这张图片将作为水印显示到上面载入的图片上),同时定义了存储图片宽和高的变量。

Image imgWatermark = new Bitmap(WorkingDirectory
            + "\\watermark.bmp");
int wmWidth = imgWatermark.Width;
int wmHeight = imgWatermark.Height;

第一步、添加水印字符串
   下面这段代码将把imgPhoto添加到Graphics对象中。原始图片的所有特征——宽度、高度、像素——都将就载入到Graphics对象中。

grPhoto.SmoothingMode = SmoothingMode.AntiAlias;
grPhoto.DrawImage(
    imgPhoto,                              
    new Rectangle(0, 0, phWidth, phHeight),
    0,                                     
    0,                                      
    phWidth,                               
    phHeight,                              
    GraphicsUnit.Pixel);

  为了更好地兼容版权字符串,我们将测试7种不同的字体大小,以便选出其中最合适的字体应用到我们的图片中。为了提高性能,我们定义了一个int数组来存储我们的字体大小,并利用循环来测试版权字符串的字体大小,一旦我们找到合适的字体就退出循环并向Graphics对象中写入字符串。

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(Copyright, crFont);
    if((ushort)crSize.Width < (ushort)phWidth)
    break;
}

  不同图片可能会有不同高度,我们将让字符串的垂直位置位于离图片底部5%处(字符串的中部位于5%处,而不是底部或者顶部位于5%处)。用版权字符串的高度来决定它所在的y方向上的坐标,通过计算图片中心位置并定义一个StringFormat对象,设置StringAlignment来使版权信息位于图片的中心。

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%(透明度的值为153)的 SolidBrush对象,绘制版权字符串时,并使其坐标位置在已计算的位置上向右和下各偏移1px,为了实现阴影效果,再创建一个颜色为白色的SolidBrush对象重复绘制一次版权字符串,并使其坐标位置直接为已计算的坐标位置。

SolidBrush semiTransBrush2 =
    new SolidBrush(Color.FromArgb(153, 0, 0,0));

grPhoto.DrawString(Copyright,                   
    crFont,                                     
    semiTransBrush2,                            
    new PointF(xCenterOfImg+1,yPosFromBottom+1),
    StrFormat);

SolidBrush semiTransBrush = new SolidBrush(
             Color.FromArgb(153, 255, 255, 255));

grPhoto.DrawString(Copyright,                
    crFont,                                  
    semiTransBrush,                          
    new PointF(xCenterOfImg,yPosFromBottom), 
    StrFormat);





第二步、添加水印图片
  为上述已经修改了的图片创建一个Bitmap,并将其载入到一个新建的Graphic对象中。

Bitmap bmWatermark = new Bitmap(bmPhoto);
bmWatermark.SetResolution(imgPhoto.HorizontalResolution,
            imgPhoto.VerticalResolution);

Graphics grWatermark =Graphics.FromImage(bmWatermark);

  为了获得半透明水印图片,将定义一个ImageAttributes 对象,通过两次颜色处理来设置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};

imageAttributes.SetRemapTable(remapTable,ColorAdjustType.Bitmap);

  第二步颜色处理为改变水印图片的透明度。这一步将用到一个包含了RGBA信息的5×5的矩阵像素,这个矩阵的第三行第三列被设置为0.3f以获得半透明效果。这步操作将使水印图片呈半透明。

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对象后,我们就可以让水印图片显示到图片的右上角了。水印图片的位置离顶上边缘10px,右侧边缘10px。

int xPosOfWm = ((phWidth - wmWidth)-10);
int yPosOfWm = 10;

grWatermark.DrawImage(imgWatermark,
    new Rectangle(xPosOfWm,yPosOfWm,wmWidth,  wmHeight),
    0,                 
    0,                  
    wmWidth,           
    wmHeight,           
    GraphicsUnit.Pixel,
    imageAttributes);

  最后一步,我们将用添加了水印的位图代替原始图片,释放Graphic对象并存储图像为文件。

来自Goberl,转载请注明出处

imgPhoto = bmWatermark;
grPhoto.Dispose();
grWatermark.Dispose();

\\watermark_final.jpg",
imgPhoto.Save(WorkingDirectory + "
    ImageFormat.Jpeg);
imgPhoto.Dispose();
imgWatermark.Dispose();

 

 


That's it! Compile the project, run it, and see what happens! The code is fairly straightforward if it all makes sense then these techniques can be used for 100's of different image manipulations. The possibilities are endless.


  原文来自:[http://www.codeproject.com/KB/GDI-plus/watermark.aspx]
  个人学习所用,英语水平有限,欢迎指正。Goberl翻译于2008年10月2日。源码下载

 

类别:Dev      标签:GDI , 英文翻译      浏览(487)
相关主题:
C#实现渐变色 生成缩略图——内存不足
评论列表:
新站长     发表于 2008-10-2 23:06:00
你的域名链接系统不错啊,可以看来路自动排名

是否有兴趣搞一个类似网页,就一个页面,加个分类功能,我想要一个这样全面的链接系统,简单的一个页面就可以了,



我是站长论坛的站长,有兴趣Q:5-5-05-9-33-31
发表评论
大名: ( *必填)
Email: (填写后,将收到Goberl对你的回复)
网址: (可选)
正文:
      记住信息?