[C con Clase] SDL operaciones bitwise y punteros.

David xdrtas en yahoo.es
Vie Feb 25 13:24:54 CET 2011


Hola, buenas a todos, estoy siguiendo el tutorial de SDL: Tutorial de libSDL para la programación devideojuegosAntonio García Alba
Y me he encontrado con varias incógnitas, pero antes les explico mi entorno:Ubuntu 10.10 32 bitsIDE: NetBeans 6.9 con g++ para compilar las aplicaciones.Procesador Intel -> Little-endian.
El objetivo de esta aplicación es seleccionar un pixel de una superficie y cambiarle el color, aunque el código no lo puse completo para no extender excesivamente el correo, si alguien lo necesita, me lo indica y con mucho gusto se lo envío en un archivo comprimido.El código funciona correctamente y hace lo que se pide, por ese lado no hay problema.
enum colores {R,G,B}
void PutPixel(SDL_Surface *superficie, int x, int y, Uint32 pixel){    //Obtener la profundidad del
 color...    int bpp = superficie->format->BytesPerPixel;
    //Obtener la posición
 del píxel a sustituir...    Uint8 *p = (Uint8 *)superficie->pixels + y * superficie->pitch + x * bpp;
    //Según sea la profundidad de color...    switch (bpp)    {        case 1: //8 bits (256
 colores)...            *p = pixel;            break;
        case 2: //16 bits (65536 colores o HighColor)...            *(Uint16 *)p = pixel;      
      break;
        case 3: //24 bits (True Color)...            if(SDL_BYTEORDER == SDL_BIG_ENDIAN)            {                //Calcular cada uno de los componentes del
 color...                //3 Bytes, 3 posiciones...                p[R] = (pixel >> 16) & 0xFF;                p[G] = (pixel >>  8) & 0xFF;                p[B] = pixel & 0xFF;            }            else            {                p[R] = pixel & 0xFF;                p[G] = (pixel >>  8) & 0xFF;                p[B] = (pixel >> 16) & 0xFF;            }            break;
        case 4: //32 bits (True color + Alpha)...          
  *(Uint32 *)p = pixel;            break;    }}
Esta función cuenta con la siguiente definición Uint8 *pEsto quiere decir que el puntero "p" de 4 bytes o 32 bits va a apuntar, de momento, a variables que sean de tipo Uint8 de 1 byte  o 8 bits de tamaño, hasta aquí estamos claros.
Mi primera pregunta es:¿Cómo se interpreta la siguiente sentencia?: *(Uint16 *)p = pixel.La primera parte lo entiendo, si el sistema trabaja con una profundidad de color de 16 bits o 2 bytes entonces se hace un cast a *p para que apunte a variables del tipo Uint16 y así *p en vez de usar un byte o 8 bits para apuntar a el valor, ahora podrá apuntar a variables de 2 bytes o 16 bits, pero qué pasa con el otro operador de indirección "*" el que está de rojo, *(Uint16 *)p, no entiendo a que apunta aquí.
Mi segunda pregunta es sobre el siguiente bloque:
p[R] = pixel & 0xFF;p[G] = (pixel >>  8) & 0xFF;p[B] = (pixel >> 16) & 0xFF;
Tratándose de punteros, sé que se pueden hacer cosas como esa, pero cómo sabe el compilador que p[1] y p[2], (p[G] y p[B] respectivamente) no están ocupadas con información de otra aplicación, no es esto peligroso?, manipular direcciones de memoria que no se han declarado? Sé que declare *p, pero no declaré p[1], ni p[2], ni p[..n].p[R], p[G], p[B], son de 32 bits o 4 bytes cada uno? O p[R], p[G], p[B] representa cada uno un byte de los 4 que tiene p. Me explico con un esquema:
Recordemos que *p es de 4 bytes y para el caso de profundidad de color de 24 bits no se ha realizado ningún casting a *p.
        
 [------0------]  [------1------]  [------2------]   [-----3------][*p-]= 0000 0000 - 0000 0000 - 0000 0000 - 0000 0000 --> 4 bytes o 32 bits.             RED        GREEN        BLUE    -  SIN USOp[R]= 0000 0000 - 0000 0000 - 0000 0000 - 0000 0000 --> 4 bytes o 32 bits.p[G]= 0000 0000 - 0000 0000 - 0000 0000 - 0000 0000 --> 4 bytes o 32 bits.p[B]= 0000 0000 - 0000 0000 - 0000 0000 - 0000 0000 --> 4 bytes o 32 bits.
O
p[R]= 0000
 0000p[G]= 0000 0000p[B]= 0000 0000

Mi tercera pregunta viene en relación a la siguiente función:
Uint32 GetPixel(SDL_Surface *superficie, int x, int y){    //Obtener la profundidad de color...    int bpp = superficie->format->BytesPerPixel;
    //Obtener la posición del píxel a consultar...    Uint8 *p = (Uint8 *)superficie->pixels + y * superficie->pitch + x *
 bpp;
  
  switch (bpp)    {        case 1:            return *p;            break;                    case 2:            return *(Uint16 *)p;            break;
        case 3:            if(SDL_BYTEORDER == SDL_BIG_ENDIAN)                return p[R] << 16 | p[G] << 8 | p[B];            else                return p[R] | p[G] << 8 | p[B] <<
 16;
            break;
        case 4:            return *(Uint32 *)p;            break;
        default:            return 0;            break;    }}
El siguiente "return " no lo entiendo bien, alguien me podría explicar a nivel de bits que hace lo siguiente:
return p[R] | p[G] << 8 | p[B] << 16;
Porque si p[R], p[G] y p[B] son cada uno de un Byte o 8 bits entonces no tiene sentido el desplazamiento de bits. O, lo que hace es que: escribe los 8 bits del rojo, luego que desplace 8 bits el verde y y escriba el valor en bits del verde y por último que desplace 16 bits
 el azul para que el return devuelva los 24 bits como [B, G, R], o sea, una concatenación de bits.Aunque lo que yo veo es que se está usando un OR entre los tres.
He tratado de explicarme lo mejor posible, sin embargo, cualquier pregunta o aclaratoria sobre los planteamientos serán bienvenidas.
Un cordial
 saludo,David Lastra.
http://xdrtas.coolpage.biz/

http://xdrtas.blogspot.com/


      
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20110225/898d3558/attachment.html>


Más información sobre la lista de distribución Cconclase