字节数组转Bitmap选什么像素格式?C#图像显示异常排查
问题分析与解决方案
你的核心问题是Bitmap的像素格式与字节数组的存储格式完全不匹配,导致内存写入不完整,出现全黑+随机彩点的异常。
为什么之前的代码会出错?
你创建的是PixelFormat.Format24bppRgb格式的位图:
- 这种格式下,每个像素需要3字节(红、绿、蓝各1字节)。
- 48×32的位图总共需要
48 * 32 * 3 = 4608字节的像素数据,但你的字节数组只有192字节,连1/24都不到!
当你用Marshal.Copy把192字节写入位图内存时,只填充了顶部极小一部分区域,剩下的内存都是未初始化的垃圾数据(多数是0,对应黑色),而顶部的彩点是因为原始字节被错误地解析成24位像素值,导致颜色错乱。
字节数组的真实格式
你的192字节正好对应 48×32 = 1536 个像素,1536位 = 192字节,说明这是1位单色位图(1bpp):每个像素用1bit表示(0=黑,1=白,反之亦然),每8个像素占1字节。
不过这里要注意:Windows位图的扫描线要求按4字节对齐,48像素=6字节/行,6不是4的倍数,所以实际每行需要填充到8字节,这也是需要处理的细节。
正确的实现代码
using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; public Bitmap ConvertBlobToBitmap(byte[] blob) { int width = 48; int height = 32; int bitsPerPixel = 1; // 计算Windows位图要求的对齐后扫描线长度(必须是4字节的倍数) int stride = ((width * bitsPerPixel + 31) / 32) * 4; // 此处计算结果为8字节/行 // 创建对齐后的像素数据数组 byte[] alignedData = new byte[stride * height]; for (int y = 0; y < height; y++) { // 把原始的6字节/行数据复制到对齐行的前6字节 Array.Copy(blob, y * 6, alignedData, y * stride, 6); // 剩余2字节自动填充0,满足对齐要求 } // 创建1位索引格式的Bitmap Bitmap bmp = new Bitmap( width, height, stride, PixelFormat.Format1bppIndexed, Marshal.UnsafeAddrOfPinnedArrayElement(alignedData, 0) ); // 设置调色板(1bpp默认调色板可能不符合预期,手动指定黑白) ColorPalette palette = bmp.Palette; palette.Entries[0] = Color.Black; // 0bit对应黑色 palette.Entries[1] = Color.White; // 1bit对应白色(可根据你的需求反转) bmp.Palette = palette; return bmp; }
额外注意点
- 如果你的字节数组中
1对应的是黑色、0对应的是白色,只需要调换调色板中Entries[0]和Entries[1]的颜色即可。 - 1bpp位图中,每个字节的bit顺序是从最高位到最低位对应从左到右的像素,比如字节
0x01(二进制00000001)表示最右侧1个像素为白,其余7个为黑,如果你的原始数据是相反顺序,需要反转每个字节的bit位。
内容的提问来源于stack exchange,提问作者sean green
相关产品推荐
相关产品推荐

