c# BitMap的data是rgb格式还是bgr格式
实验结果
BitMap是bgr格式
为什么是bgr格式
- 历史与底层图形库的依赖
GDI/GDI+ 的遗留设计:
C# 的 System.Drawing 命名空间基于 Windows 的 GDI/GDI+ 图形接口,而 GDI 在早期为了兼容某些硬件(如显卡帧缓冲)和旧标准,采用了 BGR 内存布局。这种格式在 Windows 系统中更高效,因为许多底层驱动和硬件优化(如 DirectDraw)默认支持 BGR。
字节顺序(Endianness)的影响:
在 x86/x64 架构的小端(Little-Endian)系统中,多字节数据(如 32 位 ARGB 像素)的存储顺序是 从低位到高位。例如:
Format32bppArgb 的字节布局:[Blue, Green, Red, Alpha](内存地址从低到高)。
这种布局直接映射到 CPU 和显卡的优化操作。 - 与 Windows 原生格式兼容
DIB(设备无关位图)的默认格式:
Windows 的 DIB 格式(如 BITMAPINFOHEADER)通常使用 BGR 顺序,因此 Bitmap 类直接沿用这一标准,避免额外的转换开销。
与 DirectX/OpenGL 的交互:
部分图形 API(如早期 DirectX)在处理纹理时也默认使用 BGR,Bitmap 的 BGR 格式可以减少数据转换步骤。
实验代码
生成一个bgr固定的图像
import cv2
import numpy as np
# 定义图片尺寸(例如 200x200 像素)
height, width = 200, 200
# 创建一个全黑的 BGR 图像(3通道)
bgr_img = np.zeros((height, width, 3), dtype=np.uint8)
# 填充为指定的 BGR 颜色(B=255, G=10, R=100)
bgr_img[:, :] = [255, 10, 100] # OpenCV 使用 BGR 顺序
# 保存图片
cv2.imwrite("bgr_255_10_100.png", bgr_img)
形成的测试图片 bgr_255_10_100
使用c#加载
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
public partial class Form1 : Form
{
public static void Bitmap2byte(Bitmap bitmap, byte[] img, int width, int height)
{
// Lock the bitmap's bits
BitmapData bmpData = bitmap.LockBits(
new Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb);
try
{
// 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) * height;
// Check if the provided byte array is large enough
if (img.Length < bytes)
{
throw new ArgumentException("Provided byte array is too small");
}
// Copy the RGB values into the byte array
System.Runtime.InteropServices.Marshal.Copy(ptr, img, 0, bytes);
}
finally
{
// Unlock the bits
bitmap.UnlockBits(bmpData);
}
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Test the function by loading an image from file
try
{
string imagePath = @"C:\YanHuaImage\bgr.png"; // Change this to your test image path
if (File.Exists(imagePath))
{
using (Bitmap bitmap = new Bitmap(imagePath))
{
int width = bitmap.Width;
int height = bitmap.Height;
// Calculate the required byte array size
int bytesPerPixel = 3; // For 24bpp RGB
int stride = width * bytesPerPixel;
stride += (4 - (stride % 4)) % 4; // Align to 4 bytes
int totalBytes = stride * height;
byte[] imageBytes = new byte[totalBytes];
Bitmap2byte(bitmap, imageBytes, width, height);
// Display some information
MessageBox.Show($"Image loaded successfully!\n" +
$"Width: {width}, Height: {height}\n" +
$"Total bytes: {totalBytes}\n" +
$"First pixel (BGR): {imageBytes[0]}, {imageBytes[1]}, {imageBytes[2]}");
}
}
else
{
MessageBox.Show("Test image not found at: " + imagePath);
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
}
}