我有16位深度的图像,我想只读取像素数据并将其存储到字节[]
我尝试了以下代码:
FileInfo fileInfo = new FileInfo("C:\\Image stitch API\\Temp\\output.tif");
byte[] data = new byte[fileInfo.Length];
我还尝试了以下方法:
Image img;
img = Image.FromFile("C:\\Image stitch API\\Temp\\output.tif");
ImageConverter ic = new ImageConverter();
byte[] data = (byte[])ic.ConvertTo(img, typeof(byte[]))
这里所有数据都来自图像,但是我只需要像素数据?
有人可以帮忙吗?
答案 0 :(得分:1)
如果您可以将图像加载为位图,则很容易获得如下所示的像素信息。
Bitmap bitmap = new Bitmap("somefile.ext");
Color color = bitmap.GetPixel(x,y)
GetPixel()将返回Color(结构)类型,您可以按如下所示获取单个通道值作为字节。
byte g = slateBlue.G;
byte b = slateBlue.B;
byte r = slateBlue.R;
byte a = slateBlue.A;
关于您的评论,我建议您使用Netvips来以字节数组形式处理图像(这比system.drawing更好更快。)这样,您就可以将图像带作为字节数组如下所示。
var imageBands = inputImage.Bandsplit();
var R = imageBands [0];
var B = imageBands [1];
var G = imageBands [2];
如果您不想切换库,则可以使用System.Drawing获得字节数组,如下所示。
byte[] image = new[] {R, B, G};
答案 1 :(得分:0)
从图像中获取图像数据的最快方法是使用LockBits
和Marshal.Copy
。
我强烈建议不要使用GetPixel
。 LockBits
的工作方式是保留内存,用于放置图像的字节并在其中复制图像的字节。 UnlockBits
然后将清理该保留的内存。
现在,问题是,GetPixel
对您访问的每个单个像素执行相同的锁定和解锁操作。一次使用LockBits相当快,但是一遍又一遍地使用它成千上万像素真的会使事情变慢。
请注意,有两种使用LockBits
的方法;您可以使用sourceImage.PixelFormat
获得原始像素格式的数据,也可以通过提供不同的格式使LockBits将数据转换到所需的格式。在这段代码中,我将输出强制为像素格式Format32bppArgb
。
/// <summary>
/// Gets the raw bytes from an image.
/// </summary>
/// <param name="sourceImage">The image to get the bytes from.</param>
/// <returns>The raw bytes of the image</returns>
public static Byte[] GetImageDataAs32bppArgb(Bitmap sourceImage)
{
BitmapData sourceData = sourceImage.LockBits(
new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Byte[] data = new Byte[sourceData.Stride * sourceImage.Height];
Marshal.Copy(sourceData.Scan0, data, 0, data.Length);
sourceImage.UnlockBits(sourceData);
return data;
}
Stride
通常可以与width * bpp
不同,因为位图的行始终与4个字节的倍数对齐,因此通常您也需要返回该位并对其进行跟踪,但是由于这是一个32位格式,其数据总是对齐到4个字节,因此这里没有任何实际差异。
注意,您的问题永远不会指定需要数据的顺序。典型的ARGB数据实际上是按字节顺序B,G,R,A,因为在IBM PC架构上普通的整数存储是低位字节序的,这意味着Int32值“ FFEEDDCC”的实际字节在内存中被反转为[CC DD EE FF]。但是您对此处给出的其他答案的评论似乎表明您使用了字节顺序[RR,GG,BB,AA]或'ABGR',这实际上不是我曾经使用过的格式见过。但是,如果您确实需要更改它,那只是交换红色和蓝色的简单额外循环:
for (Int32 i = 0; i < data.Length; i += 4)
{
Byte b = data[i]; // save Blue
data[i] = data[i + 2]; // set first component to the Red value
data[i + 2] = b; // set third component to the Blue value
}