Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An algorithm for iterating over a rectangular area inside a 1 dimensional array (bitmapping)

This is an odd question which I had a tough time writing a title for.

I'm working with pixels (bitmaps, more specifically) and can't figure out the (simple) maths for pragmatically accessing each array cell.

My canvas is [n16 x 16] pixels, n is always 1 or greater.

Here's a photo of a basic n = 2 canvas:

http://i.imgur.com/mabwQfJ.png

enter image description here

What I want my magical algorithm to do is run from 0 to 495 without touching that lighter grey area then go from 16 to 512 (which is actually cell 511, my bad) without touching the dark grey area.

So, 0 to 15, skip 16 to 31 followed by 32 to 47, etc.

And for n = 3:

http://i.imgur.com/TqJMWl6.png

enter image description here

In this case it would be 0-735 skipping the lighter grey areas, 16-751 skipping the areas on each side and 32-767 skipping the darker grey areas.

What I tried:

Here's an extract from my code, hopefully it's useful and shows what I tried already. It's the part that figures out the value for 'idxpos'.

// Let's say length = 3 for now.
for (int character = 0; character < length; ++character)
{
    // in case you're wondering, it grabs 16x16 characters from an ASCII spritesheet
    charpos = (string[character] - ' ') * 16 * 16;

    // Runs through the spritesheet character map
    // this is a huge 16x1520 bitmap.
    for (int pixel = 0; pixel < 16 * 16; ++pixel)
    {
        // ignore this, just me messing around with pixel tinting
        r = (((CharMap[charpos + pixel] >> 0) & 0xFF) + 255 - u);
        g = (((CharMap[charpos + pixel] >> 8) & 0xFF) + 255 - v);
        b = (((CharMap[charpos + pixel] >> 16) & 0xFF) + 255 - w);
        newcolour = RGB(r, g, b);

        // THIS is the part I am stuck on:
        idxpos = pixel + (character * 16 * 16);

        bitmap[idxpos] = CharMap[charpos + j];
    }
}

You probably get the idea. It sounds dead simple to me but I can't figure it out.

Oh, and I'm not interested in some magical library that can handle all my bitmap stuff for me, I'm not in a position where I can use one.

like image 542
Southclaws Avatar asked Apr 22 '15 16:04

Southclaws


2 Answers

If i get your question properly, you want to visit them in the order you mentioned. Here's the code that does that (given your n):

for(int i = 0; i < n; i++) //which section we are going through
{
  for(int row = 0; row < size; row++) //size = 16, better use on of your constants
  { 
    for(int col = 0; col < size; col++)
    {
      int pixelIndex = size * (row * n) + col + size * i; 
      /*the last one is an offset - it moves the 
      index to the right as far as we need.
      If you need two coordinates (as in (x,y))
      instead of one number, it is: */
      int x = row, y = col + size * i;
      doSomethingWithPixel(pixelIndex);
    }
  }
}

Hope this helps.

like image 170
Filip Kowalski Avatar answered Oct 31 '22 11:10

Filip Kowalski


Its simple enough. Taking n as the rectangle total width multiplier and bitmap as your rectangle data:

for (int i = 0; i < 16*16; ++i) // 16*16 because you want a 16x16 area
{
    int x = i % 16;
    int y = i / 16;
    bitmap[x + y * 16 * n] = value;
}

Now say you want to do it on the second square, or square of index square = 1:

for (int i = 0; i < 16*16; ++i)
{
    int x = i % 16;
    int y = i / 16;
    bitmap[x + y * 16 * n + 16 * square] = value;
}

You can also have a more generic function to all shapes of bitmaps that takes a rect and allow you to modify data in any rectangle you want inside your bitmap. It only needs the bitmap width as reference:

void bitmap_fill(int* bitmap, int width, int top, int left, int right, int bottom)
{
    for (; top <= bottom; ++top)
        for (int x = left; x <= right; ++x)
             bitmap[top * width + x] = value;
}
like image 24
Havenard Avatar answered Oct 31 '22 11:10

Havenard