在BMP中浏览像素

Sud*_*ha 26 .net c# image-processing

在此输入图像描述

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

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

has*_*shi 49

当您想在巨大的图像上进行图像处理时,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]);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你可能想添加`bmp.UnlockBits(bmpData); `完成复制后. (4认同)
  • 我使用了类似的解决方案,效果很好。你只需要确保你的源 bmp 是相同的像素格式!您还反转了行和列循环(只是名称,因为实现仍然有效) (2认同)

kin*_*nak 8

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

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);
}
Run Code Online (Sandbox Code Playgroud)

  • if(row%2!= 0)c = bmp.Width-col-1; 应该是if(row%2!= 0)col = bmp.Width-col-1; (2认同)
  • GetPixel非常昂贵且速度慢.根据答案使用BitmapData要好得多. (2认同)

tho*_*att 7

你需要使用两个循环:

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


And*_*ini 6

您冷使用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);
Run Code Online (Sandbox Code Playgroud)

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

foreach(var color in pixelColors)
{
    //do stuff on RGB values, etc...
}
Run Code Online (Sandbox Code Playgroud)


Ry-*_*Ry- 5

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

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
}
Run Code Online (Sandbox Code Playgroud)

您可以这样称呼它:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以在任何方向上快速遍历返回的数组。