Color conversion algoritgms?

Started by
4 comments, last by DeadXorAlive 17 years, 8 months ago
Hello everyone! OK, I have a red soldier, and I want to make it green (for example). Instead of drawing 2 soldiers for each animation, how can I make it change colors in the game itself? I did a search on this forum and I got a post that linked to this. But, that seemed to be Java code... Does anyone know how to do this in C++? Thanks! Oh, BTW, I'm using SDL. (Note: I tried translating the formula in the Wikipedia page, but I'm not so advanced in math yet. [embarrass] (Either that, or I don't pay attention in class... [lol]))
Advertisement
I don't think a color conversion is what you need. A color conversion converts from one color space to another (RGB->HSV for instance), while you are staying in one (RGB).

You should only have to swap the R and the G values i guess for a simple color swap, or you could specify 2 different colorbuffers along with your vertexbuffer and switch between the two before drawing. If you could use a pixel shader it would be the best way to go, but i only have OpenGL knowledge on this subject, so i can't help you there (with SDL).

Good Luck.

EDIT: btw, the code on the site you linked to was C++, it uses pointers ;)
Check out Lode's computer graphics tutorial, I think you want to check the 'Color and Image Arithmetic' ones. (You might want to check the others too, they are well written imo). Lode also uses SDL in his tutorials, but with his own codebase.

When you do this with SDL, make sure you make a software image, as pixel access with hardware surfaces is very slow. You could also preprocess the images, either store them on disk or at level loading time, to prevent annoying glitches during gameplay. But maybe performance will not be an issue, it depends.

Good luck with the pixel hacking!
Limitz: Oh, oops... [embarrass] But it didn't compile...

Nope, DeadXorAlive, he doesn't use SDL... But anyways, I tried to translate his code to SDL, but I need to know where the RGB values are stored in a SDL_Surface... I tried this:

int t;t = this->player->format->palette->colors->g;this->player->format->palette->colors->g = this->player->format->palette->colors->r;this->player->format->palette->colors->r = t;


But my app crashed. [flaming] Where are they stored? Thanks!
Use these functions to access the RGB values on a surface.

getpixel
SDL_GetRGB
SDL_MapRGB
putpixel
SDL_LockSurface()
SDL_UnlockSurface()

Example usage:
//This function swaps the Red and Green component of a pixel once it//finds a pixel that has the swap color(swapR,swapG,swapB).void SwapRedWithGreen(SDL_Surface* surf,int swapR,int swapG,int swapB){//Convert RGB color to the surface's pixel format(easier/faster comparison)const Uint32 swapcolor = SDL_MapRGB(surf->format,swapR,swapG,swapB);//Lock surface before we mess with the surface's pixels    if ( SDL_MUSTLOCK(surf) ) {        if ( SDL_LockSurface(surf) < 0 ) {            fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());            return;        }    }//Go through all the pixels on the surfacefor(int y =0 ;y < surf->h;y++){for(int x =0;x < surf->w;x++){//Get a pixel from the surfaceUint32 color = getpixel(surf,x,y);Uint8 r,g,b;   if(swapcolor == color){   //OK, we found the color red we needed to swap out and   //will try to replace it with green.   //Get RGB components of the surface   SDL_GetRGB(color,surf->format,&r,&g,&b);   //Swap color components(red and green) and map back to pixel format   color = SDL_MapRGB(surf->format,g,r,b);   //Replace with new color   putpixel(surf,x,y,color);   }}}//Unlock (if necessary)    if ( SDL_MUSTLOCK(surf) ) {        SDL_UnlockSurface(surf);    }}

Good Luck.
0xa0000000
Quote:Original post by Kixdemp
Limitz: Oh, oops... [embarrass] But it didn't compile...

Nope, DeadXorAlive, he doesn't use SDL... But anyways, I tried to translate his code to SDL, but I need to know where the RGB values are stored in a SDL_Surface... I tried this:

*** Source Snippet Removed ***

But my app crashed. [flaming] Where are they stored? Thanks!


Yes it looks like there is no SDL because it is abstracted in QuickCG, his library which does use SDL. Download that one and check QuickCG.cpp for all sorts of handy SDL stuff.

About getting the RGB values in SDL, they are stored in a pointer called pixels, a member of the SDL_Surface struct. It's a bit tricky, you'll have to know to format. Check out SDL_Surface and SDL_PixelFormat. More convenient are SDL_MapRGB and SDL_GetRGB. There are also SDL_MapRGBA and SDL_GetRGBA.

The way it works is that pixels* is a pointer to a blob of data, which contains all the pixels in the surface. Now each pixel can be described by one, three or four bytes, depending on the format (palette, RGB, RGBA). Thats why the SDL_Map* and SDL_Get* functions need to know the format, which is contained in a pointer called format, also member of SDL_Surface struct.
Now to iterate over the pixels of a surface, you'll also need to know the scanline, it's in the pitch member (not a pointer) of SDL_Surface. This sounds a bit weird perhaps, but the scanline represents the width of the surface data, and can be more than SDL_Surface->w, don't ask me why.

Here is an example. (warning: I just come up with this, not tested and not meant to be most efficient):
 // ugly stuff:Uint8  r, g, b;Uint32 color;for ( Uint8* pixPtr, int x = 0; x < image->w; ++x){    for (int y = 0; y < image->h; ++y)    {        pixPtr = (Uint8*) image->pixels + y * image->pitch + x * image->format->BytesPerPixel;        color = *(Uint32 *)pixPtr;    	SDL_GetRGB(color, image->format, &r, &g, &b);        // do something with r,g,b    	color = SDL_MapRGB(image->format, r, g, b);    	*(Uint32 *)pixPtr = color;    }}


Hope this helps.

EDIT: I'm too slow! - Jack Sotac's example is better

This topic is closed to new replies.

Advertisement