ここで 24bpp イメージを処理するために同様の質問をしましたが、そこで説明されている手法を使用しており、2 つ目の問題があります。今回は 48bpp を処理するためです...
byte[]
16ビットの色深度画像を含むがあります。したがって、画像の左上から右下に向かって、赤に 2 バイト、緑に 2 バイト、青に 2 バイトが順番に存在します。これを次のようにロードしてい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);
}
そして、次の画像が生成されます。
画像は正しくありませんが、次のようになります。
それで、私の質問は、まあ、私は何を間違えたのですか?
アップデート
エンディアンの問題が発生した場合に r1,r2 と b1,b2 (および緑色のもの) を切り替えた場合、次のような画像が描画されます。
(まだ正しくありませんが、何が起こっているのかについての手がかりを与えてくれますか?)
生データであるファイルを github に置いたので、それをディスクに保存してから、この小さな方法でファイルを開くことができます。
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、0x00、0x00、0x00、0xFF、0xFF
- 0x00、0x00、0x00、0x00、0x00、0xFF
- 0x00、0x00、0x00、0x00、0xFF、0x00
- 0x00、0x00、0x00、0x00、0x00、0x00
これは、色の違いがわかるということですか?さて、私が実際に得たのはこれでした。では、何が間違っているのでしょうか?:
上記の画像を生成したコードは次のとおりです。
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形式などを知りませんか?