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
.
我正在尝试使用 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
.