spx31
spx31

Reputation: 133

Creating a chess board with variable square size

I have a class called Image in C++, where I have a width, and height and a long vector which stores all the pixel values in a manner, that it iterates through the first column, then it moves one row down, iterates through the second column etc.. ( 0 ist black, 255 is white )

Now I have written a function void chess (), that transforms the pixel values in such a way that it has the basic chess pattern on it, when you give it out.

My next idea is to create chess board with varying size,e.g. width 8, height 8, and each square of the chessboard is 2x2 pixels instead of 1x1

Now, if I try to implement it, my only "idea" is to use 2 counters, one to track that it changes from white to black not after every pixel, but after the new size of pixels. Additionally, you'd have to have a second counter to keep track, after how many rows you have to invert, so you start with black, instead of white.

Yet I can't figure it out, I end up with so many If statements and for and while loops, that it always comes out messy. There has to be a significantly easier way. Does anybody have any ideas?

class Image
{
public:
    typedef uint16_t PixelType;

private:
    int width_;
    int height_;
    std::vector<PixelType> data_;

public:
    // Standardkonstruktor: initialisiere Bild mit Groesse (0,0)
    Image()
    : width_(0)
    , height_(0)
    {}

    Image(unsigned int width, unsigned int height)
    : width_(width)
      , height_(height)
    {
        int size = width * height;

        for(int j=0; j < height; j++)
        {
            for(int i=0; i < width; i++)
            {
                data_.push_back(0);
            }
        }
    }

    void chess() // change an image to chess board pattern
    {
        data_.clear();
        int width = (*this).width();
        int height = (*this).height();

        for(int w=0; w < width; w++)
        {
            for(int h=1; h <= height; h++)
            {
                /*std::cout << "P=("+ std::to_string(w) + "," + std::to_string(h) + ")" << std::endl;
                std::cout << std::to_string(h%2) <<std::endl;
                for testing purposes only */
                if(w%2==0)
                {
                    if( !(h%2==0) )
                    {
                        data_.push_back(255);
                    }
                    else
                    {
                        data_.push_back(0);
                    }
                }
                else
                {
                    if( !(h%2==0) )
                    {
                        data_.push_back(0);
                    } else
                    {
                        data_.push_back(255);
                    }

                }
            }
        }
    }
};

Upvotes: 0

Views: 1315

Answers (2)

Yuriy Ivaskevych
Yuriy Ivaskevych

Reputation: 966

I think it is actually better to allocate the vector first (as pointed out in @Humam 's comment to your question) and then just setting it's values.

Suppose you want your cells to be n x n pixels size (I hope you check width and height to be divisible by n). One solution can be something like this:

void chess(int n)                          // pass n as parameter or as you want
{
    ...

    bool isBlackCell = true;               // change to false to start with a white one

    for(int h=0; h < height; h+=n)
    {
        for(int w=0; w < width; w+=n)
        {
            // now fill the whole cell
            for (int i=0; i < n; ++i)
            {
                for (int j=0; j < n; ++j)
                {
                    data_[(h+i)*size+w+j] = isBlackCell ? 0 : 255;
                }
            }

            // switch to another color as we moving to another 'cell'
            isBlackCell = !isBlackCell;
        }
    }

Note: This is straightforward but a bit inefficient because of painful cache misses

Edit 1: Let me explain what this data_[(h+i)*w+w+j] does: as you store your pixel data row after row, so (h+i)*size skips (h+i) rows and then comes to current pixel position adding w+j

Upvotes: 0

Stefan Matcovici
Stefan Matcovici

Reputation: 106

You could try coloring the matrix based on the parity of the w and h. If w+h is even color black else color white. Start with both h and w from 0.

Upvotes: 3

Related Questions