Travel through pixels in BMP

后端 未结 7 1063
梦谈多话
梦谈多话 2020-11-30 02:32

\"enter

Hi i have a bmp loaded to a BMP object and im requir

相关标签:
7条回答
  • 2020-11-30 02:52

    You can turn it into an easy-to-access multidimensional array of colors like so:

    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(bd.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
    }
    

    You would call it like so:

    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
        }
    }
    

    And you could traverse the returned array quite quickly in any direction you want at all.

    0 讨论(0)
  • 2020-11-30 02:54

    You need to use two loops:

    for (int ii = 0; ii < 100; ii++)
    {
      for (int jj = 0; jj < 100; jj++)
      {
        Color pixelColor = bitmap.GetPixel(ii, jj);
        // do stuff with pixelColor
      }
    }
    
    0 讨论(0)
  • 2020-11-30 02:58

    You can try something like this

    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);
       }
    }
    

    or you can split internal cycle to: left to right and right to left

    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);
             }
           }
        }
    
    0 讨论(0)
  • 2020-11-30 03:09

    You cold use a Linq selection to obtain a IEnumerable object:

    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);
    

    ...then iterate on the IEnumerable (using implicit typing):

    foreach(var color in pixelColors)
    {
        //do stuff on RGB values, etc...
    }
    
    0 讨论(0)
  • 2020-11-30 03:09

    Though the two nested loop approach is typically "better" or more readable, you can do it in 1 loop like this:

    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);
    }
    

    Or slightly better, change the first line to:

    var numberOfPixels = bmp.Height * bmp.Width;
    for(int i = 0; i < numberOfPixels; i++)
    
    0 讨论(0)
  • 2020-11-30 03:11

    When you want to doing image processing on huge images GetPixel() method takes long time but I think my algorithm takes less time than other answers , for example you can test this code on 800 * 600 pixels image.


    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]);
        }
    }
    
    0 讨论(0)
提交回复
热议问题