我正在尝试在我的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);
}
像这样,但这样做会给我一半的图像并且它比它应该的颜色更暗,因为数组中每个第二个字节有1个字节,值为0.做像素[i / 2]再次给我像之前提到的相同的图像(16位加载样本)。
将16位原始图像加载到Photoshop中会显示导入对话框,其中将通道计数设置为2为8位(将其设置为16位,使用2个通道将不允许我导入它,但是16位,1个通道可以工作)。 / p>
这可以解释为什么将16位图像作为8位加载到我的WPF应用程序中只导入其中的一半..但这给我留下了一个很大的问号,为什么它也没有加载第二个通道。
这个主题记录很少,几乎没有在任何地方讨论过。在这件事情上找不到任何地方。希望找到一个能够帮助我的人。
谢谢新年快乐!
答案 0 :(得分:0)
通过在Hex编辑器中分析.RAW图像,找到了解决方案。
基本上,多通道8/16位RAW图像的结构如此屏幕截图所示(8位示例):http://puu.sh/t97fY/6920f804af.png
第一个字节属于图像本身(根据Photoshop也称为Alpha 1),第二个字节是第二个通道(称为Alpha 2)。 每个图像层的字节交替,如屏幕截图所示。 在上面显示的屏幕截图中,0x00字节属于第二个通道,而其他字节(59,57,58,56等)属于主图像。
此时拆分2层非常简单。由于BitmapSource.Create从原始字节生成位图,我们所要做的就是遍历FileStream并交替使用目标缓冲区以使字节适合其正确的缓冲区,然后将其提供给BitmapSource类。
如果RAW图像没有Alpha通道,只有普通图像本身,您可以分配一个与普通图像一样大的缓冲区,并用0x00填充它,这将为您提供一个空白的alpha图层。
如何以编程方式确定RAW图像是否具有Alpha通道也很容易。给定宽度和高度,多通道RAW图像的大小将是基本图像的两倍。
示例:
Width: 128
Height: 128
RAW Image Size: 32768
128 * 128 = 16384
如果
file_size == width * height
然后我们没有alpha通道。
如果
file_size == width * height * 2
然后我们就有了一个alpha通道。
希望这可以在将来帮助某人。有很多RAW图像格式,它可以非常快速地混淆,特别是那些使用Heightmaps / Photoshop RAW图像试图以编程方式操作这些图像的人。这些格式似乎没有很好的记录......或者也许虽然我花了整整一个下午来讨论这个话题,但我根本就没有足够的挖掘力。