Winform的Bitmap调色板的一个问题
2011-03-27 01:07 贼寇在何方 阅读(2415) 评论(7) 编辑 收藏 举报帮人做一个遥感数字图像处理的小功能,其中的数据源是Landset图像,八位灰度。
然而Winform真的太弱了,System.Drawing下的PixelFormat(像素格式)枚举居然没有提供八位灰度模式,无奈只好用
要使颜色索引模式生效,必须在Bitmap的调色板中设置每个索引到具体的颜色的映射:
for (int i = 0; i < 256; i++){// 每一个灰度映射到一种颜色bmp.Palette.Entries[i] = Color.FromArgb(i, i, i);}
运行结果,图像呈现了一种蓝色色调,没有在灰度模式下显示。
我找到了bmp.Palette的定义,Bitmap的Palette属性可读可写,是一个ColorPalette(调色板)对象(MSDN链接)。
那么是否能够直接对这个属性赋值呢?
似乎有难度,因为“调色板”没有一个公开的构造方法。于是谷歌了一下解决方法,有一位网友是这么做的:
Bitmap bmpTemp = newBitmap(1, 1, PixelFormat.Format8bppIndexed);ColorPalette palette = bmpTemp.Palette;for (int i = 0; i < 256; i++){palette.Entries[i] = Color.FromArgb(i, i, i);}bmp.Palette = palette;
特别构造了一个临时的Bitmap,为的就是取他的调色板。运行后,确实有效,灰度图像正常显示。
有没有不用更容易的办法呢?有!我在后面的尝试当中,发现了另一种方法:
ColorPalette palette = bmp.Palette;for (int i = 0; i < 256; i++){palette.Entries[i] = Color.FromArgb(i, i, i);}bmp.Palette = palette;
和第一段代码没有什么差别啊,只是定义一个新的变量来保存bmp.Palette。这段代码如何能够起作用呢?
但确实起作用了···
按照正常的思维,ColorPalette是引用类型,所以palette只是复制了bmp.Palette的引用,最后一句把自己的引用重新赋值回来应当没有用处,因此效果和第一段代码应当一样!!
既然MSDN不能解决疑惑,那只有求助于Reflector了。
在Bitmap的父类Image中,找到了Palette属性的实现:
public ColorPalette get_Palette()
{
return this._GetColorPalette();
}
private ColorPalette _GetColorPalette()
{
······
ColorPalette palette = new ColorPalette(size);
IntPtr ptr = Marshal.AllocHGlobal(size);
······
return palette;
}
很明显,Bitmap.Palette并没有像普通的属性一样,返回对应字段的引用,而是复制了一份新的。这就好的解释了为什么第一段代码完全没有效果。
当然,这样的类用起来实在不爽,不了解他的内部构造,就没有办法正常使用。能改用WPF的,还是改了吧。