You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C# Standard中将16位RGB565格式BMP文件加载为字节数组

可实现需求的两种方案如下:

方案1:手动解析BMP文件(无第三方依赖,全版本.NET Standard兼容)

BMP文件格式为公开固定结构,直接读取二进制流即可提取原始RGB565像素数据,不会发生自动格式转换,示例代码如下:

// 自定义Icon结构和你原有代码对齐
public class Icon
{
    public ushort Width { get; set; }
    public ushort Height { get; set; }
    public byte[] Data { get; set; }
}

private static Icon? LoadRgb565Bmp(string filepath)
{
    using var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
    using var br = new BinaryReader(fs);
    
    // 读取BMP文件头
    var bfType = br.ReadUInt16();
    if (bfType != 0x4D42) // 校验BMP文件标识"BM"
        return null;
    
    br.ReadUInt32(); // 跳过文件大小
    br.ReadUInt32(); // 跳过保留字段
    var bfOffBits = br.ReadUInt32(); // 像素数据的起始偏移量
    
    // 读取BMP信息头
    var biSize = br.ReadUInt32();
    var biWidth = br.ReadInt32();
    var biHeight = br.ReadInt32();
    br.ReadUInt16(); // 跳过平面数
    var biBitCount = br.ReadUInt16();
    var biCompression = br.ReadUInt32();
    
    // 校验是否为16位BMP
    if (biBitCount != 16)
    {
        Debug.Print($"Image at path `{filepath}` is not 16bit!");
        return null;
    }
    
    // 校验是否为RGB565格式(16位BMP有555和565两种,通过压缩标志和位掩码判断)
    bool isRgb565 = false;
    if (biCompression == 3) // BI_BITFIELDS 标志
    {
        var redMask = br.ReadUInt32();
        var greenMask = br.ReadUInt32();
        var blueMask = br.ReadUInt32();
        if (redMask == 0xF800 && greenMask == 0x07E0 && blueMask == 0x001F)
            isRgb565 = true;
    }
    
    if (!isRgb565)
    {
        Debug.Print($"Image at path `{filepath}` is not RGB565!");
        return null;
    }
    
    // 计算每行像素的字节数,BMP要求每行按4字节对齐
    int rowStride = (biWidth * 2 + 3) / 4 * 4;
    // 读取所有像素数据
    byte[] rawData = new byte[rowStride * Math.Abs(biHeight)];
    fs.Seek(bfOffBits, SeekOrigin.Begin);
    fs.Read(rawData, 0, rawData.Length);
    
    // 整理成正序的RGB565字节数组(BMP默认行存储顺序是从下到上)
    byte[] result = new byte[biWidth * Math.Abs(biHeight) * 2];
    int targetIndex = 0;
    int startRow = biHeight > 0 ? biHeight - 1 : 0;
    int rowIncrement = biHeight > 0 ? -1 : 1;
    
    for (int y = startRow; y >= 0 && y < Math.Abs(biHeight); y += rowIncrement)
    {
        Buffer.BlockCopy(rawData, y * rowStride, result, targetIndex, biWidth * 2);
        targetIndex += biWidth * 2;
    }
    
    return new Icon
    {
        Width = (ushort)biWidth,
        Height = (ushort)Math.Abs(biHeight),
        Data = result
    };
}

方案2:使用跨平台图像库ImageSharp

如果你不想自己处理文件解析,可以使用兼容.NET Standard的第三方图像库SixLabors.ImageSharp,它支持保留原始像素格式读取,不会强制转换为RGB888,使用步骤如下:

  • 安装NuGet包:SixLabors.ImageSharp
  • 读取代码示例:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;

private static Icon? LoadRgb565Bmp(string filepath)
{
    try
    {
        using var image = Image.Load<Rgb565>(filepath);
        byte[] data = new byte[image.Width * image.Height * 2];
        image.CopyPixelDataTo(data);
        return new Icon
        {
            Width = (ushort)image.Width,
            Height = (ushort)image.Height,
            Data = data
        };
    }
    catch (InvalidOperationException)
    {
        Debug.Print($"Image at path `{filepath}` is not RGB565!");
        return null;
    }
}

内容的提问来源于stack exchange,提问作者Dan Forever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 06:15:08