GP32 Synkro's Resize Code


Rik

Member
Joined
Dec 21, 2004
Messages
103
Age
40
Website
Visit site
Hi~

I made an ugly bastardisation of Synkro's clever bitmap resizing code as found here: http://www.gp32.co.nz/snippet_view.php?snippet_id=24

Certain sized bitmaps (orig size) were being displayed wrong (from rounding error), so I've just added an 'offset' which I can pass through to correct it. Can anyone see which sizes will need which offset? I'm assuming we can work out the offset automaticly but I've only tested a few sizes so far and I don't really understand it. Only offsets I've used are 0, 1 and 2, and I'd assume 2 is the max you'd ever need but since I don't fully understand the problem, that could be a red herring.

edit: The first thing I thought of was odd old_width and/or old_height, but certain even sizes did the same error IIRC.

Sorry for the dreadfuly unreadable version of the code, I started remaking the whole loop in a different way, then ended up putting it all back to basicly how it originaly worked. Main difference is that it works on the gamepark SDK with Edorul/Gp32convertor graphics format and I made four versions with variable transparency / boundry checking.

If you can't work out what's going on just look at Synkro's original code (http://www.gp32.co.nz/snippet_view.php?snippet_id=24).

Code:
void scale(int old_width, int old_height, int new_width, int new_height, int put_x, int put_y, int offset, unsigned char * bitmap){

int dx, dy;
  for(dx=0; dx<new_width; dx++){
    for(dy=0; dy<new_height; dy++){
      //LCDbuffer[nflip].ptbuffer[(dx + put_x) * 240 + dy + put_y] = bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)];
      memcpy( &LCDbuffer[nflip].ptbuffer[(dx + put_x) * 240 + dy + put_y], &bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)], 1 );
  	}
  }
}

void scale_check(int old_width, int old_height, int new_width, int new_height, int put_x, int put_y, int offset, unsigned char * bitmap){
int dx, dy;

  for(dx=0; dx<new_width; dx++)
  {
  	if(dx + put_x >= 0 && dx + put_x < 320){
     for(dy=0; dy<new_height; dy++){
      if (dy + put_y >= 0 && dy + put_y < 240){
         //LCDbuffer[nflip].ptbuffer[(dx + put_x) * 240 + dy + put_y] = bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)];
        	memcpy( &LCDbuffer[nflip].ptbuffer[(dx + put_x) * 240 + dy + put_y], &bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)], 1 );
      }
    }
  	}
  }
}

void scale_trans(int old_width, int old_height, int new_width, int new_height, int put_x, int put_y, int offset, unsigned char * bitmap, unsigned char trans){

int dx, dy;
  for(dx=0; dx<new_width; dx++){
    for(dy=0; dy<new_height; dy++){
    	if (bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)] != trans){
      	//LCDbuffer[nflip].ptbuffer[(dx + put_x) * 240 + dy + put_y] = bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)];
      	memcpy( &LCDbuffer[nflip].ptbuffer[(dx + put_x) * 240 + dy + put_y], &bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)], 1 );
    }
  	}
  }
}

void scale_trans_check(int old_width, int old_height, int new_width, int new_height, int put_x, int put_y, int offset, unsigned char * bitmap, unsigned char trans){
int dx, dy;  

  for(dx=0; dx<new_width; dx++)
  {
  	if(dx + put_x >= 0 && dx + put_x < 320){
     for(dy=0; dy<new_height; dy++){
      if (dy + put_y >= 0 && dy + put_y < 240){
      	if (bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)] != trans){
        	//LCDbuffer[nflip].ptbuffer[(dx + put_x) * 240 + dy + put_y] = bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)];
        	memcpy( &LCDbuffer[nflip].ptbuffer[(dx + put_x) * 240 + dy + put_y], &bitmap[(((dx*old_width) / new_width) * (old_height + offset)) + ((dy*old_height) / new_height)], 1 );
      }
      }
    }
  	}
  }
}
 
can you give an example bitmap and the destinated size? I tested it only with square bitmaps and it works. what special cases did you use?
 
can you give an example bitmap and the destinated size? I tested it only with square bitmaps and it works. what special cases did you use?

Current image I'm using is:
#define gfx_title_width 204
#define gfx_title_height 191

and requires an offset of 1. I think 320x240 required an offset of 0.
 
Last edited by a moderator:
I am working on a better scaling code. I can get horizantal scaling easily simply by memcpy-ing the source lines multiple times. That way there is no speed penalty, except that of copying the extra data, which is something you just can't get around. Now I have to work on the vertical part.
 
I am working on a better scaling code. I can get horizantal scaling easily simply by memcpy-ing the source lines multiple times. That way there is no speed penalty, except that of copying the extra data, which is something you just can't get around. Now I have to work on the vertical part.

Surely you can only do that if the old_height and new_height are the same? And not at all for transparants?

I wonder how Smash GP scales, that seems very fast.
 
Last edited by a moderator:
I am working on a better scaling code. I can get horizantal scaling easily simply by memcpy-ing the source lines multiple times. That way there is no speed penalty, except that of copying the extra data, which is something you just can't get around. Now I have to work on the vertical part.

Surely you can only do that if the old_height and new_height are the same? And not at all for transparants?

I wonder how Smash GP scales, that seems very fast.

Yes, that is true. I will have to scale the height the old-fashioned way.
I also have to figure out clipping, and non-integer scaling (when old_width/height and new_width/height are not exact multiples). For transparency/alpha/both, you'd need to blit it to a temporary buffer, then blit the temporary buffer with transparency/alpha/both.
 
Last edited by a moderator:
Back
Top