2013-03-08 71 views
7

我問過類似的問題和24bpp圖像here這樣做,但我使用有描述的技術,並有第二個問題,這個時候做48bpp ...如何將48bpp圖像的原始數據加載到位圖中?

我有一個包含16位色彩深度的byte[]圖片。所以從圖像的左上角到右下角依次有兩個字節紅色,兩個綠色和兩個藍色。我加載此爲Bitmap像這樣(考慮到跨越等):

byte[] data = ReadRawData(); 

// Swap from rgb to bgr 
for (int i = 5; i < data.Length; i+=6) 
{ 
    var r1 = data[i - 5]; 
    var r2 = data[i - 4]; 

    var b1 = data[i - 1]; 
    var b2 = data[i]; 

    data[i - 5] = b1; 
    data[i - 4] = b2; 

    data[i - 1] = r1; 
    data[i] = r2; 
} 

// Load into a bitmap (I know the width and height, and the format 
using (var b = new Bitmap(157, 196, PixelFormat.Format48bppRgb)) 
{ 
    var bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), 
    ImageLockMode.ReadWrite, b.PixelFormat); 

    // Here we loop through each line and make sure it is padded to 
    // the stride length 
    var bytesPerLine = b.Width * 6; 
    for (int i = 0; i < b.Height; i++) 
    { 
    IntPtr offset = bmpData.Scan0 + i * bmpData.Stride; 
    Marshal.Copy(data, i * bytesPerLine, offset, bytesPerLine); 
    int padding = bmpData.Stride - bytesPerLine; 

    if (padding > 0) 
    { 
     var pad = new byte[padding]; 
     Marshal.Copy(pad, 0, offset + bytesPerLine, padding); 
    } 
    } 
    b.UnlockBits(bmpData); 
    // Done so save 
    b.Save("c:\\out.tiff", ImageFormat.Tiff); 
} 

它產生這一形象:

wrong image

的圖像是不正確的,但是,它應該是這樣的:

correct image

所以,我的問題是,好了,我做了什麼錯?


更新

如果我換了R1,R2和B1,B2(和綠色的)中的字節序問題的情況下,但隨後繪製這樣的形象:

endianness switch

(所以仍然沒有正確的 - 但是這給我們一個線索是什麼也許是怎麼回事?)

我已經把文件了GitHub上here這是原始數據,這樣就可以保存下來,爲您的磁盤,然後這個小方法打開它:

private static byte[] ReadRawData() 
{ 
    byte[] data; 
    using (var ms = new MemoryStream()) 
    { 
     using (var f = File.OpenRead("c:\\data16.bin")) 
     { 
      byte[] buffer = new byte[2048]; 
      int read; 
      while ((read = f.Read(buffer, 0, buffer.Length)) > 0) 
      { 
        ms.Write(buffer, 0, read); 
      } 
     } 
     data = ms.ToArray(); 
    } 
    return data; 
} 

如果我需要使用WPF庫相反,這對我來說很好。


更新2

所以,在意見提出,我想出了一些代碼生成的字節數組,我可以推理。因此,我所做的是輸出一個長度爲196 * 200 * 6的字節數組,這樣我就可以得到一幅寬196像素,高200像,每像素6字節的圖像(這個大小非常方便它足夠大,看到一個並不意味着我不得不打擾的步幅)。然後我決定,我將分割的圖片分成4個垂直條紋,其中用於每個條帶的字節爲:

  • 0x00時,0×00,0x00時,0×00,爲0xFF,0xFF的
  • 0x00時,0×00,0×00,爲0x00,0x00時,0xFF的
  • 爲0x00,0x00時,爲0x00,0x00時,爲0xFF,0×00
  • 爲0x00,0x00時,0×00,0×00,0×00,0×00

這應該意味着我可以看到顏色之間的差別對?那麼,事實上,我是這樣的,所以我在做什麼錯?:

After second attempt

這裏是我的代碼所產生的上圖:

using System; 
using System.Drawing; 
using System.Drawing.Imaging; 
using System.IO; 
using System.Runtime.InteropServices; 

namespace ImagePlayingApplication 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      const int width = 196; 
      const int height = 200; 
      const int columnWidth = width/4; 
      const int bytesPerPixel = 6; 

      var data = new byte[width * height * bytesPerPixel]; 
      for (int y = 0; y < height; y++) 
      { 
       for (int x = 0; x < width * bytesPerPixel; x += bytesPerPixel) 
       { 
        int i = y * width * bytesPerPixel + x; 

        // Blue and Green components 
        // always 0x00 since we are just 
        // interested in red 
        data[i] = 0x00; 
        data[i + 1] = 0x00; 
        data[i + 2] = 0x00; 
        data[i + 3] = 0x00; 

        if (x < columnWidth * bytesPerPixel) 
        { 
         // Left most column, full red 
         data[i + 4] = 0xFF; 
         data[i + 5] = 0xFF; 
        } 
        else if (x < columnWidth * bytesPerPixel * 2) 
        { 
         // Next left, half red 
         data[i + 4] = 0x00; 
         data[i + 5] = 0xFF; 
        } 
        else if (x < columnWidth * bytesPerPixel * 3) 
        { 
         // Next left, other half red 
         data[i + 4] = 0xFF; 
         data[i + 5] = 0x00; 
        } 
        else 
        { 
         // Final column, no red 
         data[i + 4] = 0x00; 
         data[i + 5] = 0x00; 
        } 
       } 
      } 

      using (var b = new Bitmap(width, 
             height, 
             PixelFormat.Format48bppRgb)) 
      { 
       var bmpData = b.LockBits(
        new Rectangle(0, 0, b.Width, b.Height), 
        ImageLockMode.ReadWrite, 
        b.PixelFormat); 
       Marshal.Copy(data, 0, bmpData.Scan0, data.Length); 
       b.UnlockBits(bmpData); 

       b.Save(@"c:\users\public\stripes2.tiff", ImageFormat.Tiff); 
      } 
     } 
    } 
} 

因此,沒有任何一個知道如何我可以將這裏描述的字節數組轉換成正確的位圖嗎?正如我所說,如果WPF中有什麼可以幫助的話,那可能很好,或者我需要將它轉換爲,我不知道64bppargb格式或其他什麼?

+0

你可以發佈一個完整的程序/例子,包括圖像數據,作爲文件(鏈接)還是用C#聲明的字節數組?如果他們能夠複製你的示例代碼並運行在Visual Studio或LINQPad或類似的代碼中,它將有助於未來的幫助者。 – 2013-03-08 19:52:11

+2

可能是Big-Endian/Little-Endian問題?嘗試反轉r1/r2和b1/b2。 – 2013-03-08 20:56:21

+0

我知道48 bpp圖像不直接支持。看到http://stackoverflow.com/q/7276212/56778 – 2013-03-08 23:54:42

回答

2

所以我已經找到了如何做到這一點,但它不是真正的完美......

如果我添加引用了System.XamlPresentationCoreWindowsBase和使用WPF圖像類作爲一箇中間步驟,我可以得到到Bitmap,像這樣(使用data.bin文件中的問題鏈接和ReadRawData法):

// Declare what we know 
const int width = 157; 
const int height = 196; 
const double dpi = 50; 
var format = PixelFormats.Rgb48; 
int stride = (width * format.BitsPerPixel + 7)/8; 

// Get the data (see the question for this method) 
var data = ReadRawData(); 

// Now put the data into a WiteableBitmap 
var wb = new WriteableBitmap(width, height, dpi, dpi, format, null); 
wb.WritePixels(new Int32Rect(0, 0, width, height), data, stride, 0); 

// Encode as a TIFF 
var enc = new TiffBitmapEncoder { Compression = TiffCompressOption.None }; 
enc.Frames.Add(BitmapFrame.Create(wb)); 

// And convert to a bitmap 
using (var ms = new MemoryStream()) 
{ 
    enc.Save(ms); 

    using (var bmp = new Bitmap(ms)) 
    { 
     // Blergh, I feel dirty! 
     bmp.Save("c:\\works.tiff", ImageFormat.Tiff); 
    } 
} 

等瞧!

works.tiff

我想我會在我的項目做的是溝Windows.Drawing完全放棄這個問題,整個pain with the stride和事實,即RGB實際上是BGR(基本上我都膩了)。

相關問題