Peter
Peter

Reputation: 11890

How to change RGB values in SDL surface?

In my application, once I load an image into an SDL_Surface object, I need to go through each RGB value in the image and replace it with another RGB value from a lookup function.

 (rNew, gNew, bNew) = lookup(rCur, gCur, bCur);

It seems surface->pixels gets me the pixels. I would appreciate it if someone can explain to me how to obtain R, G, and B values from the pixel and replace it with the new RGB value.

Upvotes: 1

Views: 6443

Answers (3)

user1944441
user1944441

Reputation:

Use built-in functions SDL_GetRGB and SDL_MapRGB

#include <stdint.h>

/*
...
*/

short int x = 200 ;
short int y = 350 ;

uint32_t pixel = *( ( uint32_t * )screen->pixels + y * screen->w + x ) ;

uint8_t r ;
uint8_t g ;
uint8_t b ;

SDL_GetRGB( pixel, screen->format ,  &r, &g, &b );

screen->format deals with the format so you don't have to.

You can also use SDL_Color instead of writing r,g,b variables separately.

Upvotes: 3

UmNyobe
UmNyobe

Reputation: 22890

First of all you need to lock the surface to safely access the data for modification. Now to manipulate the array you need to know the numbers of bit per pixels, and the alignment of the channels (A, R, G, B). As Photon said if is 32 bits per pixel the array can be RGBARGBA.... if it is 24 the array can be RGBRGB.... (can also be BGR, BGR, blue first)

//i assume the signature of lookup to be
int lookup(Uint8 r, Uint8 g, Uint8 b, Uint8 *rnew, Uint8* gnew, Uint8* bnew);

SDL_LockSurface( surface );

/* Surface is locked */
/* Direct pixel access on surface here */
Uint8 byteincrement  = surface->format->BytesPerPixel;

int position;
for(position = 0; position < surface->w * surface->h* byteincrement; position += byteincrement  )
{
    Uint8* curpixeldata = (Uint8*)surface->data + position;
    /* assuming RGB, you need to know the position of channels otherwise the code is overly complex. for instance, can be BGR */
    Uint8* rdata = curpixeldata +1;
    Uint8* gdata = curpixeldata +2;
    Uint8* bdata = curpixeldata +3;
    /* those pointers point to r, g, b, use it as you want */
    lookup(*rdata, *gdata, *bdata, rdata,gdata,bdata);
}

.
SDL_LockSurface( surface );

Upvotes: -1

Photon
Photon

Reputation: 3222

Depending on the format of the surface, the pixels are arranged as an array in the buffer.
For typical 32 bit surfaces, it is R G B A R G B A
where each component is 8 bit, and every 4 are a pixel

Upvotes: 0

Related Questions