如何在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
相关产品推荐
相关产品推荐

