2023年3月

以前使用DataMapper-1.6.1,现在改用DataMapper-1.5.1,结果lazyload无效了。
以下引用《Data Mapper Guide-1.6.1.chm》中的内容:

3.5.4.9. lazyLoad

Use the lazyLoad attribute with the select attribute to indicate whether or
not the select statement's results should be lazy loaded. This can provide a
performance boost by delaying the loading of the select statement's results
until they are needed/accessed.

Lazy loading is supported transparently for IList and IList<T>
implementation.

Lazy loading is supported on strongly typed collection via
Castle.DynamicProxy component. In this case you must set the listClass attribute
and declare all methods/properties of the typed collection that you want to
proxy as virtual.

Lazy loading is supported on concrete class via Castle.DynamicProxy
component. In this case, you must declare all methods/properties of the class
that you want to proxy as virtual.


在1.5.1版本中,我没有把lazyload属性定义为virtual都可以使用lazyload功能,现在即使声明为virtual也没有效果。调试的过程中发现,属性的第一次读取是肯定为空的,而之后lazyload属性的值却有可能获取。深入分析代码并把1.6.1和1.5.1做比较,无奈水平有限,发现直接相关的代码似乎没有改动,没看出端倪。

在Ibatis.Net的Issue Tracker上看到了此bug的报告,但是没有评论和解决方案。不知道cnblogs上研究Ibatis.Net的牛人能不能提供帮助?实在不行,只有使用1.5.1了。

附代码:

IRegDao dao
=

new
RegDao();
Reg reg

=
dao.Find(
1
);
Console.WriteLine(

"
Reg:
"
);
Console.WriteLine(

"
SeqId:{0}
"
, reg.SeqId);
Console.WriteLine(

"
SubjID:{0}\tName:{1}
"
, reg.SubjID, reg.Subj.Name);


///
class Reg


public
partial
class
Reg
{

#region
Private Member


private

int
?
_SubjID;

#endregion



#region
Private Extend Member


private
Subj _Subj;

#endregion



#region
Constructor


public
Reg()
{
}

#endregion



#region
Public Properties


public

int
?
SubjID
{

get
{
return
_SubjID;}

set
{_SubjID
=
value;}
}

#endregion



#region
Public Extend Properties


public

virtual
Subj Subj
{

get
{
return
_Subj; }

set
{ _Subj
=
value; }
}

#endregion

}


为了应付越来越多的自动发帖机、恶意攻击等情形,验证码技术在大量的网站上得到使用。我在近期开发一个注册网站的时候,也使用了这一技术。当然,我并不想完完全全自己重新实现,而是参考了网上能够找到的实现,做了若干改进而已。下面谈谈我的实现。
补两张图片:


首先看验证码图片输出页的代码:

<%
@ Page Language
=
"
C#
"

%>



<!
DOCTYPE html PUBLIC
"
-//W3C//DTD XHTML 1.0 Transitional//EN
"

"
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
"
>



<
script runat
=
"
server
"
>


protected

void
Page_Load(
object
sender, EventArgs e)
{
VryImgGen gen

=

new
VryImgGen();

string
verifyCode
=
gen.CreateVerifyCode(
5
,
1
);
Session[

"
VerifyCode
"
]
=
verifyCode.ToUpper();
System.Drawing.Bitmap bitmap

=
gen.CreateImage(verifyCode);
System.IO.MemoryStream ms

=

new
System.IO.MemoryStream();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
Response.Clear();
Response.ContentType

=

"
image/Png
"
;
Response.BinaryWrite(ms.GetBuffer());
bitmap.Dispose();
ms.Dispose();
ms.Close();
Response.End();
}

</
script
>

功能很简单,初始化一个验证码生成对象,生成图片。然后保存到一个MemoryStream里。得到字节流,输出字节流。验证码的数据是保存在Session中的,这是最简单的方法。或者可以加密储存在cookie里,也是可以的。

再来看看验证码生成对象:

using
System;

using
System.Data;

using
System.Configuration;

using
System.Web;

using
System.Web.Security;

using
System.Web.UI;

using
System.Web.UI.WebControls;

using
System.Web.UI.WebControls.WebParts;

using
System.Web.UI.HtmlControls;

using
System.Drawing;

using
System.Text;


///

<summary>


///
Summary description for VryImgGen

///

</summary>


public
partial
class
VryImgGen
{


///

<summary>


///
供验证码生成汉字时选取的汉字集,若为空则按照《GB2312简体中文编码表》编码规则构造汉字

///

</summary>



public

static

string
ChineseChars
=
String.Empty;


///

<summary>


///
英文与数字串

///

</summary>



protected

static

readonly

string
EnglishOrNumChars
=

"
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
"
;


public
VryImgGen()
{
rnd

=

new
Random(
unchecked
((
int
)DateTime.Now.Ticks));
}


///

<summary>


///
全局随机数生成器

///

</summary>



private
Random rnd;


int
length
=

5
;

///

<summary>


///
验证码长度(默认6个验证码的长度)

///

</summary>



public

int
Length
{

get
{
return
length; }

set
{ length
=
value; }
}


int
fontSize
=

18
;

///

<summary>


///
验证码字体大小(为了显示扭曲效果,默认30像素,可以自行修改)

///

</summary>



public

int
FontSize
{

get
{
return
fontSize; }

set
{ fontSize
=
value; }
}


int
padding
=

4
;

///

<summary>


///
边框补(默认4像素)

///

</summary>



public

int
Padding
{

get
{
return
padding; }

set
{ padding
=
value; }
}


bool
chaos
=

true
;

///

<summary>


///
是否输出燥点(默认输出)

///

</summary>



public

bool
Chaos
{

get
{
return
chaos; }

set
{ chaos
=
value; }
}

Color chaosColor

=
Color.LightGray;

///

<summary>


///
输出燥点的颜色(默认灰色)

///

</summary>



public
Color ChaosColor
{

get
{
return
chaosColor; }

set
{ chaosColor
=
value; }
}

Color backgroundColor

=
Color.White;

///

<summary>


///
自定义背景色(默认白色)

///

</summary>



public
Color BackgroundColor
{

get
{
return
backgroundColor; }

set
{ backgroundColor
=
value; }
}

Color[] colors

=
{ Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };

///

<summary>


///
自定义随机颜色数组

///

</summary>



public
Color[] Colors
{

get
{
return
colors; }

set
{ colors
=
value; }
}


string
[] fonts
=
{
"
Arial
"
,
"
Georgia
"
};

///

<summary>


///
自定义字体数组

///

</summary>



public

string
[] Fonts
{

get
{
return
fonts; }

set
{ fonts
=
value; }
}


#region
产生波形滤镜效果



private

const

double
PI
=

3.1415926535897932384626433832795
;

private

const

double
PI2
=

6.283185307179586476925286766559
;


///

<summary>


///
正弦曲线Wave扭曲图片(Edit By 51aspx.com)

///

</summary>


///

<param name="srcBmp">
图片路径
</param>


///

<param name="bXDir">
如果扭曲则选择为True
</param>


///

<param name="nMultValue">
波形的幅度倍数,越大扭曲的程度越高,一般为3
</param>


///

<param name="dPhase">
波形的起始相位,取值区间[0-2*PI)
</param>


///

<returns></returns>



public
System.Drawing.Bitmap TwistImage(Bitmap srcBmp,
bool
bXDir,
double
dMultValue,
double
dPhase)
{
System.Drawing.Bitmap destBmp

=

new
Bitmap(srcBmp.Width, srcBmp.Height);


//
将位图背景填充为白色


System.Drawing.Graphics graph
=
System.Drawing.Graphics.FromImage(destBmp);
graph.FillRectangle(

new
SolidBrush(System.Drawing.Color.White),
0
,
0
, destBmp.Width, destBmp.Height);
graph.Dispose();


double
dBaseAxisLen
=
bXDir
?
(
double
)destBmp.Height : (
double
)destBmp.Width;


for
(
int
i
=

0
; i
<
destBmp.Width; i
++
)
{

for
(
int
j
=

0
; j
<
destBmp.Height; j
++
)
{

double
dx
=

0
;
dx

=
bXDir
?
(PI2
*
(
double
)j)
/
dBaseAxisLen : (PI2
*
(
double
)i)
/
dBaseAxisLen;
dx

+=
dPhase;

double
dy
=
Math.Sin(dx);


//
取得当前点的颜色



int
nOldX
=

0
, nOldY
=

0
;
nOldX

=
bXDir
?
i
+
(
int
)(dy
*
dMultValue) : i;
nOldY

=
bXDir
?
j : j
+
(
int
)(dy
*
dMultValue);

System.Drawing.Color color

=
srcBmp.GetPixel(i, j);

if
(nOldX
>=

0

&&
nOldX
<
destBmp.Width

&&
nOldY
>=

0

&&
nOldY
<
destBmp.Height)
{
destBmp.SetPixel(nOldX, nOldY, color);
}
}
}


return
destBmp;
}




#endregion



///

<summary>


///
生成校验码图片

///

</summary>


///

<param name="code">
验证码
</param>


///

<returns></returns>



public
Bitmap CreateImage(
string
code)
{

int
fSize
=
FontSize;

int
fWidth
=
fSize
+
Padding;


int
imageWidth
=
(
int
)(code.Length
*
fWidth)
+

4

+
Padding
*

2
;

int
imageHeight
=
fSize
*

2

+
Padding
*

2
;

System.Drawing.Bitmap image

=

new
System.Drawing.Bitmap(imageWidth, imageHeight);

Graphics g

=
Graphics.FromImage(image);

g.Clear(BackgroundColor);


//
给背景添加随机生成的燥点



if
(
this
.Chaos)
{

Pen pen

=

new
Pen(ChaosColor,
0
);

int
c
=
Length
*

10
;


for
(
int
i
=

0
; i
<
c; i
++
)
{

int
x
=
rnd.Next(image.Width);

int
y
=
rnd.Next(image.Height);

g.DrawRectangle(pen, x, y,

1
,
1
);
}
}


int
left
=

0
, top
=

0
, top1
=

1
, top2
=

1
;


int
n1
=
(imageHeight
-
FontSize
-
Padding
*

2
);

int
n2
=
n1
/

4
;
top1

=
n2;
top2

=
n2
*

2
;

Font f;
Brush b;


int
cindex, findex;


//
随机字体和颜色的验证码字符



for
(
int
i
=

0
; i
<
code.Length; i
++
)
{
cindex

=
rnd.Next(Colors.Length
-

1
);
findex

=
rnd.Next(Fonts.Length
-

1
);

f

=

new
System.Drawing.Font(Fonts[findex], fSize, System.Drawing.FontStyle.Bold);
b

=

new
System.Drawing.SolidBrush(Colors[cindex]);


if
(i
%

2

==

1
)
{
top

=
top2;
}

else

{
top

=
top1;
}

left

=
i
*
fWidth;

g.DrawString(code.Substring(i,

1
), f, b, left, top);
}


//
画一个边框 边框颜色为Color.Gainsboro


g.DrawRectangle(
new
Pen(Color.Gainsboro,
0
),
0
,
0
, image.Width
-

1
, image.Height
-

1
);
g.Dispose();


//
产生波形(Add By 51aspx.com)


image
=
TwistImage(image,
true
,
8
,
4
);


return
image;
}


///

<summary>


///
生成随机字符码

///

</summary>


///

<param name="codeLen">
字符串长度
</param>


///

<param name="zhCharsCount">
中文字符数
</param>


///

<returns></returns>



public

string
CreateVerifyCode(
int
codeLen,
int
zhCharsCount)
{

char
[] chs
=

new

char
[codeLen];


int
index;

for
(
int
i
=

0
; i
<
zhCharsCount; i
++
)
{
index

=
rnd.Next(
0
, codeLen);

if
(chs[index]
==

'
\0
'
)
chs[index]

=
CreateZhChar();

else


--
i;
}

for
(
int
i
=

0
; i
<
codeLen; i
++
)
{

if
(chs[i]
==

'
\0
'
)
chs[i]

=
CreateEnOrNumChar();
}


return

new

string
(chs,
0
, chs.Length);
}


///

<summary>


///
生成默认长度5的随机字符码

///

</summary>


///

<returns></returns>



public

string
CreateVerifyCode()
{

return
CreateVerifyCode(Length,
0
);
}


///

<summary>


///
生成英文或数字字符

///

</summary>


///

<returns></returns>



protected

char
CreateEnOrNumChar()
{

return
EnglishOrNumChars[rnd.Next(
0
, EnglishOrNumChars.Length)];
}


///

<summary>


///
生成汉字字符

///

</summary>


///

<returns></returns>



protected

char
CreateZhChar()
{

//
若提供了汉字集,查询汉字集选取汉字



if
(ChineseChars.Length
>

0
)
{

return
ChineseChars[rnd.Next(
0
, ChineseChars.Length)];
}

//
若没有提供汉字集,则根据《GB2312简体中文编码表》编码规则构造汉字



else

{

byte
[] bytes
=

new

byte
[
2
];


//
第一个字节值在0xb0, 0xf7之间


bytes[
0
]
=
(
byte
)rnd.Next(
0xb0
,
0xf8
);

//
第二个字节值在0xa1, 0xfe之间


bytes[
1
]
=
(
byte
)rnd.Next(
0xa1
,
0xff
);


//
根据汉字编码的字节数组解码出中文汉字



string
str1
=
Encoding.GetEncoding(
"
gb2312
"
).GetString(bytes);


return
str1[
0
];
}
}
}

这里面大量使用了
51aspx.com
的代码,在此表示感谢。这里的主要改进在于支持生成中英文混合的验证码。中文的生成有两种方式,一是根据
《GB2312简体中文编码表》
编码规则构造汉字,二是从一个选定的中文字符集合中随即选取汉字。实现很简单,参考函数
protected

char
CreateZhChar(),在此不赘述。

最后说一下验证码的使用,下面是一个例子:

<
img
src
="VerifyCode.aspx"
id
="valiCode"
alt
="验证码"

/>


<
a
title
="刷新验证码"
href
="#"
onclick
="javascript:document.getElementById('valiCode').src='VerifyCode.aspx?id='+Math.random();return false;"
>
看不清,换张图片?
</
a
>

这里有个小技巧,就是在刷新验证码的使用,验证码的URL后面用了随机参数以欺骗浏览器重新请求。

源代码
2500常用汉字
498常用汉字

老早以前写的,害怕以后忘了或找不到了,发到这里以备忘。

using
System;

using
System.IO;

using
System.Drawing;

using
System.Drawing.Imaging;


///

<summary>


///
PictureMarker 的摘要说明。

///

</summary>


public

class
PictureMarker
{

///

<summary>


///
PictureMarker的构造函数

///

</summary>



public
PictureMarker()
{
}


///

<summary>


///
PictureMarker的构造函数

///

</summary>


///

<param name="width">
缩略图的宽度
</param>


///

<param name="height">
缩略图的高度
</param>


///

<param name="ismust">
是否一定要生成缩略图,推荐为false
</param>



public
PictureMarker(
int
width,
int
height,
bool
ismust)
{

this
.width
=
width;

this
.height
=
height;

this
.ismust
=
ismust;
}


///

<summary>


///
PictureMarker的构造函数

///

</summary>


///

<param name="width">
缩略图的宽度
</param>


///

<param name="height">
缩略图的高度
</param>


///

<param name="ismust">
是否一定要生成缩略图,推荐为false
</param>


///

<param name="isSavePrimaryPic">
是否要保存源图片
</param>


///

<param name="primaryPicPath">
源图片的保存目录
</param>



public
PictureMarker(
int
width,
int
height,
bool
ismust,
bool
isSavePrimaryPic,
string
primaryPicPath)
:

this
(width, height, ismust)
{

this
.isSavePrimaryPic
=
isSavePrimaryPic;

this
.primaryPicPath
=
primaryPicPath;
}


private

int
width;

private

int
height;

private

bool
ismust
=

false
;

private

bool
isSavePrimaryPic
=

false
;

private

string
primaryPicPath;


///

<summary>


///
缩略图的宽度

///

</summary>



public

int
Width
{

get
{
return
width; }

set
{ width
=
value; }
}


///

<summary>


///
缩略图的高度

///

</summary>



public

int
Height
{

get
{
return
height; }

set
{ height
=
value; }
}


///

<summary>


///
是否一定要生成缩略图,推荐为false

///

</summary>



public

bool
IsMust
{

get
{
return
ismust; }

set
{ ismust
=
value; }
}


///

<summary>


///
是否要保存源图片

///

</summary>



public

bool
IsSavePrimaryPic
{

get
{
return
isSavePrimaryPic; }

set
{ isSavePrimaryPic
=
value; }
}


///

<summary>


///
源图片的保存目录

///

</summary>



public

string
PrimaryPicPath
{

get
{
return
primaryPicPath; }

set
{ primaryPicPath
=
value; }
}


///

<summary>


///
在图片上添加版权信息水印

///

</summary>


///

<param name="input">
目标图片
</param>


///

<param name="copyright">
文字版权信息
</param>


///

<param name="savepath">
保存路径
</param>


///

<param name="position">
水印显示位置
</param>



public

void
CreateMark(Stream input,
string
copyright,
string
savepath, WaterPosition position)
{

int
xpoint, ypoint;
System.Drawing.Image photo

=
System.Drawing.Image.FromStream(input);

int
pwidth
=
photo.Width;

int
pheight
=
photo.Height;
Bitmap markpic

=

new
Bitmap(photo);
markpic.SetResolution(photo.HorizontalResolution, photo.VerticalResolution);

Graphics graphics

=
Graphics.FromImage(markpic);

xpoint

=
(pwidth
-

100
)
/

2
;
ypoint

=
pheight
-

40
;
graphics.DrawString(copyright,

new
Font(
"
楷体
"
,
15
),
new
System.Drawing.SolidBrush(Color.FromArgb(
255
,
0
,
255
,
255
)),

new
RectangleF(xpoint, ypoint,
400
,
30
));



try

{
markpic.Save(savepath);
}

finally

{
input.Close();
photo.Dispose();
markpic.Dispose();
graphics.Dispose();
}
}


///

<summary>


///
在图片上添加版权信息水印

///

</summary>


///

<param name="input">
目标图片
</param>


///

<param name="copyright">
图片版权信息
</param>


///

<param name="savepath">
保存路径
</param>


///

<param name="position">
水印显示位置
</param>



public

void
CreateMark(Stream input, Stream copyright,
string
savepath, WaterPosition position)
{

int
xpoint, ypoint;
System.Drawing.Image photo

=
System.Drawing.Image.FromStream(input);
System.Drawing.Image copy

=
System.Drawing.Image.FromStream(copyright);

int
pwidth
=
photo.Width;

int
pheight
=
photo.Height;

int
cwidth
=
copy.Width;

int
cheight
=
copy.Height;

if
(pwidth
-
cwidth
<

20

||
pheight
-
cheight
<

20
)
{
input.Close();
copyright.Close();
photo.Dispose();
copy.Dispose();

throw

new
ArgumentException(
"
不合适的图片尺寸.目标图片比版权图片至少宽20像素,高20像素.
"
);
}


if
(isSavePrimaryPic)
{

if
(primaryPicPath
==

null

||
primaryPicPath
==

""
)
{
input.Close();
copyright.Close();
photo.Dispose();
copy.Dispose();

throw

new
ArgumentException(
"
当要求保存源图片时,源图片的保存路径不能为空
"
);
}


try

{
photo.Save(primaryPicPath

+

"
\\
"

+
Path.GetFileName(savepath)
+

"
.jpg
"
, ImageFormat.Jpeg);
}

catch
(Exception ex)
{
input.Close();
copyright.Close();
photo.Dispose();
copy.Dispose();


throw
ex;
}
}

Bitmap markpic

=

new
Bitmap(photo);
markpic.SetResolution(photo.HorizontalResolution, photo.VerticalResolution);

Graphics graphics

=
Graphics.FromImage(markpic);
System.Drawing.Imaging.ImageAttributes att

=

new
System.Drawing.Imaging.ImageAttributes();


float
[][] matrixelements
=
{


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.5f
,
0.0f
},


new

float
[] {
0.0f
,
0.0f
,
0.0f
,
0.0f
,
1.0f
}};

System.Drawing.Imaging.ColorMatrix matrix

=

new
System.Drawing.Imaging.ColorMatrix(matrixelements);

att.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);


switch
(position)
{

case
WaterPosition.Left:
xpoint

=

10
;
ypoint

=
(pheight
-
cheight)
/

2
;

break
;

case
WaterPosition.LeftUp:
xpoint

=

10
;
ypoint

=

10
;

break
;

case
WaterPosition.MiddleUp:
xpoint

=
(pwidth
-
cwidth)
/

2
;
ypoint

=

10
;

break
;

case
WaterPosition.RightUp:
xpoint

=
pwidth
-
cwidth
-

10
;
ypoint

=

10
;

break
;

case
WaterPosition.Right:
xpoint

=
pwidth
-
cwidth
-

10
;
ypoint

=
(pheight
-
cheight)
/

2
;

break
;

case
WaterPosition.RightDown:
xpoint

=
pwidth
-
cwidth
-

10
;
ypoint

=
pheight
-
cheight
-

10
;

break
;

case
WaterPosition.MiddleDown:
xpoint

=
(pwidth
-
cwidth)
/

2
;
ypoint

=
pheight
-
cheight
-

10
;

break
;

case
WaterPosition.LeftDown:
xpoint

=

10
;
ypoint

=
pheight
-
cheight
-

10
;

break
;

default
:
xpoint

=
(pwidth
-
cwidth)
/

2
;
ypoint

=
(pheight
-
cheight)
/

2
;

break
;
};

graphics.DrawImage(copy,

new
Rectangle(xpoint, ypoint, cwidth, cheight),
0
,
0
, cwidth, cheight, GraphicsUnit.Pixel, att);


if
(width
!=

0

&&
height
!=

0
)
{

if
(ismust)
{

int
twidth, theight;

if
(markpic.Width
*
height
>
markpic.Height
*
width)
{
twidth

=
width;
theight

=
markpic.Height
*
width
/
markpic.Width;
}

else

{
theight

=
height;
twidth

=
markpic.Width
*
height
/
markpic.Height;
}

markpic.SetResolution(twidth, theight);
markpic

=
(Bitmap)markpic.GetThumbnailImage(twidth, theight,
null
,
new
IntPtr());
}

else

{

if
(width
<
markpic.Width
||
height
<
markpic.Height)
{

if
(width
<
markpic.Width
||
height
<
markpic.Height)
{

int
twidth, theight;

if
(markpic.Width
*
height
>
markpic.Height
*
width)
{
twidth

=
width;
theight

=
markpic.Height
*
width
/
markpic.Width;
}

else

{
theight

=
height;
twidth

=
markpic.Width
*
height
/
markpic.Height;
}

markpic.SetResolution(twidth, theight);
markpic

=
(Bitmap)markpic.GetThumbnailImage(twidth, theight,
null
,
new
IntPtr());
}
}
}
}


try

{
markpic.Save(savepath, ImageFormat.Jpeg);
}

finally

{
graphics.Dispose();
input.Close();
copyright.Close();
photo.Dispose();
copy.Dispose();
markpic.Dispose();
}
}



///

<summary>


///
在图片上添加版权信息水印

///

</summary>


///

<param name="input">
目标图片
</param>


///

<param name="copyright">
版权信息,可以为图片路径或文字版权信息
</param>


///

<param name="directory">
保存目录
</param>


///

<param name="filename">
保存文件名
</param>


///

<param name="isDrectory">
copyright是否为文件路径
</param>


///

<param name="position">
水印显示位置
</param>



public

void
CreateMark(Stream input,
string
copyright,
string
directory,
string
filename,
bool
isDrectory, WaterPosition position)
{

if
(isDrectory)
{
FileStream _copyright

=

new
FileStream(copyright, FileMode.Open, FileAccess.Read, FileShare.Read);
CreateMark(input, _copyright, directory, filename, position);
}

else

{
CreateMark(input, copyright, directory

+

"
\\
"

+
filename, position);
}
}


///

<summary>


///
在图片上添加版权信息水印

///

</summary>


///

<param name="input">
目标图片
</param>


///

<param name="copyright">
图片版权信息
</param>


///

<param name="directory">
保存目录
</param>


///

<param name="filename">
保存文件名
</param>


///

<param name="position">
水印显示位置
</param>



public

void
CreateMark(Stream input, Stream copyright,
string
directory,
string
filename, WaterPosition position)
{
CreateMark(input, copyright, directory

+

"
\\
"

+
filename, position);
}


///

<summary>


///
在图片上添加版权信息水印

///

</summary>


///

<param name="filepath">
目标图片路径
</param>


///

<param name="copyright">
版权信息,可以为图片路径或文字版权信息
</param>


///

<param name="directory">
保存目录
</param>


///

<param name="filename">
保存文件名
</param>


///

<param name="isDrectory">
copyright是否为文件路径
</param>


///

<param name="position">
水印显示位置
</param>



public

void
CreateMark(
string
filepath,
string
copyright,
string
directory,
string
filename,
bool
isDrectory, WaterPosition position)
{
FileStream input

=

new
FileStream(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
CreateMark(input, copyright, directory, filename, isDrectory, position);
}


///

<summary>


///
在图片上添加版权信息水印

///

</summary>


///

<param name="filepath">
目标图片路径
</param>


///

<param name="copyright">
版权信息,可以为图片路径或文字版权信息
</param>


///

<param name="savepath">
保存路径
</param>


///

<param name="isDrectory">
copyright是否为文件路径
</param>


///

<param name="position">
水印显示位置
</param>



public

void
CreateMark(
string
filepath,
string
copyright,
string
savepath,
bool
isDrectory, WaterPosition position)
{

if
(isDrectory)
{
FileStream input

=

new
FileStream(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
FileStream _copyright

=

new
FileStream(copyright, FileMode.Open, FileAccess.Read, FileShare.Read);
CreateMark(input, _copyright, savepath, position);
}

else

{
FileStream input

=

new
FileStream(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
CreateMark(input, copyright, savepath, position);
}
}


public

void
CreateThumbnailImage(Stream input,
string
savepath)
{

if
(width
==

0

||
height
==

0
)
{
input.Close();

throw

new
ArgumentException(
"
缩略图的宽度和高度不能为0.
"
);
}
Image photo

=
Image.FromStream(input);


if
(isSavePrimaryPic)
{

if
(primaryPicPath
==

null

||
primaryPicPath
==

""
)
{
input.Close();
photo.Dispose();

throw

new
ArgumentException(
"
当要求保存源图片时,源图片的保存路径不能为空
"
);
}


try

{
photo.Save(Path.Combine(primaryPicPath, Path.GetFileNameWithoutExtension(savepath)

+

"
.jpg
"
), ImageFormat.Jpeg);
}

catch
(Exception ex)
{
input.Close();
photo.Dispose();


throw
ex;
}
}

Bitmap markpic

=

new
Bitmap(photo);


if
(ismust)
{

int
twidth, theight;

if
(markpic.Width
*
height
>
markpic.Height
*
width)
{
twidth

=
width;
theight

=
markpic.Height
*
width
/
markpic.Width;
}

else

{
theight

=
height;
twidth

=
markpic.Width
*
height
/
markpic.Height;
}

markpic.SetResolution(twidth, theight);
markpic

=
(Bitmap)markpic.GetThumbnailImage(twidth, theight,
null
,
new
IntPtr());
}

else

{

if
(width
<
markpic.Width
||
height
<
markpic.Height)
{

if
(width
<
markpic.Width
||
height
<
markpic.Height)
{

int
twidth, theight;

if
(markpic.Width
*
height
>
markpic.Height
*
width)
{
twidth

=
width;
theight

=
markpic.Height
*
width
/
markpic.Width;
}

else

{
theight

=
height;
twidth

=
markpic.Width
*
height
/
markpic.Height;
}

markpic.SetResolution(twidth, theight);
markpic

=
(Bitmap)markpic.GetThumbnailImage(twidth, theight,
null
,
new
IntPtr());
}
}
}


try

{
markpic.Save(savepath, ImageFormat.Jpeg);
}

finally

{
input.Close();
photo.Dispose();
markpic.Dispose();
}
}


public

void
CreateThumbnailImage(
string
source,
string
savepath)
{
FileStream input

=

new
FileStream(source, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
CreateThumbnailImage(input, savepath);
}


///

<summary>


///
水印显示的位置

///

</summary>



public

enum
WaterPosition
{

///

<summary>


///
左上

///

</summary>


LeftUp,

///

<summary>


///
中上

///

</summary>


MiddleUp,

///

<summary>


///
右上

///

</summary>


RightUp,

///

<summary>


///


///

</summary>


Right,

///

<summary>


///
右下

///

</summary>


RightDown,

///

<summary>


///
中下

///

</summary>


MiddleDown,

///

<summary>


///
左下

///

</summary>


LeftDown,

///

<summary>


///


///

</summary>


Left,

///

<summary>


///
正中间

///

</summary>


Middle
}
}


源代码

使用Asp.Net Ajax + Web Service实现的,发布在此以备忘。
截图:


调用:

javascript:window.open('MiniFeeManage.aspx', 'MiniMode', 'height
=
358
, width
=
610
, top
=
200
, left
=
300
, toolbar
=
no, titlebar
=
yes, menubar
=
no, scrollbars
=
no, resizable
=
yes, location
=
no, status
=
no');
return

false
;



源码