简体   繁体   English

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

[英]How to read pixel data only not meta data from 16 bit image in c#?

I have 16 bit depth image from that I want to read only pixel data and store it to byte[] 我有16位深度图像,我只想读取像素数据并将其存储到byte []

I tried following code : 我试过以下代码:

FileInfo fileInfo = new FileInfo("C:\\Image stitch API\\Temp\\output.tif");
byte[] data = new byte[fileInfo.Length];

I also tried the following : 我也尝试过以下方法:

Image img;
img = Image.FromFile("C:\\Image stitch API\\Temp\\output.tif");
ImageConverter ic = new ImageConverter();
byte[] data = (byte[])ic.ConvertTo(img, typeof(byte[]))

Here all data it is coming from image, but I need only pixel data? 这里所有的数据来自图像,但我只需要像素数据?

Can any one help on this? 任何人都可以帮忙吗?

If you can load your image as Bitmap, it is pretty easy to get pixel info as shown below. 如果您可以将图像加载为Bitmap,则很容易获得像素信息,如下所示。

    Bitmap bitmap = new Bitmap("somefile.ext");
    Color color = bitmap.GetPixel(x,y) 

GetPixel() will return Color (struct) type and you can get individual channel values as byte like shown below. GetPixel()将返回Color(struct)类型,您可以将单个通道值作为字节获取,如下所示。

    byte g = slateBlue.G;
    byte b = slateBlue.B;
    byte r = slateBlue.R;
    byte a = slateBlue.A;

Regarding your comment, I will suggest you to use use Netvips to manipulate image in byte array form (it is way betterand faster than system.drawing). 关于你的评论,我建议你使用Netvips来操作字节数组形式的图像(它比system.drawing更快)。 By doing so, you could get image bands as byte arrays as below. 通过这样做,您可以将图像波段作为字节数组,如下所示。

    var imageBands = inputImage.Bandsplit();
    var R = imageBands [0];
    var B = imageBands [1];
    var G = imageBands [2];

If you dont wanna switch the libraries, you could get byte array with System.Drawing like shown below. 如果您不想切换库,可以使用System.Drawing获取字节数组,如下所示。

byte[] image = new[] {R, B, G};

The fastest way to get image data out of an image is to use LockBits and Marshal.Copy . 从图像中获取图像数据的最快方法是使用LockBitsMarshal.Copy

I strongly advice against using GetPixel . 强烈反对使用GetPixel See, LockBits works by reserving memory for putting the bytes of the image and copying the bytes of the image in there. 请参阅, LockBits通过保留内存来放置图像的字节并在那里复制图像的字节。 UnlockBits will then clean up that reserved memory. 然后, UnlockBits将清理该保留的内存。

Now, the problem is, GetPixel performs this same locking and unlocking operation for every single pixel you access . 现在,问题是, GetPixel您访问的每个像素执行相同的锁定和解锁操作。 Using LockBits once is fairly fast, but using it over and over for tens of thousands of pixels really slows things down. 使用LockBits曾经是相当快的,但使用它一遍又一遍的像素数以万计真的会减慢速度。

Note that there are two ways of using LockBits ; 请注意,有两种方法可以使用LockBits ; either you get the data in the original pixel format, using sourceImage.PixelFormat , or you make LockBits convert the data to the format you require, by giving a different one. 要么使用sourceImage.PixelFormat获取原始像素格式的数据,要么让LockBits 数据转换为您需要的格式,方法是给出不同的格式。 In this code, I force the output to the pixel format Format32bppArgb . 在此代码中,我强制输出为像素格式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 can normally differ from width * bpp since lines of bitmaps are always aligned to multiples of 4 bytes, so normally you need to return that as well and keep track of it, but since this is a 32-bit format, its data is always aligned to 4 bytes, so there is never an actual difference here. Stride通常可以与width * bpp不同,因为位图行总是与4个字节的倍数对齐,所以通常你需要返回它并跟踪它,但由于这是一个32位格式,它的数据总是对齐到4个字节,所以这里从来没有实际的区别。

Note, your question never specifies the order in which you need the data. 请注意,您的问题从不指定您需要数据的顺序 Typical ARGB data is actually in the byte order B, G, R, A, because normal integer saving on IBM PC architecture is little-endian, meaning that the actual bytes of an Int32 value "FFEEDDCC" are reversed in memory to [CC DD EE FF]. 典型的ARGB数据实际上是字节顺序B,G,R,A,因为IBM PC体系结构上的正常整数保存是小端的,这意味着Int32值“FFEEDDCC”的实际字节在内存中被反转为[CC DD EE FF]。 But your comment on the other answer given here seemed to indicate you went for byte order [RR, GG, BB, AA], or, 'ABGR', which is honestly not a format I've ever seen before. 但你对这里给出的另一个答案的评论似乎表明你选择了字节顺序[RR,GG,BB,AA],或'ABGR',这实际上不是我以前见过的格式。 But if you do need to change that, it's just a simple extra loop to exchange red and blue: 但是如果你确实需要改变它,它只是一个简单的额外循环来交换红色和蓝色:

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