轉(zhuǎn)帖|其它|編輯:郝浩|2011-04-15 11:23:56.000|閱讀 2795 次
概述:最近項(xiàng)目有個需求,需要顯示出圖片Image的“SUNKEN”效果,就是可以將圖片變成各種凹凸的形狀,可能有些園友也做過類似的需求。在WPF 3.5(及之前)版本中,這個效果很簡單就可以實(shí)現(xiàn),直接應(yīng)用BevelBitmapEffect就可以實(shí)現(xiàn)這樣的效果。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
最近項(xiàng)目有個需求,需要顯示出圖片Image的“SUNKEN”效果,就是可以將圖片變成各種凹凸的形狀,可能有些園友也做過類似的需求。
在WPF 3.5(及之前)版本中,這個效果很簡單就可以實(shí)現(xiàn),直接應(yīng)用BevelBitmapEffect就可以實(shí)現(xiàn)這樣的效果。
1 <Image Name="bevelImage" Stretch="Uniform" Source="/WpfUnleashed;component/image/testBevelImage.jpg">
2 <Image.BitmapEffect>
3 <BevelBitmapEffect ></BevelBitmapEffect>
4 </Image.BitmapEffect>
5 </Image>
或者在Code中直接加上 bevelImage.BitmapEffect = new BevelBitmapEffect(); 就可以了,效果如下:
但是,從WPF 4.0開始,微軟已經(jīng)宣布這個API已經(jīng)過時了,也即意味著在WPF 4.0及之后已經(jīng)不支持這個效果了。
Code中的代碼也會受到警告:
而且,這種效果最終在界面上是不會起作用的,這就很讓人dan疼了。
微軟放棄使用這個API的原因,很大程度上是這種效果是由軟件渲染的,其代價就是如果在項(xiàng)目中有比較多這種效果,則會占用大量的性能。而微軟在WPF中主要是推薦由硬件去渲染這些特效的,所以保留了Effect,新加入了ShaderEffect,推薦使用著色器來提升效果,感興趣的園友可以去研究。
由于時間比較緊,對ShaderEffect也不是很熟悉,所以暫時使用了另外的途徑來替代實(shí)現(xiàn)這種效果。
原理是使用對Bitmap進(jìn)行重繪,然后將重繪后的byte數(shù)據(jù)再寫回去,替換原先PictureBox中的Image。
缺點(diǎn)顯而易見,性能不好。 但是由于趕時間,只好等日后去研究ShaderEffect再來優(yōu)化了。
下面放出代碼:
1 public byte[] ImageBytes;
2 public int RowSizeBytes;
3 private BitmapData m_BitmapData;
4
5 private void pictureBox1_Click(object sender, EventArgs e)
6 {
7 Control.CheckForIllegalCrossThreadCalls = false;
8 this.Cursor = Cursors.WaitCursor;
9
10 Bitmap bm = new Bitmap(myPictureBox.Image);
11 int bevel_width = 10;
12 float offset = 0.5f;
13
14 Rectangle bounds = new Rectangle(0, 0, bm.Width, bm.Height);
15 m_BitmapData = bm.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
16 RowSizeBytes = m_BitmapData.Stride;
17
18 // Allocate room for the data.
19 int total_size1 = m_BitmapData.Stride * m_BitmapData.Height;
20 ImageBytes = new byte[total_size1];
21
22 // Copy the data into the ImageBytes array.
23 Marshal.Copy(m_BitmapData.Scan0, ImageBytes, 0, total_size1);
24
25 // Left edge.
26 for (int y = 0; y < bm.Height; y++)
27 {
28 int max_x = Math.Min(bevel_width - 1, y);
29 for (int x = 0; x <= max_x; x++)
30 {
31 ShadePixel(bm, x, y, offset * 0.75f);
32 }
33 }
34
35 // Top edge.
36 for (int x = 1; x < bm.Width; x++)
37 {
38 int max_y = Math.Min(bevel_width, x) - 1;
39 for (int y = 0; y <= max_y; y++)
40 {
41 ShadePixel(bm, x, y, offset);
42 }
43 }
44
45 // Right edge.
46 for (int y = 0; y < bm.Height; y++)
47 {
48 int min_x = bm.Width - Math.Min(bevel_width, y);
49 for (int x = min_x; x < bm.Width; x++)
50 {
51 ShadePixel(bm, x, y, -offset * 0.75f);
52 }
53 }
54
55 // Bottom edge.
56 for (int x = 0; x < bm.Width; x++)
57 {
58 int min_y = bm.Height - Math.Min(Math.Min(bevel_width, x), bm.Width - x);
59 for (int y = min_y; y < bm.Height; y++)
60 {
61 ShadePixel(bm, x, y, -offset);
62 }
63 }
64
65 int total_size2 = m_BitmapData.Stride * m_BitmapData.Height;
66 Marshal.Copy(ImageBytes, 0, m_BitmapData.Scan0, total_size2);
67
68 // Unlock the bitmap.
69 bm.UnlockBits(m_BitmapData);
70
71 myPictureBox.Image = bm;
72 this.Cursor = Cursors.Default;
73 }
74
75 // Make the pixel lighter or darker.
76 private void ShadePixel(Bitmap bm, int x, int y, float amount)
77 {
78 // Get the pixel's current color.
79 byte r, g, b;
80 GetPixel(x, y, out r, out g, out b);
81
82 // Shade it.
83 if (amount < 0)
84 {
85 // Darker.
86 amount = -amount;
87 r = (byte)(r * amount);
88 g = (byte)(g * amount);
89 b = (byte)(b * amount);
90 }
91 else
92 {
93 // Lighter.
94 r = (byte)(r + (255 - r) * amount);
95 g = (byte)(g + (255 - g) * amount);
96 b = (byte)(b + (255 - b) * amount);
97 }
98
99 // Save the result.
100 this.SetPixel(x, y, r, g, b, GetAlpha(x, y));
101 }
102
103 public void GetPixel(int x, int y, out byte red, out byte green, out byte blue)
104 {
105 byte alpha;
106 this.GetPixel(x, y, out red, out green, out blue, out alpha);
107 }
108
109 // Provide easy access to the color values.
110 public void GetPixel(int x, int y, out byte red, out byte green, out byte blue, out byte alpha)
111 {
112 int i = y * m_BitmapData.Stride + x * 4;
113 blue = ImageBytes[i++];
114 green = ImageBytes[i++];
115 red = ImageBytes[i++];
116 alpha = ImageBytes[i];
117 }
118
119 public void SetPixel(int x, int y, byte red, byte green, byte blue, byte alpha)
120 {
121 int i = y * m_BitmapData.Stride + x * 4;
122 ImageBytes[i++] = blue;
123 ImageBytes[i++] = green;
124 ImageBytes[i++] = red;
125 ImageBytes[i] = alpha;
126 }
127
128 public byte GetAlpha(int x, int y)
129 {
130 int i = y * m_BitmapData.Stride + x * 4;
131 return ImageBytes[i + 3];
132 }
效果和上面的圖片是一樣的,同時可以改變bevel_width和offset來調(diào)整效果。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:博客園