2017-01-01 255 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圖像一起工作的人,試圖以編程方式操縱這些圖像。這些格式似乎沒有很好的記錄..或者我只是簡單地儘管我在這個話題上花了整整一個下午,但並沒有挖掘到足夠的信息。