0

I am wondering why would this piece of code NOT generate a checkerboard pattern?

pbImage.Image = new Bitmap(8, 8);
        Bitmap bmp = ((Bitmap)pbImage.Image);
        byte[] bArr = new byte[64];
        int currentX = 0;
        int currentY = 0;
        Color color = Color.Black;
        do
        {
            currentY = 0;
            do
            {
                bmp.SetPixel(currentX, currentY, color);
                if (color == Color.Black) color = Color.White; else color = Color.Black;
                currentY++;
            } while (currentY < bitmapHeight);
            currentX++;
        } while (currentX < bitmapWidth);

        pbImage.Refresh();

Edit: I realized that i need to expand Bitmaps ctor with
new Bitmap(bitmapWidth, bitmapHeight, PixelFormat.Format8bppIndexed) and it seems SetPixel does not support Indexed Images and expects a Color.

My point is i want to create raw(pure byte array) grayscale images and show it on a picture box, while keeping it as simple as possible, without using any external libraries.

  • 1
    At no point do you actually assign a color to anything. You do a lot of itteration, but nothing with it. BTB, this looks like you should be using nested for loops rather then do whiles. – Christopher Apr 24 '18 at 22:08
  • there is a color variable and it doesn't matter do or for, loops are loops. – user2257918 Apr 24 '18 at 22:20
  • `SetPixel()` is very expensive and slow. You should use `LockBits` and manipulate the pixel data directly. – Dai Apr 24 '18 at 22:33
  • What pattern is it making if any? – Michael Puckett II Apr 24 '18 at 22:36
  • @user2257918 not all loops are alike, `for` loops are exactly what you need when doing x number of iterations. Also, your formatting is _horrible_ why is your `if/else` statement all in one line? It makes it really hard to read and even harder to debug – maccettura Apr 24 '18 at 22:37
  • Possible duplicate of [How to create bitmap from byte array?](https://stackoverflow.com/questions/21555394/how-to-create-bitmap-from-byte-array) – maccettura Apr 24 '18 at 22:44
  • it is creating a pattern like 1 horizontal black line and below that 1 white line and repeating.Thanks for the lockbits hint. – user2257918 Apr 24 '18 at 22:58
  • @user2257918 try changing the maths that you do to figure out its its a white or black square. Maybe this will work if (currentX % 2 == 0 && currentY % 2 == 0) { image.SetPixel(i,j,Color.Black); } else { image.SetPixel(i,j,Color.White); } – Hewiiitt Apr 24 '18 at 23:29

1 Answers1

0

Your calculation fails, because, if you switch at every pixel, then even lines that start with colour 0 will end on the colour 1, meaning the next line will once again start with colour 0.

0101010101010101
0101010101010101
0101010101010101
0101010101010101
etc...

But since, in X and Y coordinates, any horizontal and vertical movement by 1 pixel across the pattern will change the colour, the actual calculation of whether you want a filled or non-filled pixel can be simplified to (x + y) % 2 == 0.

The checkerboard generating function I put below takes an array of colours as colour palette, and allows you to specify which specific indices from that palette to use as the two colours to use on the pattern. If you just want an image with nothing but a 2-colour palette containing black and white, you can just call it like this:

Bitmap check = GenerateCheckerboardImage(8, 8, new Color[]{Color.Black, Color.White}, 0,1);

The generating function:

public static Bitmap GenerateCheckerboardImage(Int32 width, Int32 height, Color[] colors, Byte color1, Byte color2)
{
    Byte[] patternArray = new Byte[width * height];
    for (Int32 y = 0; y < height; y++)
    {
        for (Int32 x = 0; x < width; x++)
        {
            Int32 offset = x + y * height;
            patternArray[offset] = (((x + y) % 2 == 0) ? color1 : color2);
        }
    }
    return BuildImage(patternArray, width, height, width, PixelFormat.Format8bppIndexed, colors, Color.Black);
}

The BuildImage function I used is a general-purpose function I made to convert a byte array to an image. You can find it in this answer.

As explained in the rest of that question and the answers on it, the stride argument is the amount of bytes on each line of the image data. For the constructed 8-bit array we got here, that's simply identical to the width, but when loading it's generally rounded to a multiple of 4, and can contain unused padding bytes. (The function takes care of all that, so the input byte array has no such requirements.)

Nyerguds
  • 4,591
  • 1
  • 27
  • 52
  • I figured it by myself today in the morning and corrected my code, evend used Lockbits etc but i will mark yours as answer just for your ambition. – user2257918 Apr 25 '18 at 20:51