我问了一个与24bpp图像有关的类似问题here但是我正在使用那里描述的技术并有第二个问题,这次是关于48bpp ......
我有byte[]
包含16位色深图像。因此,从图像的左上角到右下角,有两个字节用于红色,两个用于绿色,两个用于蓝色。我正在加载Bitmap
这样(考虑到Stride等):
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 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字节的图像(尺寸很方便,因为它足够大,可以看到,并不意味着我必须打扰Stride的事情)。然后我决定将图片分成4个垂直条纹,每个条纹的字节为:
这应该意味着我可以看到颜色之间的差异吧?嗯,我实际得到的是这个,所以我做错了什么?:
以下是产生上述图片的代码:
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 :(得分:2)
所以我已经想出了怎么做,但它并不是很完美......
如果我添加System.Xaml
,PresentationCore
和WindowsBase
的引用并使用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);
}
}
et voila!
我认为我将在我的项目中做的是完全给出这个问题的沟渠Windows.Drawing
以及整个pain with the stride以及RGB实际上是BGR的事实(基本上我已经厌倦了它)。