GDI+中常见的几个问题(5)
2008-10-29 16:16
288 查看
6.透明,半透明和不透明
这是个大题目。在WinForm/WPF里面我们经常会看到一些关于透明的属性,比如Backcolor里面可以选择Transparant, Form里面有一个叫Opacity的属性。都是和透明以及透明度相关的。在其实是在GDI+应用层上的一些东西,在这里我就不讲了。主要从更基本的地方讲起,其中还包括两块完全不同的内容。
6.1 Alpha
我们在上一讲中提到了PixelFormat,当时我们在LockBits的时候把PixelFormat设定成为Format24bppRgb。但是如果你仔细研究,会发现其实里面有各种各样的图片格式,其中有一种叫做Format32bppArgb。这个意思是说除了RGB,在图像中还存在一个通道,叫做A。这个A就是用来描述当前像素是透明,半透明,还是全透明的分量。这个通道是2个叫Catmull和Smith在上世纪70年代初发明的。通过这个分量,我们可以进行alpha混合的一些计算。从而使表面的图像和背景图像混合,从而造成透明半透明的效果。在这种格式下A作为一个byte,取值可以从0到255,那么0表示图像完全透明,则完全不可见,255则表示图像完全不透明。每个像素都可以实现这种透明或者半透明的效果。更详细解释可以参考http://en.wikipedia.org/wiki/Alpha_compositing,或者去买本数字图像处理的书回来看。让我们来看看下面这段代码,这个函数可以把图像变成半透明的。
1 public unsafe Bitmap GenerateBitmap(byte alpha)
2 {
3 FileStream fs = new FileStream(image, FileMode.Open, FileAccess.Read);
4 Image img = Image.FromStream(fs, false, false);
5 Bitmap bmp = new Bitmap(img);
6 img.Dispose();
7 fs.Close();
8
9 int width = bmp.Width;
10 int height = bmp.Height;
11
12 BitmapData bmData = bmp.LockBits(
13 new Rectangle(0, 0, width, height),
14 ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
15
16 byte* p = (byte*)bmData.Scan0;
17 int offset = bmData.Stride - width * 4;
18 for (int j = 0; j < height; j++)
19 {
20 for (int i = 0; i < width; i++)
21 {
22 p[3] = alpha;
23 p += 4;
24 }
25 p += offset;
26 }
27
28 bmp.UnlockBits(bmData);
29
30 return bmp;
31 }
32
大家可以注意一下第17,22和23行,由于图像格式不对了,所以我们计算offset和递加的操作都该了,此外由于用小数端存储方式,Alpha通道在p[3]的位置。
顺便提一句,还有一种格式叫做Format32bppPArgb,这叫做premultiplied alpha,就是说在RGB分量里面,alpha分量的数据已经被预先乘进去了。比如说,一个半透明的红色点,在ARGB下,矢量是(255,0,0,128),而在PARGB下就变成了(128,0,0,128)。这是为了不要每次都做乘法。
还有要注意的是,如果你想把这个Bitmap保存成为一个文件,那么必须用png格式,才能够保存alpha通道的信息。如果你存为JPG/BMP/GIF,那么alpha通道的信息将会被丢失。如果存为BMP,那么文件格式将变成Format32bppRgb,其中1个字节不再使用;如果保存为JPEG,那么是Format24bppRgb;存为GIF,格式将变成Format8bppIndexed。根据标准,BMP/JPG本来就不支持透明通道,所以没有可能保留透明信息。GIF倒是支持透明,但是GIF中颜色的信息都是索引,所以Alpha的解释对GIF完全没有效果,接下去我们来分析怎么样使用GIF的透明。
这是个大题目。在WinForm/WPF里面我们经常会看到一些关于透明的属性,比如Backcolor里面可以选择Transparant, Form里面有一个叫Opacity的属性。都是和透明以及透明度相关的。在其实是在GDI+应用层上的一些东西,在这里我就不讲了。主要从更基本的地方讲起,其中还包括两块完全不同的内容。
6.1 Alpha
我们在上一讲中提到了PixelFormat,当时我们在LockBits的时候把PixelFormat设定成为Format24bppRgb。但是如果你仔细研究,会发现其实里面有各种各样的图片格式,其中有一种叫做Format32bppArgb。这个意思是说除了RGB,在图像中还存在一个通道,叫做A。这个A就是用来描述当前像素是透明,半透明,还是全透明的分量。这个通道是2个叫Catmull和Smith在上世纪70年代初发明的。通过这个分量,我们可以进行alpha混合的一些计算。从而使表面的图像和背景图像混合,从而造成透明半透明的效果。在这种格式下A作为一个byte,取值可以从0到255,那么0表示图像完全透明,则完全不可见,255则表示图像完全不透明。每个像素都可以实现这种透明或者半透明的效果。更详细解释可以参考http://en.wikipedia.org/wiki/Alpha_compositing,或者去买本数字图像处理的书回来看。让我们来看看下面这段代码,这个函数可以把图像变成半透明的。
1 public unsafe Bitmap GenerateBitmap(byte alpha)
2 {
3 FileStream fs = new FileStream(image, FileMode.Open, FileAccess.Read);
4 Image img = Image.FromStream(fs, false, false);
5 Bitmap bmp = new Bitmap(img);
6 img.Dispose();
7 fs.Close();
8
9 int width = bmp.Width;
10 int height = bmp.Height;
11
12 BitmapData bmData = bmp.LockBits(
13 new Rectangle(0, 0, width, height),
14 ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
15
16 byte* p = (byte*)bmData.Scan0;
17 int offset = bmData.Stride - width * 4;
18 for (int j = 0; j < height; j++)
19 {
20 for (int i = 0; i < width; i++)
21 {
22 p[3] = alpha;
23 p += 4;
24 }
25 p += offset;
26 }
27
28 bmp.UnlockBits(bmData);
29
30 return bmp;
31 }
32
大家可以注意一下第17,22和23行,由于图像格式不对了,所以我们计算offset和递加的操作都该了,此外由于用小数端存储方式,Alpha通道在p[3]的位置。
顺便提一句,还有一种格式叫做Format32bppPArgb,这叫做premultiplied alpha,就是说在RGB分量里面,alpha分量的数据已经被预先乘进去了。比如说,一个半透明的红色点,在ARGB下,矢量是(255,0,0,128),而在PARGB下就变成了(128,0,0,128)。这是为了不要每次都做乘法。
还有要注意的是,如果你想把这个Bitmap保存成为一个文件,那么必须用png格式,才能够保存alpha通道的信息。如果你存为JPG/BMP/GIF,那么alpha通道的信息将会被丢失。如果存为BMP,那么文件格式将变成Format32bppRgb,其中1个字节不再使用;如果保存为JPEG,那么是Format24bppRgb;存为GIF,格式将变成Format8bppIndexed。根据标准,BMP/JPG本来就不支持透明通道,所以没有可能保留透明信息。GIF倒是支持透明,但是GIF中颜色的信息都是索引,所以Alpha的解释对GIF完全没有效果,接下去我们来分析怎么样使用GIF的透明。
相关文章推荐
- GDI+中常见的几个问题(8)
- GDI+中常见的几个问题(9)
- GDI+中常见的几个问题(3)
- GDI+中常见的几个问题(10)
- GDI+中常见的几个问题(11)
- GDI+中常见的几个问题(4)
- GDI+中常见的几个问题(4) 转
- GDI+中常见的几个问题(8.外传1)
- GDI+中常见的几个问题(6)
- GDI+中常见的几个问题(2)
- GDI+中常见的几个问题(7)
- GDI+中常见的几个问题(7)多帧图像
- GDI+中常见的几个问题(1)
- 学生信息管理系统常见的几个问题
- WIN8/8.1/10换系统常见的几个问题
- 常见的几个Qt编程问题的处理
- Android 在MediaRecorder中碰到的几个常见的问题
- 常见的编码不规范的几个问题
- 分享一下Mysql常见的几个错误问题及解决方法
- Java和jsp编程中应该注意的几个常见问题