2011-07-27 11 views
7

Tengo un pequeño problema: no puedo modificar los píxeles de una pantalla SDL.¿Cómo puedo modificar los píxeles usando SDL?

Específicamente, el siguiente código no funciona.

Uint32 * pixels = (Uint32 *) screen -> pixels; 
screen -> pixels = pixels; 

Esto compila, pero no muestra nada. ¿Qué me estoy perdiendo?

+0

im no cambiar cualquier pixel particular en este caso. simplemente estoy copiando todo e intentando copiarlo todo nuevamente. Y por formato, ¿qué quieres decir? – nory

+4

¿Se da cuenta de que su código no hace nada? 'pantalla-> píxeles = pantalla-> píxeles;'. –

+0

por supuesto.Solo estoy jugando, conociendo la sintaxis y cosas – nory

Respuesta

-2

No debe modificar el contenido de la estructura SDL_Surface. Si desea copiar los píxeles, debe malloc() un poco de memoria y luego memcpy() los píxeles.

+0

pero mi objetivo es perder el tiempo con los píxeles – nory

+0

¿Puedes aclarar _por qué ** no debemos modificar ** el contenido de la SDL_Surface? ¿Podría/podría conducir a errores/comportamiento inesperado? – snapfractalpop

+0

@snapfractalpop: del archivo 'SDL_video.h':" Esta estructura [SDL_Surface] debe tratarse como de solo lectura, excepto para 'píxeles' [...] ". Si no cumple, está rompiendo la estructura invariante y la biblioteca no funcionará correctamente. – rodrigo

18

Tenía las siguientes funciones para configurar píxeles en una SDL_Surface. Hay dos versiones para superficies de 32 bits, 24 bits, 16 bits y 8 bits. Si solo quiere establecer un solo píxel, usaría las versiones normales. Pero si desea establecer un conjunto de píxeles, primero bloquea la superficie, luego utiliza la versión nolock (llamada así porque no bloquea la superficie) y luego se desbloquea. De esta forma, no estás bloqueando y desbloqueando la superficie repetidamente, lo que se supone que es una operación costosa, aunque no creo que alguna vez lo haya probado realmente.

void PutPixel32_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint32)); 
    *((Uint32*)pixel) = color; 
} 

void PutPixel24_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3); 
#if SDL_BYTEORDER == SDL_BIG_ENDIAN 
    pixel[0] = (color >> 24) & 0xFF; 
    pixel[1] = (color >> 16) & 0xFF; 
    pixel[2] = (color >> 8) & 0xFF; 
#else 
    pixel[0] = color & 0xFF; 
    pixel[1] = (color >> 8) & 0xFF; 
    pixel[2] = (color >> 16) & 0xFF; 
#endif 
} 

void PutPixel16_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint16)); 
    *((Uint16*)pixel) = color & 0xFFFF; 
} 

void PutPixel8_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint8)); 
    *pixel = color & 0xFF; 
} 

void PutPixel32(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel32_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 

void PutPixel24(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel24_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
} 

void PutPixel16(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel16_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 

void PutPixel8(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel8_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 
+2

Sé que esta es una vieja pregunta/respuesta, pero me gustaría señalar que el programa se bloqueará si intenta tomar un píxel que está fuera de los límites de la superficie. Por ejemplo, tratar de obtener un píxel en una coordenada X de 64 desde una superficie de ancho 64 se bloqueará porque el último píxel está en 63. – TyCobb

2

La manipulación de los contenidos de screen->pixels modificará píxeles, con un par de advertencias.

En primer lugar, como ha mostrado en el fragmento de código, tenga en cuenta que screen->pixels es un puntero a los datos de píxeles de la superficie. Se accede a los datos de píxel como una matriz lineal desde ese puntero en función del ancho de la superficie (surface->pitch) y el tamaño del píxel en bytes. El tamaño de píxel (también conocido como profundidad) se establece durante la inicialización, usando SDL_SetVideoMode() y se puede encontrar en screen->format->BytesPerPixel.

Es posible que sea necesario bloquear la superficie antes de realizar cambios.

Además, dependiendo de las opciones que pasaron a SDL_SetVideoMode(), también puede necesitar llamar al SDL_Flip() para mostrar los cambios que ha realizado.

Se puede encontrar un ejemplo de manipulación de píxeles here.


Como se ha señalado en los comentarios, el código que aparece en la pregunta no es en realidad va a hacer nada visible, ya que no se están realizando cambios a los datos de píxeles.

1

Adición de una variante SDL2 manipulación de píxeles no sobre una superficie, sino en un procesador (y que no se bloquea si se intenta manipular píxeles fuera de la pantalla, a diferencia de las respuestas anteriores)

void putPixelRGB(SDL_Renderer* renderer, int x, int y, unsigned char r, unsigned char g, unsigned char b) 
{ 
    SDL_SetRenderDrawColor(renderer, (Uint8)r, (Uint8)g, (Uint8)b, 255); 
    SDL_RenderDrawPoint(renderer, x, y); 
} 
-1

¿Por qué cambiar un pixel ?

crea una nueva superficie & un Rect

// CÓDIGO ------------>

SDL_Surface *screen, *PIXEL = NULL; 

SDL_Rect PIXELRect; 
PIXELRect.h=5; 
PIXELRect.w=5; 
PIXELRect.x=100; 
PIXELRect.y=100; 

screen = SDL_SetVideoMode(640, 468, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT); 

while(running){ 
SDL_FillRect(screen, &PIXELRect, (#color)); 
} 
Cuestiones relacionadas