示例#1
0
int main( int argc, char* args[] )
{
    if ( SDL_Init( SDL_INIT_VIDEO ) == -1 )
        return 1;

    SDL_Surface *screen = SDL_SetVideoMode( WIDTH, HEIGHT, 32, SDL_SWSURFACE );
    if ( !screen )
        return 1;

	// Initialize the grid from the BMP file.
    SDL_Surface *temp = SDL_LoadBMP( "test.bmp" );
	temp = SDL_ConvertSurface( temp, screen->format, SDL_SWSURFACE ); 
	SDL_LockSurface( temp );
	for( int y=0;y<HEIGHT;y++ )
	{
		for ( int x=0;x<WIDTH;x++ )
		{
			Uint8 r,g,b;
			Uint32 *src = ( (Uint32 *)( (Uint8 *)temp->pixels + y*temp->pitch ) ) + x;
			SDL_GetRGB( *src, temp->format, &r, &g, &b );
			
			// Points inside get marked with a dx/dy of zero.
			// Points outside get marked with an infinitely large distance.
			if ( g < 128 )
			{
				Put( grid1, x, y, inside );
				Put( grid2, x, y, empty );
			} else {
				Put( grid2, x, y, inside );
				Put( grid1, x, y, empty );
			}
		}
	}
	SDL_UnlockSurface( temp );

	// Generate the SDF.
	GenerateSDF( grid1 );
	GenerateSDF( grid2 );
	
	// Render out the results.
	SDL_LockSurface( screen );
	for( int y=0;y<HEIGHT;y++ )
	{
		for ( int x=0;x<WIDTH;x++ )
		{
			// Calculate the actual distance from the dx/dy
			int dist1 = (int)( sqrt( (double)Get( grid1, x, y ).DistSq() ) );
			int dist2 = (int)( sqrt( (double)Get( grid2, x, y ).DistSq() ) );
			int dist = dist1 - dist2;

			// Clamp and scale it, just for display purposes.
			int c = dist*3 + 128;
			if ( c < 0 ) c = 0;
			if ( c > 255 ) c = 255;

			Uint32 *dest = ( (Uint32 *)( (Uint8 *)screen->pixels + y*screen->pitch ) ) + x;
			*dest = SDL_MapRGB( screen->format, c, c, c );
		}
	}
	SDL_UnlockSurface( screen );
	SDL_Flip( screen );

	// Wait for a keypress
	SDL_Event event;
	while( true )
	{
		if ( SDL_PollEvent( &event ) ) 
		switch( event.type )
		{
		case SDL_QUIT:
		case SDL_KEYDOWN:
			return true;
		}
	}

	return 0;
}
	bool BitmapToSDF(Pixel *SourceBitmap, BMSize SourceWidth, BMSize SourceHeight, Pixel *DestBitmap, BMSize DestWidth, BMSize DestHeight, BMSize InsertX, BMSize InsertY, BMSize InsertWidth, BMSize InsertHeight)
	{
		// Check parameters
		if(SourceBitmap == nullptr || SourceWidth == 0 || SourceHeight == 0 || DestBitmap == nullptr || SourceBitmap == DestBitmap || DestWidth == 0 || DestHeight == 0 || (InsertX + InsertWidth) > DestWidth || (InsertY + InsertHeight) > DestHeight || InsertWidth == 0 || InsertHeight == 0)
			return false;

		// Sizes
		const BMSize SDFWidth = SourceWidth + SDFPaddingSize;
		const BMSize SDFHeight = SourceHeight + SDFPaddingSize;

		// Create two 1-bit per point grids from the Source bitmap, the grids being inverses of each other
		SDFPoint *Grid1 = new SDFPoint[SDFWidth*SDFHeight]();
		SDFPoint *Grid2 = new SDFPoint[SDFWidth*SDFHeight]();

		for(BMSize i = 0; i < SDFWidth*SDFHeight; ++i) // Fill grids with blank
		{
			Grid1[i] = SDFInside;
			Grid2[i] = SDFOutside;
		}
 
		for(BMSize y = 0; y < SourceHeight; ++y) // Write data from source
		{
			for(BMSize x = 0; x < SourceWidth; ++x)
			{
				if(SourceBitmap[(y*SourceWidth) + x] < 128)
				{
					Grid1[(((SDFPaddingSize / 2) + y)*SDFWidth) + ((SDFPaddingSize / 2) + x)] = SDFInside;
					Grid2[(((SDFPaddingSize / 2) + y)*SDFWidth) + ((SDFPaddingSize / 2) + x)] = SDFOutside;
				}
				else
				{
					Grid1[(((SDFPaddingSize / 2) + y)*SDFWidth) + ((SDFPaddingSize / 2) + x)] = SDFOutside;
					Grid2[(((SDFPaddingSize / 2) + y)*SDFWidth) + ((SDFPaddingSize / 2) + x)] = SDFInside;
				}
			}
		}

		// Compute SDF grids
		GenerateSDF(Grid1, SDFWidth, SDFHeight);
		GenerateSDF(Grid2, SDFWidth, SDFHeight);

		// Copy SDF to destination bitmap
		if(SDFWidth == InsertWidth && SDFHeight == InsertHeight && false) // The generation size and output size are the same, so there is no need to convert
		{
			// Copy the final values directly to the destination bitmap
			for(BMSize y = 0; y < SDFHeight; ++y)
			{
				for(BMSize x = 0; x < SDFWidth; ++x)
				{
					// Calculate the actual distance from the dx/dy
					int dist1 = (int)(sqrt((double)SDFGetPoint(Grid1, x, y, SDFWidth, SDFHeight).DistSq()));
					int dist2 = (int)(sqrt((double)SDFGetPoint(Grid2, x, y, SDFWidth, SDFHeight).DistSq()));
					int dist = dist1 - dist2;

					// Clamp
					int c = dist * 3 + 128;
					if(c < 0) c = 0;
					if(c > 255) c = 255;

					// Write to bitmap
					DestBitmap[((InsertY + y)*SDFWidth) + (InsertX + x)] = c;
				}
			}
		}
		else // Need to scale the output
		{
			// Copy the final values to a temporary buffer first
			Pixel *SDF = new Pixel[SDFWidth*SDFHeight]();
			for(BMSize y = 0; y < SDFHeight; ++y)
			{
				for(BMSize x = 0; x < SDFWidth; ++x)
				{
					// Calculate the actual distance from the dx/dy
					int dist1 = (int)(sqrt((double)SDFGetPoint(Grid1, x, y, SDFWidth, SDFHeight).DistSq()));
					int dist2 = (int)(sqrt((double)SDFGetPoint(Grid2, x, y, SDFWidth, SDFHeight).DistSq()));
					int dist = dist1 - dist2;

					// Clamp
					int c = dist * 3 + 128;
					if(c < 0) c = 0;
					if(c > 255) c = 255;

					// Write to bitmap
					SDF[(y*SDFWidth) + x] = c;
				}
			}

			// Scale bitmap to final size and copy it to the destination buffer
			CopyBitmap(SDF, SDFWidth, SDFHeight, DestBitmap, DestWidth, DestHeight, InsertX, InsertY, InsertWidth, InsertHeight);
			
			delete[] SDF;
		}

		// Done
		delete[] Grid1;
		delete[] Grid2;
		return true;
	}