轉(zhuǎn)帖|其它|編輯:郝浩|2010-12-21 17:12:14.000|閱讀 843 次
概述:本文主要介紹.Net繪圖如何給圖片增加透明度,希望對(duì)大家有幫助。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
首先我們強(qiáng)調(diào)一下opacity的概念,是“不透明度”,它表示的是兩個(gè)圖層之間的關(guān)系,即該屬性隸屬于本圖層,它表示與本圖層下面圖層之間的像素合成關(guān)系,當(dāng)opacity=100%時(shí),表示本圖層完全不透明,因此下面的像素完全被遮擋。當(dāng)opacity=0時(shí),表示本圖層完全透明,即能看到下面的圖層。這是photoshop中最基本的一個(gè)算法,表達(dá)如下:
像素結(jié)果=底部圖層*(1-opacity)+本圖層*opacity;
當(dāng)有多個(gè)圖層x0,x1,x2混合時(shí),表達(dá)如下:(最底層的不透明度為1)
x=((1-k1)x0+k1*x1)(1-k2)+k2*x2= (1-k1)(1-k2)x0 + k1(1-k2)x1 + k2*x2;
那么繪制透明度水印的方法也就非常直觀了,因?yàn)轭悗?kù)中的ImageAttributes屬性里面并沒(méi)有提供像素合成的繪制選項(xiàng),因此我們自己實(shí)現(xiàn)上面的算法。方法是:首先準(zhǔn)備一個(gè)小的水印圖片,我們先把原圖在水印下面的部分繪制上去,然后在吧水印的文本或圖片繪制上去,然后把原圖和水印圖片的內(nèi)存數(shù)據(jù)鎖定(防止操作系統(tǒng)移動(dòng)內(nèi)存),然后直接用上面的算法改寫(xiě)原圖的位圖數(shù)據(jù),解鎖內(nèi)存即得到最終加了水印的圖片。
代碼如下:下面是繪制文本類型的水印,只需提供水印文本內(nèi)容,繪制起始坐標(biāo)即可。注意,為了簡(jiǎn)單直觀起見(jiàn),代碼中都沒(méi)有做參數(shù)驗(yàn)證,例如水印是否超出原圖范圍,如果超出范圍將引發(fā)對(duì)超過(guò)內(nèi)存邊界的訪問(wèn)限制(引發(fā)異常)。下面使用了unsafe代碼,因此項(xiàng)目屬性->Build中,應(yīng)勾選允許不安全代碼,否則無(wú)法編譯。 在下面代碼中的定位方式是非常熟悉的。再次強(qiáng)調(diào)的是以下的概念:
scan0:指針,內(nèi)存數(shù)據(jù)的起始地址。(換句話說(shuō),就是指向第一個(gè)掃描行第一個(gè)像素的Blue)。
bpp:bit per pixel。
stride:掃描行寬度,=width*bpp/8 并在結(jié)尾補(bǔ)0~3個(gè)字節(jié)的0,以湊齊到4字節(jié)整數(shù)倍。
之所以橫坐標(biāo)乘以3是因?yàn)槲覀冩i定的方式是24bppRgb(最后一個(gè)參數(shù)指定了數(shù)據(jù)的bpp),這意味這每個(gè)像素占據(jù)了3個(gè)字節(jié),因此i要乘以3來(lái)跳躍到下一個(gè)像素。如果用32bppRGB鎖定,則每個(gè)像素在內(nèi)存占據(jù)4字節(jié),相應(yīng)的i應(yīng)該乘以4。
Code-文本水印
/// <summary>
/// 給一個(gè)位圖繪制水印文字(沒(méi)有驗(yàn)證水印是否超出圖片邊界!)
/// </summary>
/// <param name="text">水印文本</param>
/// <param name="x">起始點(diǎn)</param>
/// <param name="y">起始點(diǎn)</param>
/// <param name="opacity">不透明度,0~1</param>
private Bitmap DrawWatermark(Image image,string text, Font font,Brush brush,int x,int y,double opacity)
{
Bitmap bm1 = new Bitmap(image);
Graphics g1=Graphics.FromImage(bm1);
//測(cè)量水印文字的大小,然后申請(qǐng)一個(gè)新的位圖
SizeF sizef=g1.MeasureString(text,font);
Bitmap bm2=new Bitmap((int)sizef.Width,(int)sizef.Height);
Graphics g2=Graphics.FromImage(bm2);
g2.DrawImage(bm1, 0,0,new Rectangle
(x, y, bm2.Width, bm2.Height),GraphicsUnit.Pixel);
g2.DrawString(text,font,brush,0,0);
BitmapData data1=bm1.LockBits(new Rectangle(0,0,bm1.Width,bm1.Height),
ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb);
BitmapData data2=bm2.LockBits(new Rectangle(0,0,bm2.Width,bm2.Height),ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
unsafe
{
byte* p1=(byte*)(void*)data1.Scan0;
byte* p2=(byte*)(void*)data2.Scan0;
for(int j=0;j<bm2.Height;j++)
{
for(int i=0;i<bm2.Width*3;i++)
{
p1[(y+j)*data1.Stride+i]=(byte)(p1[(y+j)*data1.Stride+i]*
(1-opacity)+opacity*p2[j*data2.Stride+i]);
}
}
bm1.UnlockBits(data1);
bm2.UnlockBits(data2);
}
return bm1;
}
還有一種情況是,我們事先做作好水印,它是一個(gè)圖片,更多的人在photoshop中使用一個(gè)自己設(shè)計(jì)好的logo,保存為一個(gè)“畫(huà)筆形狀”,制作時(shí)只要選中此畫(huà)筆一蓋就好了。實(shí)際上這種類型的水印是一個(gè)圖片,為了加這種類型的水印,引入下面的overload方法:指定水印圖片和透明色。
Code-圖片水印
/// <param name="image">原圖</param>
/// <param name="wmImg">水印圖片</param>
/// <param name="key">透明色</param>
/// <param name="x">起始點(diǎn)</param>
/// <param name="y"></param>
/// <param name="opacity">不透明度</param>
/// <returns></returns>
private Bitmap DrawWatermark(Image image,
Bitmap wmImg, Color key,int x, int y, double opacity)
{
Bitmap bm1 = new Bitmap(image); //克隆原圖,它也是我們的返回值
Bitmap bm2 = new Bitmap(wmImg.Width, wmImg.Height); //準(zhǔn)備的水印圖片
Graphics g2 = Graphics.FromImage(bm2);
ImageAttributes att = new ImageAttributes();
att.SetColorKey(key, key, ColorAdjustType.Bitmap); //設(shè)定透明色
g2.DrawImage(bm1, 0, 0, new Rectangle(x, y, bm2.Width, bm2.Height),
GraphicsUnit.Pixel);
g2.DrawImage(wmImg, new Rectangle(0,0,bm2.Width,bm2.Height),0, 0,bm2.Width,bm2.Height,GraphicsUnit.Pixel,att);
g2.Dispose();
。。。。這里的代碼和上面的方法代碼相同,因此省略
return bm1;
}
以上兩種效果的截圖:
ASP.NET中如何使用unsafe選項(xiàng)
實(shí)際需要在ASP.NET中使用unsafe選項(xiàng)
集體的方法是:找到工程的web.config文件,在configuration節(jié)中加入:
<system.codedom>
<compilers>
<compiler
language="c#;cs;csharp" extension=".cs"
compilerOptions="/unsafe"
type="Microsoft.CSharp.CSharpCodeProvider, System, Version=
2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</compilers>
</system.codedom>
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:網(wǎng)絡(luò)轉(zhuǎn)載