Unfathomable Depths
sláinte
I wrote this for my GBAX 2007 entry and thought it might be useful to someone.
It takes a bitmap and scales it to a user specified size.
The function prototype looks like this:
CODE
void bmscaler( int top_left_x, int top_left_y,
int bottom_right_x, int bottom_right_y,
int source_width, int source_height,
SDL_Surface *source, SDL_Surface *dest);
The top left x/y and bottom right x/y specify the size and position you want the bitmap scaled to. So if you specified 0,0,10,10 you would get a 10x10 pixel version of your original bitmap at position 0,0 on the destination SDL surface. Specifying 20,20,30,30 would give you a 10x10 at 20,20.
Be aware it doesn't clip the scaled bitmap so if it is outside the SDL surface you'll probably get a lock-up or crash.
source_width and source_height specify the size of the source in pixels.
SDL_Surface *source and SDL_Surface *dest and the source and destination.
So a call of bmscaler(0,0,200,200,100,100,pacman_graphic,screen) will upscale.
Conversely bmscaler(0,0,50,50,100,100,pacman_graphic,screen) will downscale.
Black is transparent.
Heres the full routine. Sorry in advance for the not very logical varible names - I tried originally a different way of scaling and those vars a legacy from that failed attempt (well not failed - just very slow)
CODE
void bmscaler(
int top_left_x, int top_left_y,
int bottom_right_x, int bottom_right_y,
int source_width, int source_height,
SDL_Surface *source, SDL_Surface *dest)
{
int destination_width,destination_height;
destination_width=bottom_right_x-top_left_x;
destination_height=bottom_right_y-top_left_y;
int screen_x=top_left_x;
int screen_y=top_left_y;
SDL_LockSurface(source);
SDL_LockSurface(dest);
Uint32 pixel_full;
pixel_full=(Uint32)source->pixels;
int source_pitch=source->pitch;
int dest_pitch=dest->pitch;
int dest_pixels=(int)dest->pixels + screen_y * dest_pitch + screen_x * 2;
int old_dest=dest_pixels;
Uint32 old_source=pixel_full;
Uint32 xratio= ((Uint32)source_width << 16) /(bottom_right_x-top_left_x);
Uint32 yratio= ((Uint32)source_height << 16)/(bottom_right_y-top_left_y);
SDL_UnlockSurface(dest);
SDL_UnlockSurface(source);
Uint32 ypos=0;
for(int i=screen_y;i<screen_y+destination_height;i++)
{
Uint32 xpos=0, yoff=(ypos>>16)*source_pitch;
for(int j=screen_x;j<screen_x+destination_width;j++)
{
Uint16 a=*(Uint16 *)(pixel_full+((xpos>>15) & 65534) + yoff);
if (a!=0) *(Uint16 *)(dest_pixels)=a;
xpos+=xratio;
dest_pixels++;dest_pixels++;
}
dest_pixels=old_dest; dest_pixels+=dest_pitch; old_dest=dest_pixels;
ypos+=yratio;
}
}
Its reasonably fast but could probably be optimized quite a bit.
Feel free to use it in your projects.
It takes a bitmap and scales it to a user specified size.
The function prototype looks like this:
CODE
void bmscaler( int top_left_x, int top_left_y,
int bottom_right_x, int bottom_right_y,
int source_width, int source_height,
SDL_Surface *source, SDL_Surface *dest);
The top left x/y and bottom right x/y specify the size and position you want the bitmap scaled to. So if you specified 0,0,10,10 you would get a 10x10 pixel version of your original bitmap at position 0,0 on the destination SDL surface. Specifying 20,20,30,30 would give you a 10x10 at 20,20.
Be aware it doesn't clip the scaled bitmap so if it is outside the SDL surface you'll probably get a lock-up or crash.
source_width and source_height specify the size of the source in pixels.
SDL_Surface *source and SDL_Surface *dest and the source and destination.
So a call of bmscaler(0,0,200,200,100,100,pacman_graphic,screen) will upscale.
Conversely bmscaler(0,0,50,50,100,100,pacman_graphic,screen) will downscale.
Black is transparent.
Heres the full routine. Sorry in advance for the not very logical varible names - I tried originally a different way of scaling and those vars a legacy from that failed attempt (well not failed - just very slow)
CODE
void bmscaler(
int top_left_x, int top_left_y,
int bottom_right_x, int bottom_right_y,
int source_width, int source_height,
SDL_Surface *source, SDL_Surface *dest)
{
int destination_width,destination_height;
destination_width=bottom_right_x-top_left_x;
destination_height=bottom_right_y-top_left_y;
int screen_x=top_left_x;
int screen_y=top_left_y;
SDL_LockSurface(source);
SDL_LockSurface(dest);
Uint32 pixel_full;
pixel_full=(Uint32)source->pixels;
int source_pitch=source->pitch;
int dest_pitch=dest->pitch;
int dest_pixels=(int)dest->pixels + screen_y * dest_pitch + screen_x * 2;
int old_dest=dest_pixels;
Uint32 old_source=pixel_full;
Uint32 xratio= ((Uint32)source_width << 16) /(bottom_right_x-top_left_x);
Uint32 yratio= ((Uint32)source_height << 16)/(bottom_right_y-top_left_y);
SDL_UnlockSurface(dest);
SDL_UnlockSurface(source);
Uint32 ypos=0;
for(int i=screen_y;i<screen_y+destination_height;i++)
{
Uint32 xpos=0, yoff=(ypos>>16)*source_pitch;
for(int j=screen_x;j<screen_x+destination_width;j++)
{
Uint16 a=*(Uint16 *)(pixel_full+((xpos>>15) & 65534) + yoff);
if (a!=0) *(Uint16 *)(dest_pixels)=a;
xpos+=xratio;
dest_pixels++;dest_pixels++;
}
dest_pixels=old_dest; dest_pixels+=dest_pitch; old_dest=dest_pixels;
ypos+=yratio;
}
}
Its reasonably fast but could probably be optimized quite a bit.
Feel free to use it in your projects.