1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
/* Simple shell used by demos. Uses SDL multimedia library. */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "SDL.h"
/* Image loader */
typedef struct image_t
{
unsigned char const* byte_pixels;/* 8-bit pixels */
unsigned short const* rgb_16; /* 16-bit pixels */
int width;
int height;
int row_width; /* number of pixels to get to next row (may be greater than width) */
} image_t;
/* if no palette, loads as 16-bit RGB */
void load_bmp( image_t* out, const char* path, SDL_Color palette [256] );
void save_bmp( const char* path );
void init_window( int width, int height );
int read_input( void );
void lock_pixels( void );
void double_output_height( void );
void display_output( void );
void fatal_error( const char* str );
static unsigned char* output_pixels; /* 16-bit RGB */
static long output_pitch;
static float mouse_x, mouse_y; /* -1.0 to 1.0 */
static int mouse_moved;
static int key_pressed;
/* implementation */
static SDL_Rect rect;
static SDL_Surface* screen;
static SDL_Surface* surface;
static unsigned long next_time;
void fatal_error( const char* str )
{
fprintf( stderr, "Error: %s\n", str );
exit( EXIT_FAILURE );
}
static void init_sdl_( void )
{
static int initialized;
if ( !initialized )
{
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
fatal_error( "SDL initialization failed" );
atexit( SDL_Quit );
}
}
void init_window( int width, int height )
{
rect.w = width;
rect.h = height;
init_sdl_();
screen = SDL_SetVideoMode( width, height, 0, 0 );
surface = SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, 16, 0, 0, 0, 0 );
if ( !screen || !surface )
fatal_error( "SDL initialization failed" );
SDL_WM_SetCaption( "NTSC Filter Demo", "NTSC Filter Demo" );
}
int read_input( void )
{
SDL_Event e;
/* limit to 60 calls per second */
unsigned long start = SDL_GetTicks();
if ( start < next_time && next_time - start > 10 )
SDL_Delay( next_time - start );
while ( SDL_GetTicks() < next_time ) { }
next_time = start + 1000 / 60;
mouse_moved = 0;
key_pressed = 0;
while ( SDL_PollEvent( &e ) )
{
if ( e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_QUIT )
return 0;
if ( e.type == SDL_KEYDOWN )
{
if ( e.key.keysym.sym == SDLK_ESCAPE || e.key.keysym.sym == SDLK_q )
return 0;
key_pressed = e.key.keysym.sym;
}
if ( e.type == SDL_MOUSEMOTION )
{
int x, y;
SDL_GetMouseState( &x, &y );
mouse_moved = 1;
mouse_x = x / (float) (SDL_GetVideoSurface()->w - 1) * 2 - 1;
mouse_y = (1 - y / (float) (SDL_GetVideoSurface()->h - 1)) * 2 - 1;
}
}
return 1;
}
void lock_pixels( void )
{
if ( SDL_LockSurface( surface ) < 0 )
fatal_error( "Couldn't lock surface" );
SDL_FillRect( surface, 0, 0 );
output_pitch = surface->pitch;
output_pixels = (unsigned char*) surface->pixels;
}
void double_output_height( void )
{
int y;
for ( y = surface->h / 2; --y >= 0; )
{
unsigned char const* in = output_pixels + y * output_pitch;
unsigned char* out = output_pixels + y * 2 * output_pitch;
int n;
for ( n = surface->w; n; --n )
{
unsigned prev = *(unsigned short*) in;
unsigned next = *(unsigned short*) (in + output_pitch);
/* mix 16-bit rgb without losing low bits */
unsigned mixed = prev + next + ((prev ^ next) & 0x0821);
/* darken by 12% */
*(unsigned short*) out = prev;
*(unsigned short*) (out + output_pitch) = (mixed >> 1) - (mixed >> 4 & 0x18E3);
in += 2;
out += 2;
}
}
}
void display_output( void )
{
SDL_UnlockSurface( surface );
if ( SDL_BlitSurface( surface, &rect, screen, &rect ) < 0 || SDL_Flip( screen ) < 0 )
fatal_error( "SDL blit failed" );
}
void load_bmp( image_t* out, const char* path, SDL_Color palette [256] )
{
SDL_PixelFormat fmt = { 0 }; /* clear fields */
SDL_Palette pal = { 0 };
SDL_Surface* bmp;
SDL_Surface* conv;
init_sdl_();
bmp = SDL_LoadBMP( path );
if ( !bmp )
fatal_error( "Couldn't load BMP" );
fmt.BitsPerPixel = 16;
fmt.BytesPerPixel = 2;
if ( palette )
{
pal.ncolors = 256;
pal.colors = palette;
fmt.palette = &pal;
fmt.BitsPerPixel = 8;
fmt.BytesPerPixel = 1;
}
conv = SDL_ConvertSurface( bmp, &fmt, SDL_SWSURFACE );
if ( !conv )
fatal_error( "Couldn't convert BMP" );
SDL_FreeSurface( bmp );
if ( SDL_LockSurface( conv ) < 0 )
fatal_error( "Couldn't lock surface" );
out->byte_pixels = (unsigned char *) conv->pixels;
out->rgb_16 = (unsigned short*) conv->pixels;
out->width = conv->w;
out->height = conv->h;
out->row_width = conv->pitch / fmt.BytesPerPixel;
}
void save_bmp( const char* path )
{
if ( SDL_SaveBMP( surface, path ) )
fatal_error( "Couldn't save BMP" );
}
|