在C#中从图像中获取RGB数组

我正在编写一个用Java编写的小程序的C#实现。

我在我的Java应用程序中使用了BufferedImage.getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)函数。 但我无法在C#中找到这个版本,我不确定如何手动编写。

.NET Framework中没有与此方法直接等效的东西。 但是,如果您的图像是System.Drawing.Bitmap,则可以调用LockBits方法,这将返回包含第一个扫描线地址的BitmapData结构。 然后,您可以使用它来创建应该与API兼容的包装器。 我假设您正在使用C#3.5或更高版本,因此我使用的是扩展方法 – 如果您使用的是旧版本,请通过从Bitmap参数中删除“this”将其更改为常规方法:

  public static void getRGB(this Bitmap image, int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) { const int PixelWidth = 3; const PixelFormat PixelFormat = PixelFormat.Format24bppRgb; // En garde! if (image == null) throw new ArgumentNullException("image"); if (rgbArray == null) throw new ArgumentNullException("rgbArray"); if (startX < 0 || startX + w > image.Width) throw new ArgumentOutOfRangeException("startX"); if (startY < 0 || startY + h > image.Height) throw new ArgumentOutOfRangeException("startY"); if (w < 0 || w > scansize || w > image.Width) throw new ArgumentOutOfRangeException("w"); if (h < 0 || (rgbArray.Length < offset + h * scansize) || h > image.Height) throw new ArgumentOutOfRangeException("h"); BitmapData data = image.LockBits(new Rectangle(startX, startY, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat); try { byte[] pixelData = new Byte[data.Stride]; for (int scanline = 0; scanline < data.Height; scanline++) { Marshal.Copy(data.Scan0 + (scanline * data.Stride), pixelData, 0, data.Stride); for (int pixeloffset = 0; pixeloffset < data.Width; pixeloffset++) { // PixelFormat.Format32bppRgb means the data is stored // in memory as BGR. We want RGB, so we must do some // bit-shuffling. rgbArray[offset + (scanline * scansize) + pixeloffset] = (pixelData[pixeloffset * PixelWidth + 2] << 16) + // R (pixelData[pixeloffset * PixelWidth + 1] << 8) + // G pixelData[pixeloffset * PixelWidth]; // B } } } finally { image.UnlockBits(data); } } 

现在可以像这样调用这个包装器:

  Bitmap foo = Bitmap.FromFile(@"somefile.jpg") as Bitmap; int[] rgbArray = new int[100]; foo.getRGB(1, 1, 10, 10, rgbArray, 0, 10); 

希望这会有所帮助,并欢迎使用.NET!

您可以使用Bitmap.LockBits直接访问位图中的像素。 这是一个示例实现,它从传递的位图返回一个扫描线作为int []:

  int[] getRGB(Bitmap bmp, int line) { var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); try { var ptr = (IntPtr)((long)data.Scan0 + data.Stride * (bmp.Height - line - 1)); var ret = new int[bmp.Width]; System.Runtime.InteropServices.Marshal.Copy(ptr, ret, 0, ret.Length * 4); return ret; } finally { bmp.UnlockBits(data); } } 

我认为最接近的是Bitmap.GetPixel(x,y) ,它在一个点上返回单个像素颜色。 为了模拟java函数,你需要编写一些帮助器。

您可能需要检查

  • Bitmap.GetPixel
  • Bitmap.LockBits

另外,请检查将像素数组转换为C#中的图像 。

这取决于你需要多快的速度。

Bitmap具有GetPixel()方法,可以很好地处理像素。

如果您需要进行快速图像处理,则需要使用LockBits ,您可以在此处找到样本。

 Bitmap img = (Bitmap) Image.FromFile(imageFileName); BitmapData data = img.LockBits(new Rectangle(0,0,img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat); byte* ptr = (byte*) data.Scan0; for (int j = 0; j < data.Height; j++) { byte* scanPtr = ptr + (j * data.Stride); for (int i = 0; i < data.width; i++, scanPtr+=NO_OF_CHANNELS) { for (int m = 0; m < NO_OF_CHANNELS; m++) Console.WriteLine(*scanPtr); // value of each channel } } img.UnlockBits(data);