轉帖|其它|編輯:郝浩|2010-12-21 17:12:14.000|閱讀 843 次
概述:本文主要介紹.Net繪圖如何給圖片增加透明度,希望對大家有幫助。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
首先我們強調一下opacity的概念,是“不透明度”,它表示的是兩個圖層之間的關系,即該屬性隸屬于本圖層,它表示與本圖層下面圖層之間的像素合成關系,當opacity=100%時,表示本圖層完全不透明,因此下面的像素完全被遮擋。當opacity=0時,表示本圖層完全透明,即能看到下面的圖層。這是photoshop中最基本的一個算法,表達如下:
像素結果=底部圖層*(1-opacity)+本圖層*opacity;
當有多個圖層x0,x1,x2混合時,表達如下:(最底層的不透明度為1)
x=((1-k1)x0+k1*x1)(1-k2)+k2*x2= (1-k1)(1-k2)x0 + k1(1-k2)x1 + k2*x2;
那么繪制透明度水印的方法也就非常直觀了,因為類庫中的ImageAttributes屬性里面并沒有提供像素合成的繪制選項,因此我們自己實現上面的算法。方法是:首先準備一個小的水印圖片,我們先把原圖在水印下面的部分繪制上去,然后在吧水印的文本或圖片繪制上去,然后把原圖和水印圖片的內存數據鎖定(防止操作系統移動內存),然后直接用上面的算法改寫原圖的位圖數據,解鎖內存即得到最終加了水印的圖片。
代碼如下:下面是繪制文本類型的水印,只需提供水印文本內容,繪制起始坐標即可。注意,為了簡單直觀起見,代碼中都沒有做參數驗證,例如水印是否超出原圖范圍,如果超出范圍將引發對超過內存邊界的訪問限制(引發異常)。下面使用了unsafe代碼,因此項目屬性->Build中,應勾選允許不安全代碼,否則無法編譯。 在下面代碼中的定位方式是非常熟悉的。再次強調的是以下的概念:
scan0:指針,內存數據的起始地址。(換句話說,就是指向第一個掃描行第一個像素的Blue)。
bpp:bit per pixel。
stride:掃描行寬度,=width*bpp/8 并在結尾補0~3個字節的0,以湊齊到4字節整數倍。
之所以橫坐標乘以3是因為我們鎖定的方式是24bppRgb(最后一個參數指定了數據的bpp),這意味這每個像素占據了3個字節,因此i要乘以3來跳躍到下一個像素。如果用32bppRGB鎖定,則每個像素在內存占據4字節,相應的i應該乘以4。
Code-文本水印
/// <summary>
/// 給一個位圖繪制水印文字(沒有驗證水印是否超出圖片邊界!)
/// </summary>
/// <param name="text">水印文本</param>
/// <param name="x">起始點</param>
/// <param name="y">起始點</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);
//測量水印文字的大小,然后申請一個新的位圖
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;
}
還有一種情況是,我們事先做作好水印,它是一個圖片,更多的人在photoshop中使用一個自己設計好的logo,保存為一個“畫筆形狀”,制作時只要選中此畫筆一蓋就好了。實際上這種類型的水印是一個圖片,為了加這種類型的水印,引入下面的overload方法:指定水印圖片和透明色。
Code-圖片水印
/// <param name="image">原圖</param>
/// <param name="wmImg">水印圖片</param>
/// <param name="key">透明色</param>
/// <param name="x">起始點</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); //準備的水印圖片
Graphics g2 = Graphics.FromImage(bm2);
ImageAttributes att = new ImageAttributes();
att.SetColorKey(key, key, ColorAdjustType.Bitmap); //設定透明色
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選項
實際需要在ASP.NET中使用unsafe選項
集體的方法是:找到工程的web.config文件,在configuration節中加入:
<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>
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:網絡轉載