2014-10-08 101 views
0

我似乎无法将我的大脑包围图像并将其从原始RGB颜色的byte[]转换为BitMap。我发现了一个解决方案,它允许我使用SetPixel将RGB 24bpp byte[]转换为BitMap,但我读过使用LockBits的速度要快得多,所以我正试图弄清楚如何以这种方式进行。RGB 24到BitMap造成黑色图像

使用SetPixel方法,我正在用倒置图像:

public static Bitmap CreateBitmap24bppRgb(byte[] bmpData, int width, int height) 
{ 
    var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); 
    var pos = 0; 
    for (var y = 0; y < height; y++) 
    { 
     for (var x = 0; x < width; x++) 
     { 
      bmp.SetPixel(x, y, Color.FromArgb(bmpData[pos], bmpData[pos + 1], bmpData[pos + 2])); 
       pos += 3; 
     } 
    } 

    return bmp; 
} 

,我可以不太似乎弄清楚如何反转。但是当我尝试使用LockBits时,图像只是黑色,我不确定我做错了什么,它看起来很直截了当。

public static Bitmap CreateBitmap24bppRgb(byte[] data, int width, int height) 
{ 
    var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); 

    //Create a BitmapData and Lock all pixels to be written 
    var bmpData = bmp.LockBits(
         new Rectangle(0, 0, bmp.Width, bmp.Height), 
         ImageLockMode.WriteOnly, bmp.PixelFormat); 

    //Copy the data from the byte array into BitmapData.Scan0 
    for (int y = 0; y < bmp.Height - 1; y++) 
    { 
     Marshal.Copy(data, y * bmp.Width, bmpData.Scan0 bmpData.Stride); 
    } 


    //Unlock the pixels 
    bmp.UnlockBits(bmpData); 

    return bmp; 
} 

我只是好奇这里怎么了?

+1

位图数据是* *通常存储倒置。你的Marshal.Copy()方法看起来像无稽之谈,邮政编码实际上可以编译。第三个参数应该是bmpData.Scan0 +(bmp.Height - y - 1)* bmpData.Stride。 – 2014-10-08 15:16:54

+0

除了Hans的评论:在lockBits期间,你究竟用'data'做了什么?你将不得不__set__一些像素的渠道那里..!看例如[这里](http://stackoverflow.com/questions/26224095/how-to-find-the-difference-between-two-images/26225153#26225153)为一个工作lockBits代码的例子。当然还有更多... – TaW 2014-10-08 15:30:57

回答

4

如果您要创建一个新的位图,而不是修改现有的位图,则没有理由使用LockBitsMarshal.Copy

只要去与the Bitmap constructor that takes a pointer to pixel data

public static Bitmap CreateBitmap24bppRgb(byte[] data, int width, int height) 
{ 
    GCHandle pin = GCHandle.Alloc(data, GCHandleType.Pinned); 
    var bmp = new Bitmap(width, height, 
         (width * 3 + 3)/4 * 4, 
         PixelFormat.Format24bppRgb, 
         Marshal.UnsafeAddrOfPinnedArrayElement(data, 0)); 
    bmp = (Bitmap)bmp.Clone(); // workaround the requirement that the memory address stay valid 
           // the clone step can also crop and/or change PixelFormat, if desired 
    GCHandle.Free(pin); 
    return bmp; 
} 

(或使用unsafe块,pinned关键字,和一个指针)