File.ReadAllBytes 未正确读取 PNG 图像像素

File.ReadAllBytes doesn't read the PNG image pixels properly

我正在尝试使用 File.ReadAllBytes(string) 方法读取 .png 图像的字节但没有成功。

我的图像大小为 2464x2056x3(15.197.952 字节),但是这种方法 returns 一个大约 12.000.000 字节的数组。

我尝试使用相同大小的白色图像,得到一个 25.549 的字节数组,检查字节数组我可以看到所有类型的值,这显然是不正确的,因为是白色图像。

我使用的代码是:

var frame = File.ReadAllBytes("C:\workspace\white.png");

我还尝试先将图像作为 Image 对象打开,然后使用以下内容获取字节数组:

using (var ms = new MemoryStream())
{
  var imageIn = Image.FromFile("C:\workspace\white.png");
  imageIn.Save(ms, imageIn.RawFormat);
  var array = ms.ToArray();
}

但是结果和之前一样...

知道发生了什么吗?

如何读取字节数组?

PNG 是一种压缩格式。
查看有关它的一些信息:Portable Network Graphics - Wikipedia.

这意味着二进制表示不是您期望的实际像素值。

您需要某种 PNG 解码器来从压缩数据中获取像素值。

此 post 可能会引导您朝着正确的方向前进:Reading a PNG image file in .Net 2.0。请注意,它很旧,也许有更新的方法可以做到这一点。

附带说明:即使像 BMP 这样的非压缩格式也有 header,因此您不能简单地读取二进制文件并以简单的方式获取像素值。


更新: 下面演示了从 PNG 文件获取像素值的一种方法:

using System.Drawing.Imaging;

byte[] GetPngPixels(string filename)
{
    byte[] rgbValues = null;

    // Load the png and convert to Bitmap. This will use a .NET PNG decoder:
    using (var imageIn = Image.FromFile(filename))
    using (var bmp = new Bitmap(imageIn))
    {
        // Lock the pixel data to gain low level access:
        BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);

        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;

        // Declare an array to hold the bytes of the bitmap.
        int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
        rgbValues = new byte[bytes];

        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

        // Unlock the pixel data:
        bmp.UnlockBits(bmpData);
    }

    // Here rgbValues is an array of the pixel values.
    return rgbValues;
}

此方法将 return 一个具有您期望大小的字节数组。
为了使用 opencv(或任何类似用法)的数据,我建议您增强我的代码示例和 return 图像元数据(宽度、高度、跨度、 pixel-format)。您将需要此元数据来构建 cv::Mat.