Advertisement

Desaturation in SDL

Started by January 12, 2005 11:19 PM
21 comments, last by Mastadex 20 years, 1 month ago
Is there a way to take an image in SDL and slowly desature the color? much like windowsXP does when you attempt to log off or shutdown your PC...
Okay the closest I can think of is this. . .

SDL_Surface * MainScreen;//Setup MainScreenSDL_Surface * Black = SDL_CreateRGBSurface(MainScreen->flags, MainScreen->w, MainScreen->h, MainScreen->format->BitsPerPixel, MainScreen->format->Rmask, MainScreen->format->Gmask, MainScreen->format->Bmask, MainScreen->format->Amask);int Alpha(255);bool Done(false);while(!Done){//Event HandlingSDL_SetAlpha(Black, SDL_SRCALPHA, Alpha);Alpha--;SDL_BlitSurface(Black, NULL, MainScreen, NULL);SDL_Flip(MainScreen);}
Advertisement
Quote:
Original post by ImperfectFreak
Okay the closest I can think of is this. . .

*** Source Snippet Removed ***


Surely that would fade the image rather than desaturate it?

What I'd do is to create a copy of the surface that I want to desaturate then fully desaturate it by scanning each pixel, adding up the RGB of each and dividing by 3 (then resetting the pixel). So:

SDL_Surface *surfaceToFade;for (int x=0; x<surfaceToFade->w; ++x) {for (int y=0; y<surfaceToFade->h; ++y) {int colour = getPixel(surfaceToFade,x,y);int b = colour & 0xFF;colour = colour >> 8;int g = colour & 0xFF;colour = colour >> 8;int r = colour & 0xFF;int brightness = (r+b+g)/3;colour = brightness | (brightness << 8) | (brightness << 16);setPixel(surfaceToFade,x,y);}}


(getPixel and setPixel routines from SDL documentation).

Now what I'd do is have a for loop and do a linear interpolation between 0 and 1 and between the two images.

Evidently, getPixel and setPixel are slow, ideally you would set up a pointer to the pixel you're changing and increment that by the surface->format->BytesPerPixel of the *surfaceToFade.

Oh, and the way I'm ripping out colour information is for 24 bit surfaces. It's not meant to be rock steady code, just a demo of what I mean [grin]

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

Yes you could do that, but that would be very slow. . .
Quote:
Original post by ImperfectFreak
Yes you could do that, but that would be very slow. . .


Not too bad at lowish resolutions (640x480, say) but if you're going much higher then yes, it is very slow indeed - even if you just set the pointers once and add an increment each time.
Actually, it would be better to just build the unsaturated version once, then overlay it on top of the screen with 0 alpha and slowly fade it in.

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

Cool. Well my game's resolution is 800x600x32 so its still small compared to what people have thier desktop res at. THe image that im trying to desaturate is never the same, its basically going to be the game itself when you try to go into the in-game menu.

would it be worth continuing this discussion if this method is proven to be increadably slow?
Advertisement
Quote:
Original post by Mastadex
Cool. Well my game's resolution is 800x600x32 so its still small compared to what people have thier desktop res at. THe image that im trying to desaturate is never the same, its basically going to be the game itself when you try to go into the in-game menu.

would it be worth continuing this discussion if this method is proven to be increadably slow?


My raycaster, which has to do all sorts of texture lookups, maths (floating point) and the like runs at ~15FPS at that size. That's a fifteenth of a second per frame. If you can wait a fifteenth of a second before the screen starts to fade, by all means use this method!

So basically...

1. Create two new surfaces - one for the current screen image and one for the desaturated image.
2. Copy the screen image into both via a blit.
3. Scan through each pixel of your "desaturated" buffer and desaturate it.
4. Set the alpha of your desaturated image to be "fully transparent"
5. In a "fadeout loop": blit the preserved screen then the desaturated image. Increase the opacity of the desaturated image until it's fully opaque.

This sounds like a groovy idea - I'm going to try it myself and see what sort of results I get.

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

What library are SetPixel and GetPixel Located because im getting errors that they are not found
They are in the SDL Documentation, yeah and if it is just go get into the menu then go for it, do it the good way. . .
Here is my Desaturate function that I wrote. THe problem im having is that the Blit does want to work when i hope over the original screen to the new surface...any help is appreciated.

SDL_Surface *Desaturate(SDL_Surface *orig){	// The Desaturated Image memory location	SDL_Surface *newScr;	newScr = new SDL_Surface;	// Blit the current screen onto the newly created copy	SDL_Rect dest;	dest.x = 0;	dest.y = 0;	SDL_BlitSurface(orig, NULL, newScr, &dest); // Here is the problem	// Desaturate the new Image	for (int x = 0; x < newScr->w; ++x)	{		for (int y = 0; y < newScr->h; ++y)		{			// Read the pixel information for the current image			int color = GetPixel(newScr, x, y);			// Takes the Blue Channel			int b = color & 0xFF;			color = color >> 8;			// Takes the green Channel			int g = color & 0xFF;			color = color >> 8;			// Takes the Red Channel			int r = color & 0xFF;						// Take the average of the three channels			int brightness = (r + b + g) / 3;			// Desaturation of the current pixel and write it to image			color = brightness | (brightness << 8) | (brightness << 16);			PutPixel(newScr, x, y, color);		}	}	return newScr;}

This topic is closed to new replies.

Advertisement