33

I was making a 2d map editor for my square tile platformer game, when I realized I could really use an image editor with its abilities to repaint adjacent pixels and many more, so I figured I should try and read a painted level by an app that will then convert it into a lightweight format.

I'm not sure if using a bitmap format is mandatory for such thing, but I guess, reading a specific pixel would be easier than with PNG for example.

So my goal is to open an image, iterate through every pixel, look for those which colors fit my tile scheme and put corresponding tile into the array of blocks.

Note: I already have my lightweigh format, so I need only reading pixels values into array.


Solution: My sketch looks like this:

var myBitmap = new Bitmap(@"input.png");  

for (int x = 0; x < myBitmap.Width; x++)
    for (int y = 0; y < myBitmap.Height; y++)
    {                    
        Color pixelColor = myBitmap.GetPixel(x, y);
        // things we do with pixelColor
    }

Example 2:

var myBitmap = new Bitmap(@"input.png");

for (int x = 0; x < myBitmap.Width; x++)
{
    for (int y = 0; y < myBitmap.Height; y++)
    {
        // Get the color of a pixel within myBitmap.
        Color pixelColor = myBitmap.GetPixel(x, y);
        string pixelColorStringValue =
            pixelColor.R.ToString("D3") + " " +
            pixelColor.G.ToString("D3") + " " +
            pixelColor.B.ToString("D3") + ", ";

        switch (pixelColorStringValue)
        {
            case "255 255 255":
                {
                    // white pixel
                    break;
                }
            case "000 000 000":
                {
                    // black pixel
                    break;
                }
        }
    }
}
Vinod Srivastav
  • 3,644
  • 1
  • 27
  • 40
user1306322
  • 8,561
  • 18
  • 61
  • 122
  • Side note: switch/case on strings has no value. Internally it's just string compares. Just comparing the actual RGB values is bound to be loads more efficient. – Nyerguds Sep 12 '17 at 11:41
  • @Nyerguds this was years ago so I don't remember why I did it that way. I'm sure there's a much better way to do everything in this question, and if I had to solve whatever problem I had back then today, the code would be totally different. – user1306322 Sep 13 '17 at 02:37
  • Hehe. That's the way it usually goes when looking back at old code, I guess :) – Nyerguds Sep 14 '17 at 07:34

3 Answers3

55

Well, if I understood correctly, you want to iterate through the pixels in the image, perform some kind of test, and if it passes you want to store that pixel in an array. Here´s how you could do that:

using System.Drawing;

Bitmap img = new Bitmap("*imagePath*");
for (int i = 0; i < img.Width; i++)
{
    for (int j = 0; j < img.Height; j++)
    {
        Color pixel = img.GetPixel(i,j);

        if (pixel == *somecondition*)
        {
            **Store pixel here in a array or list or whatever** 
        }
    }
} 

Don´t think you need anything else. If you need the specific RGB values you can get them from the corresponding methods in the pixel object.

Hele
  • 1,558
  • 4
  • 23
  • 39
Itzack
  • 831
  • 6
  • 3
  • Haha, this is exactly what I just came up with :) – user1306322 Apr 12 '12 at 17:02
  • 2
    For anyone wondering, to create an RGB byte array, you'd use something like: `int offset = y * bitmap.Width * 3 + x * 3; rgbBytes[offset + 0] = pixel.R; rgbBytes[offset + 1] = pixel.G; rgbBytes[offset + 2] = pixel.B;` Note how the coordinates `x` and `y` are a common source of confusion (x is the column and y is the row). Should be obvious how to adapt this to work for RGBA, BGR, etc. – Kat Jun 08 '15 at 23:06
3
 public Color[][] getBitmapColorMatrix(string filePath)
    {
        Bitmap bmp = new Bitmap(filePath);
        Color[][] matrix;
        int height = bmp.Height;
        int width = bmp.Width;
        if (height > width)
        {
            matrix = new Color[bmp.Width][];
            for (int i = 0; i <= bmp.Width - 1; i++)
            {
                matrix[i] = new Color[bmp.Height];
                for (int j = 0; j < bmp.Height - 1; j++)
                {
                    matrix[i][j] = bmp.GetPixel(i, j);
                }
            }
        }
        else
        {
            matrix = new Color[bmp.Height][];
            for (int i = 0; i <= bmp.Height - 1; i++)
            {
                matrix[i] = new Color[bmp.Width];
                for (int j = 0; j < bmp.Width - 1; j++)
                {
                    matrix[i][j] = bmp.GetPixel(i, j);
                }
            }
        }
        return matrix;
    }
Hossein
  • 31
  • 2
  • Can you explain how your answer is different from the other one? Also, why are you using a 2d array? Is it faster or slower than the other method? – user1306322 Jul 12 '18 at 18:10
  • Images can be so large and processing will do so long. This way let me split array to process image for something – Hossein Jul 17 '18 at 09:35
  • 3
    That's no different from a regular one-dimensional array which you can just as well address to get and set the pixels. I still don't see a significant difference between your answer and the other. – user1306322 Jul 17 '18 at 09:37
-3

I think I've done something similar once. Here's a code snippet of what I was doing:

public static void main(String[] args) {
        try {

            String path = "src/colors.jpg";
            BufferedImage image = ImageIO.read(new File(path));
            int w = image.getWidth();
            int h = image.getHeight();
            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    Color c = new Color(image.getRGB(x, y));
                    int red = c.getRed();
                    int green = c.getGreen();
                    int blue = c.getBlue();
                    countColor(red, green, blue);
                    totalCount++;
                }
            }

            printColors();

        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

In the inner for loop you can put something into an array[i][j]. (If that is what you're looking for)

Matthias
  • 12,704
  • 13
  • 35
  • 56
  • I don't think this is something you can do in C# without the use of external libraries, am I right? – user1306322 Apr 12 '12 at 16:47
  • I don't have the original code from that project lying around anymore I'm afraid, so I couldn't tell that from the top of my head. – Matthias Apr 12 '12 at 16:52
  • 21
    You can't do this in C# because the code is a Java example :) – Patrick Apr 15 '12 at 12:12
  • I know this is an old thread, but where are you getting the idea this is a Java example? C# and Java have substantial similarities but this is very much a C# example. As far as the original poster and the examples it's bad image processing practice to use the column as the outer loop. (x then y). For optimal speed use y then x. Reduces the number of background multiplies. – Richard Robertson Dec 01 '15 at 08:53
  • 5
    @RichardRobertson, it's a Java example because of the `BufferedImage image = ImageIO.read(filePath);` and later they use `= new Color( image.getRGB(x, y) );`. I dont remember seeing a **BufferedImage** data type or a **getRGB(x, y)** in C#... Just trust this is Java. – VC.One Feb 04 '16 at 21:33
  • @VC.One Doh! I was paying attention to the OP's "C#" tag and not the specifics of the example. The creator of C# actually used Java concepts in developing the language so similarities abound. Thanks for pointing out the differences. – Richard Robertson Feb 21 '16 at 06:58