我怎样才能加载48bpp图像的原始数据转换成位图? [英] How can I load the raw data of a 48bpp image into a Bitmap?

查看:632
本文介绍了我怎样才能加载48bpp图像的原始数据转换成位图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我问过类似的问题,做在这里和24bpp图像 但我使用此处描述的技术和有第二个问题,这个时候做48bpp ...

I asked a similar question to do with a 24bpp image here but I am using the techniques described there and have a second issue, this time to do with 48bpp...

我有一个字节[] 包含一个16位色彩深度的图像。所以有两个字节用于红色,两个用于绿色和两个蓝色,在顺序,从图像的左上角向右下角。我加载它变成位图像这样(考虑到跨越等):

I have a byte[] containing a 16bit color depth image. So there are two bytes for red, two for green and two for blue, in sequence, from the top left of the image to the bottom right. I am loading this into a Bitmap like so (taking into account the Stride etc):

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

和它产生这一形象:

图片是不正确的,但是,它应该是这样的:

The image is not correct, though, it should look like this:

所以,我的问题是,好了,我做了什么错?

So, my question is, well, what have I done wrong?

更新

如果我换了R1,R2和B1,B2(和绿色的)的情况下,字节序问题,但它绘制的图像是这样的:

If I switched the r1,r2 and b1,b2 (and the green ones) in case of an endianess issue , but then it draws the image like this:

(所以还是不对? - 但这是否给我们一个线索,以什么也许是怎么回事)

(so still not right - but does that give us a clue as to what is going on perhaps?)

我已经把一个文件上github上这里那就是原始数据,这样您就可以保存到磁盘,然后这个小方法打开它:

I have put a file up on github here that is the raw data so you can save that down to your disk and then this little method will open it up:

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库相反,那就是没问题。

If I need to use WPF libraries instead, that is fine with me.

更新2

所以,在评论中建议我想出了一点点code生成的字节数组,我可以推理。

So, as suggested in the comments I came up with a bit of code to generate a byte array that I could reason about.

我所做的,因此,是输出​​字节数组,它是196 * 200 * 6的长度,使得我有一个形象,是196像素宽200高,每个像素的6个字节(大小是很方便,因为它大足以看出,一个,这并不意味着我与跨越的事情打扰)。然后,我决定,我会分裂的画面分成4纵纹,字节,每个条带是:

What I did, therefore, was output a byte array that is 196 * 200 * 6 in length such that I will have an image that is 196 pixels wide by 200 high with 6 bytes per pixel (the size is handy as it is big enough to see and one that doesn't mean I have to bother with the Stride thing). I then decided that I would split the picture up into 4 vertical stripes, the bytes of which for each stripe are:

  • 0×00,0×00,0×00,0×00,为0xFF,0xFF的
  • 0×00,0×00,0×00,0×00,0×00,0xFF的
  • 0×00,0×00,0×00,0×00,0xFF时,0×00
  • 0×00,0×00,0×00,0×00,0×00,0×00

这应该意味着我能看到的颜色权利之间的区别是什么?那么,事实上,我是这样的,所以我在做什么错了?

This should mean I can see the difference between the colours right? Well, what I actually got was this, so what am I doing wrong?:

下面是我所生产的上述图像code:

Here is my code that produced the above image:

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格式什么的?

So, does any one know how I can get the byte array described here into a Bitmap that is correct? As I said, if there is anything in WPF that would help, that would be fine or maybe I need to transform it into, I don't know 64bppargb format or something?

推荐答案

所以,我已经找到了如何做到这一点,但它不是真正的完美...

So I have figured out how to do it, but it is not really perfect...

如果我想补充参考 System.Xaml presentationCore WindowsBase 并使用WPF图像类作为一个中间步骤,我可以得到一个的位图,像这样(使用数据.BIN的问题和 ReadRawData 方法链接文件):

If I add references for System.Xaml, PresentationCore and WindowsBase and use the WPF image classes as an intermediate step I can get to a Bitmap, like so (using the data.bin file linked in the question and the ReadRawData method):

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

等瞧!

我想我会做我的项目是沟 Windows.Drawing 完全给出这个问题,整个的疼痛步幅和事实,即RGB实际上是BGR(基本上我都腻了)。

I think what I will do in my project is ditch Windows.Drawing entirely given this problem and the whole pain with the stride and fact that RGB is actually BGR (basically I'm sick of it).

这篇关于我怎样才能加载48bpp图像的原始数据转换成位图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆