Advertisement

Desaturation in SDL

Started by January 12, 2005 11:19 PM
21 comments, last by Mastadex 20 years, 1 month ago
	SDL_BlitSurface(orig, NULL, newScr, NULL);
Thats one of the first things I tried, It didnt work. I stuck a break point before that line and i stepped through it in visual studio and the values in newScr do not change to the values that are being passed into the blit function in the orig variable. Im stumped
Advertisement
I thought you are required to lock a screen before you are allowed to do pixel manipulation to it.
Quote:
Original post by Think128
I thought you are required to lock a screen before you are allowed to do pixel manipulation to it.

No - in Windowed mode you can usually get away with it, but if you go fullscreen you'll tend to get 'Memory could not be "read"' type errors. You should, therefore lock a surface (but it will still work sometimes if you don't).

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

Quote:
Original post by Mastadex
SDL_Surface *Desaturate(SDL_Surface *orig)
{
// The Desaturated Image memory location
SDL_Surface *newScr;
newScr = new SDL_Surface;


As far as I know this will not produce a working SDL_surface. You need to use SDL_CreateRGB or SDL_CreateRGBA and basicly just create a new surface the same size as the original otherwise your new surface has no size or surface format.
Evillive2
Oh man I didn't even see that yeah the above poster is right that is a big booboo. . .
Advertisement
Ok thats good to know, although i used the new keyword before and it worked fine.
Quote:
Original post by Mastadex
Ok thats good to know, although i used the new keyword before and it worked fine.


That seems pretty much impossible since using new to create a valid memory space for an SDL_surface struct does not specify the size or bit depth of the surface which are needed to create the actual surface bits that get manipulated by the SDL_BlitSurface function. I imagine you could do all this by hand after calling the new operator but that is what CreateRGBSurface is for.

Evillive2
On a more helpful note regarding the original question I looked into converting RGB values to greyscale and giving "weight" to each r, g, and b value to come up with a way to get a more accurate greyscale image than the average of the 3 values because that will give you the same grey value for too many rgb colors. Here is what I found:

weight of each rgb value:
red = 0.299
green = 0.587
blue = 0.114

to solve for a grey value (grey) from rgb value (pixel):
(note: pixel values should be floats for this conversion to be more accurate)
grey = (pixel.r*0.299f)+(pixel.g*0.587f)+(pixel.b*0.144f)

I tried this for a few 8 bit bitmaps I have and it seems to work pretty well although I am sure there could be more optimizations somewhere.

edit:
This took some reading in the colorspace-faq and some further research into certain standards mentioned in the faq in which I am sure you can find some more info on the subject.

[Edited by - evillive2 on January 16, 2005 12:45:02 AM]
Evillive2
Ok i changed my code and removed the new keyword. here is what i have for the desaturate function:

SDL_Surface *Desaturate(SDL_Surface *orig){	// The Desaturated Image memory location	SDL_Surface *newScr;	// Create a new Surface	newScr = SDL_CreateRGBSurface(SDL_HWSURFACE, orig->w, orig->h, 32, rmask, gmask, bmask, amask);	SDL_LockSurface(newScr);	// 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(orig, 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);		}	}   	// Delete the original Surface	SDL_FreeSurface(orig);	SDL_UnlockSurface(newScr);	return newScr;}


Here are my get pixel and set pixel functions. Im dealing with 32bit images and not palletized images. Now I know i didnt convert these functions right because they crash in the put pixel function.

Uint32 GetPixel(SDL_Surface *surface, int x, int y){    int bpp = surface->format->BytesPerPixel;    // Here p is the address to the pixel we want to retrieve    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;    return *(Uint32 *)p;}// Sets the Pixel Datavoid PutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel){    int bpp = surface->format->BytesPerPixel;    // Here p is the address to the pixel we want to set    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;    *(Uint32 *)p = pixel;}


[Edited by - Mastadex on January 16, 2005 6:22:10 PM]

This topic is closed to new replies.

Advertisement