winform,Winform的Bitmap调色板的一个问题

帮人做一个遥感数字图像处理的小功能,其中的数据源是Landset图像,八位灰度。 然而Winform真的太弱了,System.Drawing下的PixelFormat(像素格式)枚举居然没有提供八位灰度模式,无奈只好用 PixelFormat.Format8bppIndexed(八位颜色索引)替代,可是问题又来了···
要使颜色索引模式生效,必须在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 = new Bitmap(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的,还是改了吧。


Tags:  winform

延伸阅读

最新评论

发表评论