繁体   English   中英

如何只读取像素数据而不是c#中16位图像的元数据?

[英]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};

从图像中获取图像数据的最快方法是使用LockBitsMarshal.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM