Problem reading bitmap pixel by pixel

Post Reply
elnanni
Posts: 23
Joined: Sat Nov 14, 2009 1:41 am

Problem reading bitmap pixel by pixel

Post by elnanni » Thu Dec 31, 2009 1:49 am

Hi, I've a 32x320 png called tiles, and I'm creating the tilesBitmap variable tanks to grit, then I try to read each pixel:

for(iy = 0; iy < 1024; iy++){
tmp3 = 0;
for(ix = 0; ix < 32; ix++){
bgGetGfxPtr(bgTop2)[tmp3+tmp*256] = tilesBitmap[ix+iy*16];
tmp3 += 1;
}
tmp++;
}

the height is drawn good but the width is at the half and two copies (width 16) are drawn, I read this in a tutorial:

--We do this by starting at line height minus 1 and subtracting the y index. Because video memory only accepts 16 or 32 bit writes we copy two bytes at a time (this is why you see the width divided by 2 in several locations and why video memory and bitmap image memory are declared as pointers to short instead of char).

But i don't get it :(, I don't know how to get the width as it should be :(!!!! Help please :(...

StevenH
Posts: 133
Joined: Sun Feb 22, 2009 7:59 pm

Re: Problem reading bitmap pixel by pixel

Post by StevenH » Thu Dec 31, 2009 2:16 am

Not sure what your issue is here.

Assumptions:
  • Your input image is 32 x 320 pixels
  • Your attempting to take a tile from the images pixel by pixel and put it directly on the screen
  • tilesBitmap is a u16 array
  • tile size is 16 x 16
If your tiles are using less than 256 colours I'd suggest using the tile modes of the DS and not the bitmap mode, unless you need to do everything in software, with no assistance from the hardware.

If I've got the assumptions correctly then I think what you need is something like this:

Code: Select all

void copyTile( u16 *dst, s16 xPos, s16 yPos, u16 tileNo )
{
  u16 ix, iy;
  u16 tileOffset;
  u16 *dstOffset;
  u16 tmp;
  
  tileOffset = ( tileNo % TILESPERLINE ) * TILEWIDTH;
  tileOffset += ( tileNo / TILESPERLINE ) * TILEHEIGHT;
  
  dstOffset = xPos + ( yPos * SCREENWIDTH );
  
  for( iy = 0; iy < TILEHEIGHT; iy ++ )
  {
    tmp = 0;
    for( ix = 0; ix < TILEWIDTH; ix ++ )
    {
      *(dstOffset++) = tileBitmap[ (tmp++) + tileOffset ];
    }
    tileOffset += TILESPERLINE * TILEWIDTH;
  }
}
I can not confirm if the above works as I just quickly typed it in notepad right now :) But (as Johnny 5 said "Need more input") without more information about your issue we can not really help you out.

elnanni
Posts: 23
Joined: Sat Nov 14, 2009 1:41 am

Re: Problem reading bitmap pixel by pixel

Post by elnanni » Thu Dec 31, 2009 2:49 am

Yes, that image holds tiles, but I need to draw each tile pixel y pixel, not 8x8 or 16x16 or 32x32 (each tile is 32x32, but as I said, I need to draw it pixel by pixel).

So, I'm not using tiles at all, I just want to read the data from the tileBitmap array so I can retrieve each pixel color.

So,my guess was that tileBitmap from position 0 to position 31 was the first row of my png, 32 to 63 second row and so on, but it's not, or if it's, it's not in order :S.

Ok, so, this is what I want to show:

Image - I know i does not fit in the screen height, but I'm only triying to get the first 4 tiles.

but it looks like this :(:

Image

Hope it explains better the issue :S.

The code is this:

Code: Select all

  for(iy = 0; iy < 128; iy++){
    tmp3 = 0;
    for(ix = 0; ix < 32; ix++){
      //if(tilesBitmap[ix+iy*16] != -65012705)
        bgGetGfxPtr(bgTop2)[tmp3+tmp*256] = tilesBitmap[ix+iy*16];;
      //if(tilesBitmap[ix+iy*16] != -65012705)
        //bgGetGfxPtr(bgTop2)[(tmp3+1)+tmp*256] = tilesBitmap[(ix+18)+(iy)*16];
      tmp3 += 1;
    }
    tmp++;
  }
The commented lines are because I'm debugging :S.

StevenH
Posts: 133
Joined: Sun Feb 22, 2009 7:59 pm

Re: Problem reading bitmap pixel by pixel

Post by StevenH » Thu Dec 31, 2009 3:27 pm

OH DEAR GOD...

OK, here's what's wrong with your code:

Your working on pixel by pixel plotting of a 32 pixel wide tile and your tile width is set to 16 in your code:

Code: Select all

bgGetGfxPtr(bgTop2)[tmp3+tmp*256] = tilesBitmap[ix+iy*16];
that iy*16 should be iy*32 (or iy<<5).

I've got no idea what that magic number is that your using in the if statements, but it's the wrong size for a u16 colour...

And I know you said that you were working on 2 bytes at a time, but your not as the bgGetGfxPtr() function returns a u16*...

Of the 3 roads to do isometric on the DS, you seem to have taken the hardest route that I would only undertake with a sound knowledge of the limitations of the system, also may I sugest that you drop down from the 16bit colour mode to a 256 colour mode that way you will be able to use a form of double buffering to reduce any tearing effects that you may get on the screen, unless you can confirm that your Iso engine is very good at removing overlapping tiles..

I take it your attempting to do something like Final Fantasy Tactics Advance?

Pic from gamespot : Image

If you are then the way that the game is done was using 2 layers for the background, and the sprites were placed in a layer between the two, since any other way to do the iso tiles would mean that the main CPU would spend most of it's time on graphics and not animation...

If you have any other issues with your endevour please post a reply here and I'll see if I can assist in any way.

elnanni
Posts: 23
Joined: Sat Nov 14, 2009 1:41 am

Re: Problem reading bitmap pixel by pixel

Post by elnanni » Fri Jan 01, 2010 4:43 am

OH DEAR GOD...
Hehehe, Why?? I'm learning :S, I love to code, but I've always been a high level developer, so I find it difucult to think in low leve.

Any way, I found the problem :D...

Code: Select all

void drawTile(int bg, int tileYStart, int tileXStart, int scrY, int scrX){

  int tileY;
  int tileX;
  int screenY;
  int screenX;
  u16 pixels[2];

  screenY = scrY;

  for(tileY = tileYStart; tileY < tileYStart + 32; tileY++){
    if(screenY >= 0 && screenY <= 192){
      screenX = scrX;
      for(tileX = tileXStart; tileX < tileXStart + 16; tileX++){
        if(screenX >= 0 && screenX <= 256){
          pixels[0] = tilesBitmap[tileX + tileY * 16] << 16 >> 16;
          pixels[1] = tilesBitmap[tileX + tileY * 16] >> 16;
          if(pixels[0] != 64543)
            bgGetGfxPtr(bg)[screenX + screenY * 256] = pixels[0];
          if(pixels[1] != 64543)
            bgGetGfxPtr(bg)[screenX + 1 + screenY * 256] = pixels[1];
        }
        screenX += 2;
      }
    }
    screenY++;
  }

}
I did not know that the bgGetGfxPtr(bg)[X] was 2 bytes and tilesBitmap[X] was 4, so that was the problem :D.

It might be the hardest route, but I really belive is the right one, I don't like the way Square-Enix code that :S.

As I'll just start working whith elevations and scroll I still don't know if the engine will work without double buffer.

:D...

BTW Happy New Year!!! :D

EDIT:

The magic number is to avoid drawing the magenta color, so we can draw the isometric effect without problem :D.

StevenH
Posts: 133
Joined: Sun Feb 22, 2009 7:59 pm

Re: Problem reading bitmap pixel by pixel

Post by StevenH » Fri Jan 01, 2010 3:54 pm

elnanni wrote:
OH DEAR GOD...
Hehehe, Why?? I'm learning :S, I love to code, but I've always been a high level developer, so I find it difucult to think in low leve.
Why, because I had a convo with WinterMute a few weeks back but I was in your shoes XD. I'm was actually attempting to write a software rendering system that uses 8x8 pixel maps for the iso tiles (If you've read the book by TANSTAAFL on GameDev then you may know what I'm on about). I hope that you can get something working.
elnanni wrote: Any way, I found the problem :D...

Code: Select all

void drawTile(int bg, int tileYStart, int tileXStart, int scrY, int scrX){

  int tileY;
  int tileX;
  int screenY;
  int screenX;
  u16 pixels[2];

  screenY = scrY;

  for(tileY = tileYStart; tileY < tileYStart + 32; tileY++){
    if(screenY >= 0 && screenY <= 192){
      screenX = scrX;
      for(tileX = tileXStart; tileX < tileXStart + 16; tileX++){
        if(screenX >= 0 && screenX <= 256){
          pixels[0] = tilesBitmap[tileX + tileY * 16] << 16 >> 16;
          pixels[1] = tilesBitmap[tileX + tileY * 16] >> 16;
          if(pixels[0] != 64543)
            bgGetGfxPtr(bg)[screenX + screenY * 256] = pixels[0];
          if(pixels[1] != 64543)
            bgGetGfxPtr(bg)[screenX + 1 + screenY * 256] = pixels[1];
        }
        screenX += 2;
      }
    }
    screenY++;
  }

}
I did not know that the bgGetGfxPtr(bg)[X] was 2 bytes and tilesBitmap[X] was 4, so that was the problem :D.

It might be the hardest route, but I really belive is the right one, I don't like the way Square-Enix code that :S.

As I'll just start working whith elevations and scroll I still don't know if the engine will work without double buffer.

:D...

BTW Happy New Year!!! :D

EDIT:

The magic number is to avoid drawing the magenta color, so we can draw the isometric effect without problem :D.
If your using magic numbers, I would use a #define at some point or use the RGB macros - RGB5(31,0,31) for example.

Oh and you have a fault in that code as both pixel[0] and pixel[1] are from the same source pixel location. Oh and what's the <<16 >>16 for on the same line?

Discostew
Posts: 103
Joined: Sun Mar 08, 2009 7:24 pm

Re: Problem reading bitmap pixel by pixel

Post by Discostew » Fri Jan 01, 2010 7:50 pm

StevenH wrote:Oh and what's the <<16 >>16 for on the same line?
If 'tilesBitmap' is a 32-bit array, then I'd hazard a guess that it is odd upper bit clipping (if the value being used is 32-bit), in which case, using '& 0xFFFF' would be better as it retains only the lower 16 bits.

elnanni
Posts: 23
Joined: Sat Nov 14, 2009 1:41 am

Re: Problem reading bitmap pixel by pixel

Post by elnanni » Fri Jan 01, 2010 11:25 pm

Ok, I'm not really good explaining myself :S, and it's worst in other language :S. Anyway, I'll try:

bgGetGfxPtr(bg)[n] - size 2 bytes:
|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|
tilesBitmap[n] - size 4 bytes, so, it contains 2 pixels instead of one, and that is what I did not understand.
|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|

so:

pixels[0] = tilesBitmap[n] << 16 >> 16;

tilesBitmap[n] << 16:
|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
then >> 16:
|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|
pixels[0] = |x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|x2|

and pixels[1] = tilesBitmap[n] >> 16;
|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|
pixels[1] = |x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|x1|

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 20 guests