在BMP中浏览像素

在此处输入图像描述

嗨我有一个bmp加载到BMP对象,我需要通过像素作为上面的图像从(1,1)像素到(100,100) px。 使用getpixel()方法。 我使用的是一个循环,但没有成功。

如果我使用多维数组的概念应该是什么变量值?

当您想要在巨大的图像上进行图像处理时,GetPixel()方法需要很长时间,但我认为我的算法比其他答案花费的时间更少,例如您可以在800 * 600像素图像上测试此代码。


 Bitmap bmp = new Bitmap("SomeImage"); // Lock the bitmap's bits. Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // Get the address of the first line. IntPtr ptr = bmpData.Scan0; // Declare an array to hold the bytes of the bitmap. int bytes = bmpData.Stride * bmp.Height; byte[] rgbValues = new byte[bytes]; byte[] r = new byte[bytes / 3]; byte[] g = new byte[bytes / 3]; byte[] b = new byte[bytes / 3]; // Copy the RGB values into the array. Marshal.Copy(ptr, rgbValues, 0, bytes); int count = 0; int stride = bmpData.Stride; for (int column = 0; column < bmpData.Height; column++) { for (int row = 0; row < bmpData.Width; row++) { b[count] = (byte)(rgbValues[(column * stride) + (row * 3)]); g[count] = (byte)(rgbValues[(column * stride) + (row * 3) + 1]); r[count++] = (byte)(rgbValues[(column * stride) + (row * 3) + 2]); } } 

如果你想在一个循环中右移,左移,右移……它会这样做:

 for (int i = 0 ; i < bmp.Height * bmp.Width; ++i) { int row = i / bmp.Height; int col = i % bmp.Width; if (row%2 != 0) col = bmp.Width - col-1; var pixel = bmp.GetPixel(col, row); } 

你需要使用两个循环:

 for (int ii = 0; ii < 100; ii++) { for (int jj = 0; jj < 100; jj++) { Color pixelColor = bitmap.GetPixel(ii, jj); // do stuff with pixelColor } } 

你冷使用Linq选择来获取IEnumerable对象:

 var pixelColors = from x in Enumerable.Range(0, bmp.Width - 1) from y in Enumerable.Range(0, bmp.Height - 1) select bmp.GetPixel(x, y); 

…然后迭代IEnumerable(使用隐式类型):

 foreach(var color in pixelColors) { //do stuff on RGB values, etc... } 

虽然两个嵌套循环方法通常“更好”或更具可读性,但您可以在1循环中执行此操作:

 for(int i = 0; i < bmp.Height * bmp.Width; i++) { int row = i / bmp.Width; int col = i % bmp.Width; var pixel = bmp.GetPixel(col, row); } 

或稍好一点,将第一行更改为:

 var numberOfPixels = bmp.Height * bmp.Width; for(int i = 0; i < numberOfPixels; i++) 

你可以尝试这样的事情

 for(int y = 0; y < bmp.Height; y++) { var even = y % 2 == 0; var startX = even ? 0 : bmp.Width - 1; var endX = even ? bmp.Width : -1; var delta = even ? 1 : -1; for(int x = startX; x != endX; x += delta) { var pixel = bmp.GetPixel(x,y); } } 

或者您可以将内部循环拆分为:从左到右和从右到左

 for(int y = 0; y < bmp.Height; y += 2) { for(int x = 0; x < bmp.Width; x++) { var pixel = bmp.GetPixel(x,y); } var line = y + 1; if(line < bmp.Height) { for(int x = bmp.Width; x >= 0; --x) { var pixel = bmp.GetPixel(x,line); } } } 

您可以将其转换为易于访问的多维颜色数组,如下所示:

 using System.Drawing.Imaging; using System.Runtime.InteropServices; // ... Color[,] GetSection(Image img, Rectangle r) { Color[,] r = new Color[r.Width, r.Height]; // Create an array of colors to return using (Bitmap b = new Bitmap(img)) { // Turn the Image into a Bitmap BitmapData bd = b.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format32BppArgb); // Lock the bitmap data int[] arr = new int[b.Width * b.Height - 1]; // Create an array to hold the bitmap's data Marshal.Copy(b.Scan0, arr, 0, arr.Length); // Copy over the data b.UnlockBits(bd); // Unlock the bitmap for (int i = 0; i < arr.Length; i++) { r[i % r.Width, i / r.Width] = Color.FromArgb(arr[i]); // Copy over into a Color structure } } return r; // Return the result } 

你会这样称呼它:

 Color[,] c = GetSection(myImage, new Rectangle(0, 0, 100, 100)); // Get the upper-left 100x100 pixel block in the image myImage for (int x = 0; x < c.GetUpperBound(0); x++) { for (int y = 0; y < c.GetUpperBound(1); y++) { Color thePixel = c[x, y]; // do something with the color } } 

你可以在你想要的任何方向上快速遍历返回的arrays。