WPF C#-将16位(8位多通道)RAW Heightmap加载到BitmapSource中



我正试图在我的WPF应用程序中显示一个16位RAW图像的预览,但它并没有像我希望的那样工作。我在SA甚至CodeProject上看到了无数的例子、问题/答案,但这也没让我走多远。事实上,它确实做到了,因为我可以完全加载一个8位灰度RAW图像,并在应用程序上显示它,而不会出现任何奇怪的伪影,但当涉及到16位图像时,它会变得一团糟。

下面是一个应该如何显示的示例:https://i.stack.imgur.com/kSCX5.jpg

这是我在尝试加载同一原始图像的16位版本(从第三方程序直接导出为16位)时得到的结果:https://i.stack.imgur.com/Melmk.jpg

将16位图像加载为8位可以得到正确图像的一半。

这些是我的导入功能:

BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open));
private void LoadRAWData8bit()
{
int bits = format.BitsPerPixel;
int stride = ((width * bits + (bits - 1)) & ~(bits - 1)) / 8;
byte[] pixels = new byte[stride * height];
for (int i = 0; i < br.BaseStream.Length; ++i)
pixels[i] = br.ReadByte();
br.Close();
BitmapSource bmp = BitmapSource.Create(width, height, 96, 96, format, null, pixels, stride);
RawFile = new CRAW(new Size(width, height), format, stride, bmp);
}
// 16bit load Test
private void LoadRAWData16bit()
{
WriteableBitmap wBmp = new WriteableBitmap(width, height, 96, 96, format, null);
int bpp = format.BitsPerPixel / 8;
byte[] pixels = new byte[wBmp.PixelWidth * wBmp.PixelHeight];
Int32Rect drawRegionRect = new Int32Rect(0, 0, wBmp.PixelWidth, wBmp.PixelHeight);
for (int i = 0; i < br.BaseStream.Length; ++i)
pixels[i] = br.ReadByte();
br.Close();
int stride = wBmp.PixelWidth * bpp;
wBmp.WritePixels(drawRegionRect, pixels, stride, 0);
RawFile = new CRAW(new Size(width, height), format, stride, wBmp);
}

(请不要介意传递给CRAW类的参数,我现在只做实验,直到我能正确工作为止。)

我是不是少了一步?有人知道如何让它发挥作用吗?我试着用ushort数组代替字节数组来实现同样的8位导入函数:

private void LoadRAWData16bit()
{
int bits = format.BitsPerPixel;
int stride = ((width * bits + (bits - 1)) & ~(bits - 1)) / 8;
int bpp = format.BitsPerPixel / 8;
ushort[] pixels = new ushort[stride * height * bpp];
for (int i = 0; i < br.BaseStream.Length; i += sizeof(ushort))
pixels[i] = br.ReadUInt16();
br.Close();
BitmapSource bmp = BitmapSource.Create(width, height, 96, 96, format, null, pixels, stride);
RawFile = new CRAW(new Size(width, height), format, stride, bmp);
}

像这样,但这样做会给我一半的图像,而且它比预期的要暗得多,因为数组中每2个字节就有1个字节的值为0。做像素[i/2]再次给我提供了前面提到的相同图像(16位加载样本)。

将16位原始图像加载到Photoshop中会显示导入对话框,该对话框建议将通道计数2设置为8位(使用2个通道将其设置为16位不允许我导入,但使用1个通道将16位有效)。

这可以解释为什么将16位图像作为8位加载到我的WPF应用程序中只导入其中的一半……但这给我留下了一个很大的问号,为什么它也没有加载第二个通道。

这个话题的文献很少,几乎没有任何地方讨论过。在这件事上什么也找不到。。希望能找到一个能帮我的人。

谢谢,新年快乐!

通过分析找到了自己的解决方案。十六进制编辑器中的RAW图像。

基本上,多通道8/16位RAW图像的结构如下屏幕截图所示(8位示例):http://puu.sh/t97fY/6920f804af.png

第一个字节属于图像本身(根据Photoshop也称为Alpha 1),第二个字节是第二个通道(称为Alpha 2)。每个图像层的字节是交替的,如屏幕截图所示。在上面显示的屏幕截图中,0x00字节属于第二通道,而其他字节(59、57、58、56等)属于主图像。

在这一点上,拆分两层非常简单。自BitmapSource。Create用原始字节生成一个位图,我们所要做的就是循环通过FileStream并替换目标缓冲区,以将字节放入其正确的缓冲区中,然后将这些缓冲区提供给BitmapSource类。

如果RAW图像没有alpha通道,只有普通图像本身,您可以分配一个与普通图像一样大的缓冲区,并用0x00填充,这将给您一个空白的alpha层。

如何以编程方式确定RAW图像是否具有alpha通道也很容易。给定宽度和高度,多通道RAW图像的大小将是基础图像的两倍。

示例:

Width: 128
Height: 128
RAW Image Size: 32768
128 * 128 = 16384

如果

file_size==宽度*高度

则我们没有alpha通道。

如果

file_size==宽度*高度*2

那么我们有一个alpha通道。

希望这能在将来帮助到别人。有太多的RAW图像格式,它很快就会变得非常混乱,尤其是对于那些使用Heightmaps/Photoshop RAW图像并试图通过编程操作这些图像的人来说。。这些格式似乎没有很好的记录。。或者,尽管我花了一整个下午的时间讨论这个话题,但我可能只是挖掘得不够。

相关内容

  • 没有找到相关文章

最新更新