C# - Bitmap中的RGB缓冲区与C ++不同 [英] C# - RGB Buffer from Bitmap different from C++

查看:222
本文介绍了C# - Bitmap中的RGB缓冲区与C ++不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用第三方DLL,它具有RGB缓冲区作为参数。

I'm using a third party DLL which has as parameter a RGB buffer.

我使用以下代码从位图读取RGB缓冲区:

I have used the following code to read RGB buffer from Bitmap:

private byte[] GetBGRValues(Bitmap bmp)
    {

        // Lock the bitmap's bits. 
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;
        // Declare an array to hold the bytes of the bitmap.
        int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
        byte[] rgbValues = new byte[bytes];


        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); 
        bmp.UnlockBits(bmpData);

        return rgbValues;
    }

问题是生成的RGB缓冲区不正确。如果我在IrfanView中打开此缓冲区,提供正确的参数,生成的图像不正确(看起来像是移位)。

The problem is that the generated RGB buffer is not correct. If I open this buffer in IrfanView, supplying correct parameters, the generated image is not correct (looks like it is shifted).

如果获取我使用的缓冲区它可以使用的C ++代码。

If a get a buffer that I read using C++ code it works.

我注意到 bmpData.Stride 比我预期的大1个单位( width * channels )。 (我知道.NET使用4个字节对齐)。

I have noticed that bmpData.Stride is 1 unity greater than what I was expecting (width * channels). (I know that .NET uses 4 bytes alignment).

问题是:为什么RGB缓冲区不正确?

The question is: why is the RGB buffer not correct?

推荐答案

你注意到了 - 你需要考虑 Stride 。通常,您不能简单地在一个复制调用中复制图像。 Stride 包括行长度和填充,并且可能大于行长度。因此,您只需要从每行复制所需的字节,忽略填充字节并通过添加 Stride 前进到下一行。

You noticed right - you need to take Stride into account. In general you cannot simply copy image in one Copy call. Stride include both row length and padding and could be greater then row length. So you need to copy only bytes you need from each row, ignore padding bytes and advance to next row by adding Stride.

我想这就是您在代码中看到的内容:

I guess this is what you see with your code:

- 原始图像和预期结果

- original image and expected result

- 无效结果无效

- invalid result without stride

以下是工作代码:

public static byte[] GetBGRValues(Bitmap bmp)
{
    var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    var bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

    var rowBytes = bmpData.Width * Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
    var imgBytes = bmp.Height * rowBytes;
    byte[] rgbValues = new byte[imgBytes];

    var ptr = bmpData.Scan0;
    for (var i = 0; i < bmp.Height; i++)
    {
        Marshal.Copy(ptr, rgbValues, i * rowBytes, rowBytes);
        ptr += bmpData.Stride; // next row
    }

    bmp.UnlockBits(bmpData);

    return rgbValues;
}

您可以在此答案中阅读更多详细信息:

More details you can read in this answer: Byte Array to Image Conversion

也许这张图片会帮助你理解 Stride 目的:

Also maybe this image will help you to understand Stride purpose:

当您从<$获取字节时,您需要跳过右侧的白色区域c $ c>位图。

这篇关于C# - Bitmap中的RGB缓冲区与C ++不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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