2017-01-01 22 views
0

我试图在我的WPF应用程序中显示16位RAW图像的预览,但它不工作,因为我希望它会。我已经看了无数的例子,在这里关于SA甚至是CodeProject的问题/答案,但是这并没有让我感到很头疼。嗯,实际上它可以完全加载8bit灰度RAW图像并将其显示在应用程序中,而不会有任何奇怪的人为因素,但是当涉及到16位图像时,它会变得混乱起来。WPF C# - 将16位(8位多通道)RAW高度图加载到BitmapSource中

下面是它应该如何看一个例子: https://i.stack.imgur.com/kSCX5.jpg

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

将8bit图像加载为8bit会给我一半的正确图像。

这是我的导入功能:

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类的参数,我只经历过了,现在,直到我能得到这个工作正常)

我错过了一个步骤?有谁知道如何让这个工作?我试图做出同样的8位输入功能与USHORT阵列,而不是一个字节数组:

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位加载样本)。

将16bit原始图像加载到Photoshop中,显示导入对话框,其中显示2为8位的通道数(使用2个通道将其设置为16位不会让我导入,但1通道可使用16位)。

这可以解释为什么将16位图像加载到我的WPF应用程序中只能输入其中的一半..但是这留下了一个很大的问号,为什么它不加载第二个通道。

此主题记录不完整,几乎没有讨论任何地方。在这个问题上找不到任何东西..希望找到能够帮助我的人。

谢谢新年快乐!

回答

0

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

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

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

在这一点上拆分2层非常简单。由于BitmapSource。Create从原始字节中生成一个位图,我们所要做的就是遍历FileStream并交替目标缓冲区,以适应正确缓冲区中的字节,这些缓冲区之后将被馈送到BitmapSource类。

万一RAW图像没有alpha通道,但只是普通图像本身,则可以分配那样大平原图像缓冲器和用0x00填充它,这将给你一个空白阿尔法层。

如何以编程确定是否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图像一起工作的人,试图以编程方式操纵这些图像。这些格式似乎没有很好的记录..或者我只是简单地尽管我在这个话题上花了整整一个下午,但并没有挖掘到足够的信息。