2013-03-08 23 views
7

私は16ビットの色深度を含むbyte[]を持っている...、48bppイメージの生データをビットマップにロードするにはどうすればよいですか?

を48bppで行うには、この時間を私は24bppのイメージhereを行うには同様の質問をしたが、私はそこに記載されている技術を使用していますが、第二の問題を持っています画像。したがって、イメージの左上から右下に向かって、赤色の2バイト、緑色の2バイト、青色の2バイトが順番に並んでいます。

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); 
} 

、それはこのイメージを生成します:私はそう(ストライドなどを考慮に入れて)のようなBitmapにこれをロードしています

wrong image

画像は、それが必要、しかし、正しくありません。次のようになります。だから、

correct image

、私の質問は、よく、私が間違って何をしたのですか?


更新

私はエンディアンの問題の場合には、R1、R2およびB1、B2(及び緑色のもの)を切り替えますが、それはこのように画像を描画する場合:

endianness switch

(そう、まだ右ではない - それは私たちに、おそらく何が起こっているかのように手掛かりを与えるのでしょうか?)

私はあなたのディスクにそれをダウン保存することができ、その後、この小さなメソッドは、それを開きますので、生データであるgithubのhere上のファイルを我慢している:私は代わりに、WPFのライブラリを使用する必要がある場合は、

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; 
} 

をそれは私と一緒に良いです。


アップデート2

ので、コメントで提案されているように私はについて推論でき、バイト配列を生成するコードのビットを思い付きました。

私は196 * 200 * 6の長さのバイト配列を出力しました。これは、幅196ピクセル、高さ200ピクセル、ピクセル当たり6バイトのイメージを持ちます(サイズはそれは見えるほど大きく、ストライドのことを気にしなければならないという意味ではありません)。私は、私は4本の縦縞に画像を分割することを決定し、各ストライプのためのバイトは、次のとおり

  • は0x00、0x00に、0x00で、0x00に、0xFFの、0xFFの
  • は0x00、0x00に、0x00に、 $ 00、$ 00、0xFFの
  • $ 00、$ 00、$ 00、$ 00、0xFFの、0x00の
  • $ 00、$ 00、$ 00、$ 00、$ 00、$ 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などで実行できるだけであれば助けになります。 –

+2

おそらくビッグエンディアン/リトルエンディアンの問題ですか? r1/r2とb1/b2を逆にしてみてください。 –

+0

48 bpp画像は直接サポートされていないという考えがあります。 http://stackoverflow.com/q/7276212/56778を参照してください –

答えて

2

は、だから私はそれを行う方法を考え出したが、それは...本当に完璧ではありません

私は System.XamlPresentationCoreWindowsBaseのための参照を追加し、私が得ることができる中間ステップとしてWPFの画像クラスを使用する場合は

// 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); 
    } 
} 

ら出来上がり:そう(質問とReadRawData方法でリンクdata.binファイルを使用して)のような、Bitmapへ!

works.tiff

私は私が私のプロジェクトで行いますが、完全にこの問題と全体pain with the strideとRGBが実際にBGR(基本的に私はそれの病気だ)であるという事実与えられた溝Windows.Drawingだと思います。