相关文件下载:
1. 给图片添加水印的类库(dll)文件:ImageHandler.dll (18.00 kb)
2. 整个类库项目文件:ImageHandler.rar (45.03 kb)
摘要:
本文提供了一个给图片添加水印的C#类库,首先介绍了它的使用方法,其次介绍了该类库的结构,最后公开了它的源代码以及整个项目文件。
简介:
上篇文章介绍了使用C#及GDI+技术给图片添加水印的原理和技术细节。本文使用其技术做底层实现,采用模板设计模式架构,提供了一个高复用性与易扩展的图片处理类库。
一、类库的使用:
将类库(ImageHandler.dll (18.00 kb))复制到你的工程Bin文件夹后,在你的代码中添加zizhujy.ImageHandler命名空间,然后打开你要添加水印的图片,实例化一个zizhujy.ImageHandler中的Watermarker类,添加你想要的水印,完毕。就是如此简单!它可以被引用到Windows Console Application、Windows Form Application、Web Application、Web Service Application 等等工程中,以下以ASP.NET MVC 3 Application为例,就文字水印与图片水印分别列出三个代码实例。
1. 添加文字水印:
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using zizhujy.ImageHandler;
namespace zizhujy.Controllers
{
public class TestController : Controller
{
public void AddWatermark()
{
Image originImage = Image.FromFile(@"C:\source.jpg");
TextWatermarker txtWatermarker = new TextWatermarker(originImage, "www.zizhujy.com");
txtWatermarker.AddWatermark();
// Response and show the watermarked image in the browser
Response.ContentType = "image/jpeg";
txtWatermarker.WatermarkedImage.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
txtWatermarker.Dispose();
originImage.Dispose();
}
}
}
效果:
2. 添加图片水印:
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using zizhujy.ImageHandler;
namespace zizhujy.Controllers
{
public class TestController : Controller
{
public void AddWatermark()
{
Image originImage = Image.FromFile(@"C:\source.jpg");
Image watermark = Image.FromFile(@"C:\clock.png");
ImageWatermarker imgWatermarker = new ImageWatermarker(originImage, watermark);
imgWatermarker.AddWatermark();
// Response and show the watermarked image in the browser
Response.ContentType = "image/jpeg";
imgWatermarker.WatermarkedImage.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
imgWatermarker.Dispose();
watermark.Dispose();
originImage.Dispose();
}
}
}
效果:
3. 同时添加图片水印和文字水印:
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using zizhujy.ImageHandler;
namespace zizhujy.Controllers
{
public class TestController : Controller
{
public void AddWatermark()
{
// First, add the image watermark
Image originImage = Image.FromFile(@"C:\source.jpg");
Image watermark = Image.FromFile(@"C:\clock.png");
ImageWatermarker imgWatermarker = new ImageWatermarker(originImage, watermark);
// You can set the watermark size, if you not then the watermark will be its original size by default
imgWatermarker.SetWatermarkHeight(80);
imgWatermarker.AddWatermark();
// Second, add the text watermark
TextWatermarker txtWatermarker = new TextWatermarker(imgWatermarker.WatermarkedImage, "www.zizhujy.com");
// You can set the position of the watermark
txtWatermarker.Position = WatermarkPostion.TopLeft;
txtWatermarker.AddWatermark();
// Response and show the watermarked image in the browser
Response.ContentType = "image/jpeg";
// Note: save the secondly watermarked image
// (txtWatermarker not imgWatermarker because the txtWatermarker comes after than imgWatermarker)
txtWatermarker.WatermarkedImage.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
imgWatermarker.Dispose();
watermark.Dispose();
originImage.Dispose();
}
}
}
效果:
二、类库的结构(设计模式)
此类库采用了模板设计模式。因为对于给图片加水印,至少分为文本水印、图片水印两种。而不同的水印,将其添加到图片上的算法是一样的。即
- 获取源图片
- 获取水印
- 计算水印的位置Point (x,y)
- 计算水印的大小Size (width, height)
- 在源图片的Point位置处,以Size尺寸,将水印绘制出来,并返回新的图片
因此很自然想到使用模板设计模式,将以上算法封装在模板类Watermarker类中。对于图片水印与文本水印如何添加到源图片上,其方法是不一样的(详见上篇文章说明),故上述第5步,绘制水印的方法应该是抽象的,由具体的类来给予实现,即分别在ImageWatermarker和TextWatermarker中实现。
类图结构如下:
很简单明了,后面三个Enum是用来表示水印在源图片上出现的位置的struct结构体。
以下分别看每个类的结构:
三、类库的源码
先看模板类Watermarker.cs的源码(三个Enum结构体的代码也在这个文件中):
using System;
using System.Drawing;
namespace zizhujy.ImageHandler
{
///
/// Watermarker Template class
///
public abstract class Watermarker : IDisposable
{
#region Properties
private Image originImage;
public Image OriginImage
{
get
{
return originImage;
}
set
{
originImage = value;
}
}
private Image watermarkedImage;
public Image WatermarkedImage
{
get
{
return watermarkedImage;
}
set
{
watermarkedImage = value;
}
}
private SizeF watermarkSize;
protected SizeF WatermarkSize
{
get
{
return watermarkSize;
}
set
{
watermarkSize = value;
}
}
private float x;
protected float X
{
get
{
return x;
}
set
{
x = value;
}
}
private float y;
protected float Y
{
get
{
return y;
}
set
{
y = value;
}
}
private bool computeX = true;
public bool ComputeX
{
get { return computeX; }
}
private bool computeY = true;
public bool ComputeY
{
get { return computeY; }
}
private WatermarkHorizontalPostion hPos;
public WatermarkHorizontalPostion HorizontalPosition
{
get
{
return hPos;
}
set
{
computeX = true;
hPos = value;
}
}
private WatermarkVerticalPostion vPos;
public WatermarkVerticalPostion VerticalPosition
{
get
{
return vPos;
}
set
{
computeY = true;
vPos = value;
}
}
public WatermarkPostion Position
{
get
{
return GetPosition(this.HorizontalPosition , this.VerticalPosition) ;
}
set
{
this.HorizontalPosition = GetHorizentalPosition(value);
this.VerticalPosition = GetVerticalPosition(value);
}
}
private int hMarginPixel;
public int HorizontalMarginPixel
{
get
{
return hMarginPixel;
}
set
{
hMarginPixel = value;
}
}
private int vMarginPixel;
public int VerticalMarginPixel
{
get
{
return vMarginPixel;
}
set
{
vMarginPixel = value;
}
}
public double HorizontalMarginPercent
{
get
{
return this.HorizontalMarginPixel / this.OriginImage.Width;
}
set
{
double percent = value > 1 ? 1 : (value < 0 ? 0 : value);
this.HorizontalMarginPixel = (int)(this.OriginImage.Width * percent);
}
}
public double VerticalMarginPercent
{
get
{
return this.VerticalMarginPixel / this.OriginImage.Height;
}
set
{
double percent = value > 1 ? 1 : (value < 0 ? 0 : value);
this.VerticalMarginPixel = (int)(this.originImage.Height * percent);
}
}
private Color shadowColor;
public Color ShadowColor
{
get
{
return shadowColor;
}
set
{
shadowColor = value;
}
}
private Color foreColor;
public Color ForeColor
{
get
{
return foreColor;
}
set
{
foreColor = value;
}
}
public double ShadowOpacity
{
get
{
return shadowColor.A / 255;
}
set
{
double percent = value > 1 ? 1 : (value < 0 ? 0 : value);
int alpha = (int)(255 * percent);
shadowColor = Color.FromArgb(alpha, shadowColor);
}
}
public virtual double ForegroundOpacity
{
get
{
return foreColor.A / 255;
}
set
{
double percent = value > 1 ? 1 : (value < 0 ? 0 : value);
int alpha = (int)(255 * percent);
foreColor = Color.FromArgb(alpha, foreColor);
}
}
private int shadowOffsetX;
public int ShadowOffsetX
{
get
{
return shadowOffsetX;
}
set
{
shadowOffsetX = value;
}
}
private int shadowOffsetY;
public int ShadowOffsetY
{
get
{
return shadowOffsetY;
}
set
{
shadowOffsetY = value;
}
}
#endregion
#region Contructor
public Watermarker(Image originImage)
{
this.OriginImage = originImage;
// 默认值
this.ShadowColor = Color.FromArgb(153, 0, 0, 0);
this.ForeColor = Color.FromArgb(153, 255, 255, 255);
this.ShadowOffsetX = 1;
this.ShadowOffsetY = 1;
this.Position = WatermarkPostion.BottomRight;
this.HorizontalMarginPixel = 10;
this.VerticalMarginPixel = 10;
}
#endregion
#region Methods
public void SetX(float x)
{
this.X = x;
computeX = false;
}
public void SetY(float y)
{
this.Y = y;
computeY = false;
}
public void SetXY(float x, float y)
{
SetX(x);
SetY(y);
}
///
/// Add water mark to original image
///
public Image AddWatermark()
{
ComputeWatermarkSize();
UpdateXY();
watermarkedImage = AddWatermarkToOriginImage();
return watermarkedImage;
}
///
/// hook
///
///
protected virtual SizeF ComputeWatermarkSize()
{
this.WatermarkSize = new SizeF(100f, 50f);
return this.WatermarkSize;
}
///
/// hook
///
protected virtual Image AddWatermarkToOriginImage()
{
return originImage;
}
///
/// hook
///
protected virtual void UpdateXY()
{
if (this.ComputeX)
{
switch (this.HorizontalPosition)
{
case WatermarkHorizontalPostion.Left:
this.X = this.HorizontalMarginPixel;
break;
case WatermarkHorizontalPostion.Center:
this.X = this.OriginImage.Width / 2 - this.WatermarkSize.Width / 2;
break;
case WatermarkHorizontalPostion.Right:
this.X = (this.OriginImage.Width - this.HorizontalMarginPixel - this.WatermarkSize.Width);
break;
default:
break;
}
}
if (this.ComputeY)
{
switch (this.VerticalPosition)
{
case WatermarkVerticalPostion.Top:
this.Y = this.VerticalMarginPixel;
break;
case WatermarkVerticalPostion.Middle:
this.Y = this.OriginImage.Height / 2 - this.WatermarkSize.Height / 2;
break;
case WatermarkVerticalPostion.Bottom:
this.Y = (this.OriginImage.Height - this.VerticalMarginPixel - this.WatermarkSize.Height);
break;
default:
break;
}
}
}
private static WatermarkHorizontalPostion GetHorizentalPosition(WatermarkPostion pos)
{
// Mask: 000 111
return (WatermarkHorizontalPostion)((char)pos & (char)0x07);
}
private static WatermarkVerticalPostion GetVerticalPosition(WatermarkPostion pos)
{
// Mask: 111 000
return (WatermarkVerticalPostion)((char)pos & (char)0x38);
}
private static WatermarkPostion GetPosition(WatermarkHorizontalPostion hPos, WatermarkVerticalPostion vPos)
{
return (WatermarkPostion)((char)hPos | (char)vPos);
}
#endregion
#region IDisposable 成员
public virtual void Dispose()
{
this.OriginImage.Dispose();
this.WatermarkedImage.Dispose();
}
#endregion
}
public enum WatermarkPostion
{
TopLeft = 0x24, // 100 100
TopCenter = 0x22, // 100 010
TopRight = 0x21, // 100 001
MiddleLeft = 0x14, // 010 100
MiddleCenter = 0x12, // 010 010
MiddleRight = 0x11, // 010 001
BottomLeft = 0x0C, // 001 100
BottomCenter = 0x0A, // 001 010
BottomRight = 0x09, // 001 001
}
public enum WatermarkHorizontalPostion
{
Left = 0x04, // 000 100
Center = 0x02, // 000 010
Right = 0x01, // 000 001
}
public enum WatermarkVerticalPostion
{
Top = 0x20, // 100 000
Middle = 0x10, // 010 000
Bottom = 0x08, // 001 000
}
}
再来分别看加图片水印的类ImageWatermarker.cs与加文本水印的类TextWatermark.cs的源码:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
namespace zizhujy.ImageHandler
{
public class ImageWatermarker : Watermarker
{
#region Properties
private Image watermarkImage;
public Image WatermarkImage
{
get
{
return watermarkImage;
}
set
{
watermarkImage =value;
}
}
private ImageAttributes imageAttributes = new ImageAttributes();
public ImageAttributes ImageAttributes
{
get
{
return imageAttributes;
}
set
{
imageAttributes = value;
}
}
private List colorMaps = new List();
public List ColorMaps
{
get
{
return colorMaps;
}
set { colorMaps = value; }
}
public float[][] ColorMatrixElements
{
get
{
if (this.ColorMatrix != null)
{
return new float[][] {
new float[] {this.ColorMatrix.Matrix00, this.ColorMatrix.Matrix01, this.ColorMatrix.Matrix02, this.ColorMatrix.Matrix03, this.ColorMatrix.Matrix04},
new float[] {this.ColorMatrix.Matrix10, this.ColorMatrix.Matrix11, this.ColorMatrix.Matrix12, this.ColorMatrix.Matrix13, this.ColorMatrix.Matrix14},
new float[] {this.ColorMatrix.Matrix20, this.ColorMatrix.Matrix21, this.ColorMatrix.Matrix22, this.ColorMatrix.Matrix23, this.ColorMatrix.Matrix24},
new float[] {this.ColorMatrix.Matrix30, this.ColorMatrix.Matrix31, this.ColorMatrix.Matrix32, this.ColorMatrix.Matrix33, this.ColorMatrix.Matrix34},
new float[] {this.ColorMatrix.Matrix40, this.ColorMatrix.Matrix41, this.ColorMatrix.Matrix42, this.ColorMatrix.Matrix43, this.ColorMatrix.Matrix44}
};
}
else
{
return null;
}
}
set
{
this.ColorMatrix.Matrix00 = value[0][0];
this.ColorMatrix.Matrix01 = value[0][1];
this.ColorMatrix.Matrix02 = value[0][2];
this.ColorMatrix.Matrix03 = value[0][3];
this.ColorMatrix.Matrix04 = value[0][4];
this.ColorMatrix.Matrix10 = value[1][0];
this.ColorMatrix.Matrix11 = value[1][1];
this.ColorMatrix.Matrix12 = value[1][2];
this.ColorMatrix.Matrix13 = value[1][3];
this.ColorMatrix.Matrix14 = value[1][4];
this.ColorMatrix.Matrix20 = value[2][0];
this.ColorMatrix.Matrix21 = value[2][1];
this.ColorMatrix.Matrix22 = value[2][2];
this.ColorMatrix.Matrix23 = value[2][3];
this.ColorMatrix.Matrix24 = value[2][4];
this.ColorMatrix.Matrix30 = value[3][0];
this.ColorMatrix.Matrix31 = value[3][1];
this.ColorMatrix.Matrix32 = value[3][2];
this.ColorMatrix.Matrix33 = value[3][3];
this.ColorMatrix.Matrix34 = value[3][4];
this.ColorMatrix.Matrix40 = value[4][0];
this.ColorMatrix.Matrix41 = value[4][1];
this.ColorMatrix.Matrix42 = value[4][2];
this.ColorMatrix.Matrix43 = value[4][3];
this.ColorMatrix.Matrix44 = value[4][4];
}
}
private ColorMatrix colorMatrix;
public ColorMatrix ColorMatrix
{
get
{
return colorMatrix;
}
set
{
colorMatrix = value;
}
}
private bool keepScale;
public bool KeepScale
{
get { return keepScale; }
set { keepScale = value; }
}
public override double ForegroundOpacity
{
get
{
return base.ForegroundOpacity;
}
set
{
double percent = value > 1 ? 1 : (value < 0 ? 0 : value);
base.ForegroundOpacity = percent;
this.ColorMatrix.Matrix33 = (float)percent;
}
}
#endregion
#region Constructor
public ImageWatermarker(Image originImage, Image watermarkImage)
: base(originImage)
{
this.WatermarkImage = watermarkImage;
// Default values
this.ColorMaps.Add(new ColorMap());
this.ColorMaps[0].OldColor = Color.FromArgb(255, 255, 255, 255);
this.ColorMaps[0].NewColor = Color.FromArgb(0, 0, 0, 0);
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}
};
this.ColorMatrix = new ColorMatrix(colorMatrixElements);
this.WatermarkSize = this.WatermarkImage.Size;
this.KeepScale = true;
}
#endregion
#region Methods
protected override SizeF ComputeWatermarkSize()
{
return this.WatermarkSize;
}
protected override Image AddWatermarkToOriginImage()
{
this.WatermarkedImage = this.OriginImage;
Graphics watermarkGraphic = Graphics.FromImage(this.WatermarkedImage);
this.ImageAttributes.SetRemapTable(this.ColorMaps.ToArray(), ColorAdjustType.Bitmap);
this.ImageAttributes.SetColorMatrix(this.ColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
watermarkGraphic.DrawImage(this.WatermarkImage,
new Rectangle((int)this.X, (int)this.Y, (int)this.WatermarkSize.Width, (int)this.WatermarkSize.Height),
0, 0, this.WatermarkImage.Width, this.WatermarkImage.Height,
GraphicsUnit.Pixel, this.ImageAttributes);
watermarkGraphic.Dispose();
imageAttributes.Dispose();
return this.WatermarkedImage;
}
public void SetWatermarkWidth(int width)
{
float height = this.WatermarkSize.Height;
if (this.KeepScale)
{
height = height * width / this.WatermarkSize.Width;
}
this.WatermarkSize = new SizeF(width, height);
}
public void SetWatermarkHeight(int height)
{
float width = this.WatermarkSize.Width;
if (this.KeepScale)
{
width = width * height / this.WatermarkSize.Height;
}
this.WatermarkSize = new SizeF(width, height);
}
public void SetWatermarkSize(int width, int height)
{
this.WatermarkSize = new SizeF(width, height);
this.KeepScale = false;
}
public override void Dispose()
{
base.Dispose();
this.WatermarkImage.Dispose();
}
#endregion
}
}
using System;
using System.Drawing;
using System.Collections.Generic;
namespace zizhujy.ImageHandler
{
public class TextWatermarker : Watermarker
{
#region Properties
private string watermarkText;
public string WatermarkText
{
get
{
return watermarkText;
}
set
{
watermarkText = value;
}
}
// 自动计算最合适的水印文本字体大小
private bool autoSize = true;
public bool AutoSize
{
get
{
return autoSize;
}
set
{
autoSize = value;
}
}
private double fontSizePercent;
public double FontSizePercent
{
get { return fontSizePercent; }
set {
fontSizePercent = value > 1 ? 1 : (value <= 0.01 ? 0.01 : value);
}
}
private List<Font> fonts = new List<Font>();
public List<Font> Fonts
{
get
{
return fonts;
}
set
{
fonts = value;
}
}
private Font bestFont = new Font("Arial", 12, FontStyle.Regular, GraphicsUnit.Pixel);
public Font BestFont{
get{
return bestFont;
}
set
{
bestFont = value;
}
}
private StringFormat StringFormat
{
get
{
StringFormat format = new StringFormat();
if (this.ComputeX)
{
switch (this.HorizontalPosition)
{
case WatermarkHorizontalPostion.Left:
format.Alignment = StringAlignment.Near;
break;
case WatermarkHorizontalPostion.Center:
format.Alignment = StringAlignment.Center;
break;
case WatermarkHorizontalPostion.Right:
format.Alignment = StringAlignment.Far;
break;
}
}
else
{
format.Alignment = StringAlignment.Near;
}
return format;
}
}
#endregion
#region Constructor
public TextWatermarker(Image originImage, string watermarkText) : base(originImage)
{
this.WatermarkText = watermarkText;
// Default values
this.Fonts.Add(new Font("Arial", 18, FontStyle.Regular, GraphicsUnit.Pixel));
this.Fonts.Add(new Font("Arial", 16, FontStyle.Regular, GraphicsUnit.Pixel));
this.Fonts.Add(new Font("Arial", 14, FontStyle.Regular, GraphicsUnit.Pixel));
this.Fonts.Add(new Font("Arial", 12, FontStyle.Regular, GraphicsUnit.Pixel));
this.Fonts.Add(new Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Pixel));
this.Fonts.Add(new Font("Arial", 8, FontStyle.Regular, GraphicsUnit.Pixel));
this.Fonts.Add(new Font("Arial", 6, FontStyle.Regular, GraphicsUnit.Pixel));
this.Fonts.Add(new Font("Arial", 4, FontStyle.Regular, GraphicsUnit.Pixel));
this.FontSizePercent = 30.00 / 480.00;
this.AutoSize = true;
}
#endregion
#region Methods
public void ChangeFontFamily(string fontFamily)
{
FontFamily ff = new FontFamily(fontFamily);
for (int i = 0; i < this.Fonts.Count; i++)
{
this.Fonts[i] = new Font(ff, this.Fonts[i].Size, this.Fonts[i].Style, this.Fonts[i].Unit, this.Fonts[i].GdiCharSet, this.Fonts[i].GdiVerticalFont);
}
this.BestFont = new Font(ff, this.BestFont.Size, this.BestFont.Style, this.BestFont.Unit, this.BestFont.GdiCharSet, this.BestFont.GdiVerticalFont);
}
protected override SizeF ComputeWatermarkSize()
{
FindAvailableMaxSizedFont();
return this.WatermarkSize;
}
protected override void UpdateXY()
{
if (this.ComputeX)
{
switch (this.HorizontalPosition)
{
case WatermarkHorizontalPostion.Left:
this.X = this.HorizontalMarginPixel;
break;
case WatermarkHorizontalPostion.Center:
this.X = this.OriginImage.Width / 2;
break;
case WatermarkHorizontalPostion.Right:
this.X = (this.OriginImage.Width - this.HorizontalMarginPixel);
break;
default:
break;
}
}
if (this.ComputeY)
{
switch (this.VerticalPosition)
{
case WatermarkVerticalPostion.Top:
this.Y = this.VerticalMarginPixel;
break;
case WatermarkVerticalPostion.Middle:
this.Y = this.OriginImage.Height / 2 - this.WatermarkSize.Height / 2;
break;
case WatermarkVerticalPostion.Bottom:
this.Y = (this.OriginImage.Height - this.VerticalMarginPixel - this.WatermarkSize.Height);
break;
default:
break;
}
}
}
protected override Image AddWatermarkToOriginImage()
{
this.WatermarkedImage = this.OriginImage;
Graphics g = Graphics.FromImage(this.WatermarkedImage);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
SolidBrush semiTransBrushShadow = new SolidBrush(this.ShadowColor);
StringFormat format = this.StringFormat;
g.DrawString(this.WatermarkText, this.BestFont, semiTransBrushShadow, new PointF(this.X + this.ShadowOffsetX, this.Y + this.ShadowOffsetY), format);
SolidBrush semiTransBrush = new SolidBrush(this.ForeColor);
g.DrawString(this.WatermarkText, this.BestFont, semiTransBrush, new PointF(this.X, this.Y), format);
g.Dispose();
return this.WatermarkedImage;
}
private Font FindAvailableMaxSizedFont()
{
if (this.AutoSize)
{
this.BestFont = FindAvailableMaxSizedFont(false);
if (this.BestFont.Size >= 16)
{
return this.BestFont;
}
else
{
return FindAvailableMaxSizedFont(true);
}
}
else
{
return FindAvailableMaxSizedFont(true);
}
}
private Font FindAvailableMaxSizedFont(bool byAbsoluteSizes)
{
if (byAbsoluteSizes)
{
this.Fonts.Sort(delegate(Font font1, Font font2) { return font2.Size.CompareTo(font1.Size); });
SizeF size = new SizeF();
Bitmap image = new Bitmap(1, 1);
Graphics g = Graphics.FromImage(image);
for (int i = 0; i < this.Fonts.Count; i++)
{
//size = MeasureSize(this.WatermarkText, this.Fonts[i]);
size = g.MeasureString(this.WatermarkText, this.Fonts[i]);
if ((ushort)(size.Width + this.HorizontalMarginPixel * 2) < (ushort)this.OriginImage.Width && (ushort)(size.Height + this.VerticalMarginPixel * 2) < (ushort)this.OriginImage.Height)
{
g.Dispose();
image.Dispose();
this.WatermarkSize = size;
this.BestFont = this.fonts[i];
return this.Fonts[i];
}
}
g.Dispose();
image.Dispose();
this.WatermarkSize = new SizeF(0, 0);
return null;
}
else
{
int fontSize = (int)(this.OriginImage.Height * this.FontSizePercent);
fontSize = fontSize >= 1 ? fontSize : 1;
this.BestFont = new Font(this.BestFont.FontFamily, fontSize, this.BestFont.Style, this.BestFont.Unit);
this.WatermarkSize = MeasureSize(this.WatermarkText, this.BestFont);
if ((ushort)(this.WatermarkSize.Width + this.HorizontalMarginPixel * 2) < (ushort)this.OriginImage.Width && (ushort)(this.WatermarkSize.Height + this.VerticalMarginPixel * 2) < (ushort)this.OriginImage.Height)
{
return this.BestFont;
}
else
{
this.WatermarkSize = new SizeF(0, 0);
return null;
}
}
}
private SizeF MeasureSize(string text, Font font)
{
// Use a test image to measure the text.
Bitmap image = new Bitmap(1, 1);
Graphics g = Graphics.FromImage(image);
SizeF size = g.MeasureString(text, font);
g.Dispose();
image.Dispose();
return size;
}
#endregion
}
}
四、总结:
这里采用模板设计模式,可复用性高,能被引用在多种工程之中;可扩展性强,比如当有需要添加HTML水印时,只需要新建一个HtmlWatermarker类,并实现模板类Watermarker中的相关方法即可,不需要更改任何现有代码。
注意,模板设计模式很好地遵循了面向对象设计中的一个重要原则:对修改关闭,对扩展开放。
五、相关文件下载:
DLL 文件(若仅需使用):ImageHandler.dll (18.00 kb)
整个项目文件(若还需开发):ImageHandler.rar (45.03 kb)
[donate: www.zizhujy.com]