在C#中使用RGB数组创建位图,结果图像差异?

时间:2017-12-21 05:26:26

标签: c# arrays image bitmap

我正在使用类似this answer的方法从字节数组创建位图。

private static void MySaveBMP(byte[] buffer, int width, int height)
{
    Bitmap b = new Bitmap(width, height, PixelFormat.Format24bppRgb);
    Rectangle BoundsRect = new Rectangle(0, 0, width, height);
    BitmapData bmpData = b.LockBits(BoundsRect,
                                    ImageLockMode.WriteOnly,
                                    b.PixelFormat);
    IntPtr ptr = bmpData.Scan0;

    // fill in rgbValues
    Marshal.Copy(buffer, 0, ptr, buffer.Length);
    b.UnlockBits(bmpData);
    b.Save(@"D:\myPic.bmp", ImageFormat.Bmp);        
}

我生成一个字节数组,填写一些像这样的值:

int width = 20;
int height = 30;
int bytesPerPixel = 3;
int bytesPerRow = width * bytesPerPixel;
int totalLength = bytesPerRow * height;            
byte[] managedArray = new byte[totalLength];

// fill background with white
for (int i = 0; i < totalLength; i++)
    managedArray[i] = 255;

// draw on each row
for (int i = 0; i < height; i++)
{
    // first pixel is green
    managedArray[0 + i * bytesPerRow] = 0;
    managedArray[1 + i * bytesPerRow] = 255;
    managedArray[2 + i * bytesPerRow] = 0;
    // last pixel is red
    managedArray[bytesPerRow - 3 + i * bytesPerRow] = 0;
    managedArray[bytesPerRow - 2 + i * bytesPerRow] = 0;
    managedArray[bytesPerRow - 1 + i * bytesPerRow] = 255;
}
MySaveBMP(managedArray, width, height);

生成的20x30 bmp图像如下所示:

20x30 bmp image

但是,如果我更改图像高度(例如,更改为21),则生成的图像似乎已损坏。 每一行看起来都向左移动了一点:

21x30 bmp image

制作位图图像时我做错了什么?

1 个答案:

答案 0 :(得分:1)

我想我找到了答案。 因为我不知道BitmapData.Stride属性。有人有答案here.

我修改过的保存功能在这里:

    private static void MySaveBMP(byte[] buffer, int width, int height)
    {
        Bitmap b = new Bitmap(width, height, PixelFormat.Format24bppRgb);

        Rectangle BoundsRect = new Rectangle(0, 0, width, height);
        BitmapData bmpData = b.LockBits(BoundsRect,
                                        ImageLockMode.WriteOnly,
                                        b.PixelFormat);

        IntPtr ptr = bmpData.Scan0;

        // add back dummy bytes between lines, make each line be a multiple of 4 bytes
        int skipByte = bmpData.Stride - width*3;
        byte[] newBuff = new byte[buffer.Length + skipByte*height];
        for (int j = 0; j < height; j++)
        {
            Buffer.BlockCopy(buffer, j * width * 3, newBuff, j * (width * 3 + skipByte), width * 3);
        }

        // fill in rgbValues
        Marshal.Copy(newBuff, 0, ptr, newBuff.Length);
        b.UnlockBits(bmpData);
        b.Save(@"D:\myPic.bmp", ImageFormat.Bmp);        
    }

另一个解决方案是,我将PixelFormat更改为Format32bppPArgb,并将bytesPerPixel更改为4.因此,我不需要打扰4字节扫描线格式。