2

我正在使用 c sharp,.net 4(客户端配置文件,如果这很重要)并且我有一个byte包含图像原始数据的数组。具体来说,这张图片:

好形象

它是 SANE 测试后端的输出,格式在SANE 网站上有完整描述。顺便说一句,我已经传入了参数:

  • 深度:8
  • 模式:彩色

它已经返回:

  • 格式:RGB
  • 深度:8
  • 行数:196
  • 每行像素:157
  • 每行字节数:471
  • 一个 92316 字节长的字节流

因此,这些数字似乎是合理的 (196 * (157 * 471) = 92316) - 每个像素三个字节(24 位)。

通过阅读 SANE 文档,数据从左上角从左到右,从上到下按每个像素三个字节进行排序 - 就像这样(他们有更好的图片,对不起这种 ASCIItastic 方法):

red,green,blue   red,green,blue  
--------------   --------------
    byte 1           byte 2       ...

因为我对图像非常了解,所以我认为将它加载到位中会非常简单,我敲了这个:

var bmp = new Bitmap(157, 196, PixelFormat.Format24bppRgb);
BitmapData bmpData = bmp
    .LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
              ImageLockMode.ReadWrite,
              bmp.PixelFormat);
Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
bmp.UnlockBits(bmpData);

但它产生了这个:

坏形象

关闭,但没有雪茄,可以这么说。

那么,我做错了什么?

4

2 回答 2

4

问题是在位图中,一行的字节和下一行的字节之间存在间隙(更多here )。如果速度不是您的主要关注点,您可以使用SetPixel和循环更轻松地做到这一点。

编辑:
与 SetPixel 相比,这将显着提高速度,但恐怕您仍然必须使用循环;)

for(int i = 0; i < bmp.Height; i++) {
    Marshal.Copy(data, 
        i * bmp.Height,
        bmpData.Scan0 + i * bmpData.Stride,
        bmp.Width * 3);
}

请注意,我没有测试过代码,但它应该足以给你这个想法。

于 2013-03-06T18:23:02.670 回答
3

位图需要将行填充到某个特定大小(4 字节,搜索格式详细信息,即此处)。

结果,每行 157 个像素并不完全映射为位图位的二进制格式,您会看到下一行移动了一点。我认为您需要为每行分配 158*3 字节,并将每一行从源(由于缺少填充而不是位图)格式复制到目标,用 0 填充每行的最后 3 个字节。

于 2013-03-06T18:24:27.420 回答