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

