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

字节数组转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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:16:20