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

C#中将Bitmap转换为字节数组结果不符合预期的问题

问题分析与解决方案

问题根源

你当前代码里convertedBrightnessVals = memory.ToArray()获取的是TIFF格式文件的完整字节流,包含文件头、压缩信息、元数据等内容,并非图像的原始像素数据,所以长度和像素宽高的乘积(甚至16bpp对应的2倍乘积)不匹配。

16bpp灰度图像每个像素占2字节,理论原始像素数据长度应为 816×624×2 = 1018368 字节,你得到的466422字节是压缩后的TIFF文件大小(TIFF默认可能采用LZW或其他压缩算法)。

另外,图像的DPI(每英寸点数)仅控制打印/显示时的物理尺寸,和像素数据的长度无关,不需要修改。

正确获取原始像素字节数组的代码

使用Bitmap.LockBits方法直接锁定图像内存,读取原始像素缓冲区的字节数据:

private byte[] GetRawPixelData(Bitmap bitmap)
{
    // 校验图像格式是否为16bpp灰度
    if (bitmap.PixelFormat != PixelFormat.Format16bppGrayScale)
        throw new ArgumentException("仅支持16bpp灰度图像");

    // 锁定整个图像的像素区域
    Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

    // 计算像素数据总长度(Stride为每行对齐后的字节数)
    int byteCount = bmpData.Stride * bitmap.Height;
    byte[] pixelData = new byte[byteCount];

    // 将内存中的像素数据复制到字节数组
    Marshal.Copy(bmpData.Scan0, pixelData, 0, byteCount);

    // 解锁图像内存
    bitmap.UnlockBits(bmpData);

    return pixelData;
}

使用示例

在你的btnOpen_Click方法中,加载Bitmap后直接调用该方法获取原始像素数据:

if (openfile.ShowDialog() == true)
{
    using (Stream stream = new FileStream(openfile.FileName, FileMode.Open, FileAccess.Read))
    {
        _photo = new Bitmap(stream);
        imgSrc.Width = _photo.Width;
        imgSrc.Height = _photo.Height;
        imgSrc.Source = BitmapToImageSource(_photo);
        
        // 获取原始像素字节数组
        convertedBrightnessVals = GetRawPixelData(_photo);
    }
}

注意事项

  • Stride是图像每行的字节数,由于内存对齐要求,可能会比宽度×每个像素字节数稍大,必须用Stride×高度计算总长度。
  • 16bpp灰度图像的像素采用小端存储(低字节在前,高字节在后),处理单个像素值时需要注意字节顺序。

内容的提问来源于stack exchange,提问作者Denis Hu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:25:54