彩票走势图

解决WPF中BitmapEffect过时的方法

转帖|其它|编辑:郝浩|2011-04-15 11:23:56.000|阅读 2753 次

概述:最近项目有个需求,需要显示出图片Image的“SUNKEN”效果,就是可以将图片变成各种凹凸的形状,可能有些园友也做过类似的需求。在WPF 3.5(及之前)版本中,这个效果很简单就可以实现,直接应用BevelBitmapEffect就可以实现这样的效果。

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

  最近项目有个需求,需要显示出图片Image的“SUNKEN”效果,就是可以将图片变成各种凹凸的形状,可能有些园友也做过类似的需求。

  在WPF 3.5(及之前)版本中,这个效果很简单就可以实现,直接应用BevelBitmapEffect就可以实现这样的效果。

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开始,微软已经宣布这个API已经过时了,也即意味着在WPF 4.0及之后已经不支持这个效果了。

  Code中的代码也会受到警告:

  而且,这种效果最终在界面上是不会起作用的,这就很让人dan疼了。

  微软放弃使用这个API的原因,很大程度上是这种效果是由软件渲染的,其代价就是如果在项目中有比较多这种效果,则会占用大量的性能。而微软在WPF中主要是推荐由硬件去渲染这些特效的,所以保留了Effect,新加入了ShaderEffect,推荐使用着色器来提升效果,感兴趣的园友可以去研究。

  由于时间比较紧,对ShaderEffect也不是很熟悉,所以暂时使用了另外的途径来替代实现这种效果。

  原理是使用对Bitmap进行重绘,然后将重绘后的byte数据再写回去,替换原先PictureBox中的Image。

  缺点显而易见,性能不好。 但是由于赶时间,只好等日后去研究ShaderEffect再来优化了。

  下面放出代码:

  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来调整效果。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn

文章转载自:博客园

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP