test/testbitmap.c
author Patrice Mandin <patmandin@gmail.com>
Thu, 19 Jan 2006 21:28:52 +0000
changeset 1257 448a9a64537b
parent 1151 be9c9c8f6d53
child 1662 782fd950bd46
child 1895 c121d94672cb
permissions -rw-r--r--
[PATCH] SDL_GetVideoMode() does not find best mode, part 2

Following commit 1.51, I come accross a problem when SDL must choose between
several video modes that could suit the one asked.

If I ask 320x240 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200

The smallest selectables modes are 384x240 and 320x400. And SDL choose the later
in this list, but 384x240 is more suitable. So I added a check to compare
the pixel count (surface) of modes, and select the one which has the smallest
pixel count.

In my example, 384x240 has 92160 pixels, and 320x400 has 128000 pixels. So now
SDL will choose 384x240 for the asked 320x240 mode.
slouken@0
     1
slouken@0
     2
/* Simple program:  Test bitmap blits */
slouken@0
     3
slouken@0
     4
#include <stdio.h>
slouken@0
     5
#include <stdlib.h>
slouken@0
     6
#include <string.h>
slouken@0
     7
slouken@0
     8
#include "SDL.h"
slouken@0
     9
#include "picture.xbm"
slouken@0
    10
icculus@1151
    11
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
icculus@1151
    12
static void quit(int rc)
icculus@1151
    13
{
icculus@1151
    14
	SDL_Quit();
icculus@1151
    15
	exit(rc);
icculus@1151
    16
}
icculus@1151
    17
slouken@0
    18
SDL_Surface *LoadXBM(SDL_Surface *screen, int w, int h, Uint8 *bits)
slouken@0
    19
{
slouken@0
    20
	SDL_Surface *bitmap;
slouken@0
    21
	Uint8 *line;
slouken@0
    22
slouken@0
    23
	/* Allocate the bitmap */
slouken@0
    24
	bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 1, 0, 0, 0, 0);
slouken@0
    25
	if ( bitmap == NULL ) {
slouken@0
    26
		fprintf(stderr, "Couldn't allocate bitmap: %s\n",
slouken@0
    27
						SDL_GetError());
slouken@0
    28
		return(NULL);
slouken@0
    29
	}
slouken@0
    30
slouken@0
    31
	/* Copy the pixels */
slouken@0
    32
	line = (Uint8 *)bitmap->pixels;
slouken@0
    33
	w = (w+7)/8;
slouken@0
    34
	while ( h-- ) {
slouken@0
    35
		memcpy(line, bits, w);
slouken@0
    36
		/* X11 Bitmap images have the bits reversed */
slouken@0
    37
		{ int i, j; Uint8 *buf, byte;
slouken@0
    38
			for ( buf=line, i=0; i<w; ++i, ++buf ) {
slouken@0
    39
				byte = *buf;
slouken@0
    40
				*buf = 0;
slouken@0
    41
				for ( j=7; j>=0; --j ) {
slouken@0
    42
					*buf |= (byte&0x01)<<j;
slouken@0
    43
					byte >>= 1;
slouken@0
    44
				}
slouken@0
    45
			}
slouken@0
    46
		}
slouken@0
    47
		line += bitmap->pitch;
slouken@0
    48
		bits += w;
slouken@0
    49
	}
slouken@0
    50
	return(bitmap);
slouken@0
    51
}
slouken@0
    52
slouken@0
    53
int main(int argc, char *argv[])
slouken@0
    54
{
slouken@0
    55
	SDL_Surface *screen;
slouken@0
    56
	SDL_Surface *bitmap;
slouken@0
    57
	Uint8  video_bpp;
slouken@0
    58
	Uint32 videoflags;
slouken@0
    59
	Uint8 *buffer;
slouken@691
    60
	int i, k, done;
slouken@0
    61
	SDL_Event event;
slouken@691
    62
	Uint16 *buffer16;
slouken@691
    63
        Uint16 color;
slouken@691
    64
        Uint8  gradient;
slouken@691
    65
	SDL_Color palette[256];
slouken@691
    66
slouken@0
    67
slouken@0
    68
	/* Initialize SDL */
slouken@0
    69
	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
slouken@0
    70
		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
icculus@1151
    71
		return(1);
slouken@0
    72
	}
slouken@0
    73
slouken@0
    74
	video_bpp = 0;
slouken@0
    75
	videoflags = SDL_SWSURFACE;
slouken@0
    76
	while ( argc > 1 ) {
slouken@0
    77
		--argc;
slouken@0
    78
		if ( strcmp(argv[argc-1], "-bpp") == 0 ) {
slouken@0
    79
			video_bpp = atoi(argv[argc]);
slouken@0
    80
			--argc;
slouken@0
    81
		} else
slouken@0
    82
		if ( strcmp(argv[argc], "-warp") == 0 ) {
slouken@0
    83
			videoflags |= SDL_HWPALETTE;
slouken@0
    84
		} else
slouken@0
    85
		if ( strcmp(argv[argc], "-hw") == 0 ) {
slouken@0
    86
			videoflags |= SDL_HWSURFACE;
slouken@0
    87
		} else
slouken@0
    88
		if ( strcmp(argv[argc], "-fullscreen") == 0 ) {
slouken@0
    89
			videoflags |= SDL_FULLSCREEN;
slouken@0
    90
		} else {
slouken@0
    91
			fprintf(stderr,
slouken@0
    92
			"Usage: %s [-bpp N] [-warp] [-hw] [-fullscreen]\n",
slouken@0
    93
								argv[0]);
icculus@1151
    94
			quit(1);
slouken@0
    95
		}
slouken@0
    96
	}
slouken@0
    97
slouken@0
    98
	/* Set 640x480 video mode */
slouken@0
    99
	if ( (screen=SDL_SetVideoMode(640,480,video_bpp,videoflags)) == NULL ) {
slouken@0
   100
		fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
slouken@0
   101
						video_bpp, SDL_GetError());
icculus@1151
   102
		quit(2);
slouken@0
   103
	}
slouken@0
   104
slouken@691
   105
	if (video_bpp==8) {
slouken@691
   106
		/* Set a gray colormap, reverse order from white to black */
slouken@691
   107
		for ( i=0; i<256; ++i ) {
slouken@691
   108
			palette[i].r = 255-i;
slouken@691
   109
			palette[i].g = 255-i;
slouken@691
   110
			palette[i].b = 255-i;
slouken@691
   111
		}
slouken@691
   112
		SDL_SetColors(screen, palette, 0, 256);
slouken@691
   113
	}
slouken@691
   114
slouken@0
   115
	/* Set the surface pixels and refresh! */
slouken@0
   116
	if ( SDL_LockSurface(screen) < 0 ) {
slouken@0
   117
		fprintf(stderr, "Couldn't lock the display surface: %s\n",
slouken@0
   118
							SDL_GetError());
icculus@1151
   119
		quit(2);
slouken@0
   120
	}
slouken@0
   121
	buffer=(Uint8 *)screen->pixels;
slouken@691
   122
	if (screen->format->BytesPerPixel!=2) {
slouken@691
   123
        	for ( i=0; i<screen->h; ++i ) {
slouken@691
   124
        		memset(buffer,(i*255)/screen->h, screen->pitch);
slouken@691
   125
        		buffer += screen->pitch;
slouken@691
   126
        	}
slouken@691
   127
        }
slouken@691
   128
        else
slouken@691
   129
        {
slouken@691
   130
		for ( i=0; i<screen->h; ++i ) {
slouken@691
   131
			gradient=((i*255)/screen->h);
slouken@691
   132
                        color = SDL_MapRGB(screen->format, gradient, gradient, gradient);
slouken@691
   133
                        buffer16=(Uint16*)buffer;
slouken@691
   134
                        for (k=0; k<screen->w; k++)
slouken@691
   135
                        {
slouken@691
   136
                            *(buffer16+k)=color;
slouken@691
   137
                        }
slouken@691
   138
			buffer += screen->pitch;
slouken@691
   139
		}
slouken@691
   140
        }
slouken@0
   141
	SDL_UnlockSurface(screen);
slouken@0
   142
	SDL_UpdateRect(screen, 0, 0, 0, 0);
slouken@0
   143
slouken@0
   144
	/* Load the bitmap */
slouken@0
   145
	bitmap = LoadXBM(screen, picture_width, picture_height,
slouken@0
   146
					(Uint8 *)picture_bits);
slouken@0
   147
	if ( bitmap == NULL ) {
icculus@1151
   148
		quit(1);
slouken@0
   149
	}
slouken@0
   150
slouken@0
   151
	/* Wait for a keystroke */
slouken@0
   152
	done = 0;
slouken@0
   153
	while ( !done ) {
slouken@0
   154
		/* Check for events */
slouken@0
   155
		while ( SDL_PollEvent(&event) ) {
slouken@0
   156
			switch (event.type) {
slouken@0
   157
				case SDL_MOUSEBUTTONDOWN: {
slouken@0
   158
					SDL_Rect dst;
slouken@0
   159
slouken@0
   160
					dst.x = event.button.x - bitmap->w/2;
slouken@0
   161
					dst.y = event.button.y - bitmap->h/2;
slouken@0
   162
					dst.w = bitmap->w;
slouken@0
   163
					dst.h = bitmap->h;
slouken@0
   164
					SDL_BlitSurface(bitmap, NULL,
slouken@0
   165
								screen, &dst);
slouken@0
   166
					SDL_UpdateRects(screen,1,&dst);
slouken@0
   167
					}
slouken@0
   168
					break;
slouken@0
   169
				case SDL_KEYDOWN:
slouken@0
   170
					/* Any key press quits the app... */
slouken@0
   171
					done = 1;
slouken@0
   172
					break;
slouken@0
   173
				case SDL_QUIT:
slouken@0
   174
					done = 1;
slouken@0
   175
					break;
slouken@0
   176
				default:
slouken@0
   177
					break;
slouken@0
   178
			}
slouken@0
   179
		}
slouken@0
   180
	}
slouken@0
   181
	SDL_FreeSurface(bitmap);
icculus@1151
   182
	SDL_Quit();
slouken@0
   183
	return(0);
slouken@0
   184
}