[英]How to read pixel data only not meta data from 16 bit image in c#?
我有16位深度图像,我只想读取像素数据并将其存储到byte []
我试过以下代码:
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[]))
这里所有的数据来自图像,但我只需要像素数据?
任何人都可以帮忙吗?
如果您可以将图像加载为Bitmap,则很容易获得像素信息,如下所示。
Bitmap bitmap = new Bitmap("somefile.ext");
Color color = bitmap.GetPixel(x,y)
GetPixel()将返回Color(struct)类型,您可以将单个通道值作为字节获取,如下所示。
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};
从图像中获取图像数据的最快方法是使用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
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.