SDL - Trabajar con transparencias por índice de paleta

Tratamos sobre el manejo de APIs frecuentemente utilizadas en el desarrollo de videojuegos, como SDL, pygame o SFML.

SDL - Trabajar con transparencias por índice de paleta

Notapor delaPipol » Mar Ago 07, 2007 1:03 pm

Hola, que tal! Me llamo Fran y estaba aprendiendo un poco de SDL para un proyecto libre recientemente comenzado. El proyecto se basa en simular el funcionamiento de otro y por ello requiere algunos aspectos un tanto extravagantes como el siguiente, que no sé si alguien se lo habrá encontrado en alguna ocasión:

A la hora de trabajar con sprites en este proyecto se necesita tratar con imágenes de 8 bit, por tanto utiliza un bloque de paleta y luego un bloque de mapa de bits haciendo referencia a esos valores del índice de paleta (a diferencia de las de color verdadero, que no tienen esa paleta sino que en el propio mapa de bits se define el valor de color por cada "píxel").

Así pues, en este caso el formato de píxel es de 8 bit y se puede tratar con la paleta. El problema viene con la transparencia. SDL trata la transparencia por un valor de color (ColorKey) y los archivos de sprite que necesitan leerse tienen definida la transparencia por el índice de paleta.

En principio con leer el valor de color de ese índice 0 sería suficiente, con algo así como surface->format->palette->colors[0] si no me equivoco.

El problema viene cuando en esa misma paleta encuentras que por ejemplo el color número 0 de la paleta que será el transparente vale 255,0,255 y el número 43 y el 129 (por decir algunos) también tienen como valor 255,0,255. Eso supone que esos colores también se vean transparentes, por las características del propio SDL.

La solución al problema de colores duplicados sería aplicar por ejemplo sumarle +1 al componente azul, que es el que menos diferencia percibirán nuestros ojos surface->format->palette->colors[43].b + 1 y si ya vale 255 como en este ejemplo entonces - 1 (quedando 255,0,254). Todo ello se podría meter en un for para que recorriera la paleta entera comparando si el valor RGB del índice 0 coincide con el resto de los 256 colores.

¿Alguien se ha encontrado con este caso? He mirado en listas de correo y demás y no he encontrado ninguna situación similar.

Un saludo y suerte!
Avatar de Usuario
delaPipol
 
Mensajes: 3
Registrado: Mié Jul 18, 2007 7:59 am
Ubicación: Barcelona

Notapor rcaf » Mar Ago 07, 2007 8:18 pm

Hola:

Hace varios años atrás trabaje con modos de video a 8 Bits por Pixel, en Allegro y SDL.

Creo que la solución para estos típicos problemas es que todas las imágenes que van a formar una escena, compartan la misma paleta de colores.

Solía copiar el fondo y todas los imágenes que usaría en una escena en una imagen nueva con formato RGB (con un tamaño adecuado para que cupieran todas). Luego cuando ya tenía todas las imágenes listas le cambiaba el formato a la imagen a modo indexado (8 bits).

En aquellos años ocupé Paint Shop Pro para hacer esta tarea, y también para obtener la paleta de colores en un archivo separado.

Espero que este método te ayude a solucionar tus problemas. Creo que es mejor que estar haciendo códigos extraños para arreglar los colores.

Saludos!
Roberto Albornoz Figueroa
Mi Blog
Wiki
Avatar de Usuario
rcaf
 
Mensajes: 71
Registrado: Jue Ago 10, 2006 4:35 am
Ubicación: Concepción, Octava Región. Chile

¿posible solución?

Notapor hugoruscitti » Mié Ago 08, 2007 5:43 pm

Hola Fran, la verdad es que nunca me encontré ante un problema similar y
por ello intenté "reconstruir" el problema que tienes e intenté buscarle una
solución (y creo que la encontré).

En el siguiente archivo están las pruebas que realicé:

http://www.losersjuegos.com.ar/incoming/descargas/20070808/transparencias_8bits.tar.gz

Cuando extraigas el contenido del archivo encontrarás dos directorios, uno se
llama "problema", en donde se almacena una imagen que tiene el problema que nos
indicas, a saber:

La imagen original se encuentra en 8 bits, por lo tanto cada "pixel" de la
imagen es, en realidad, un número que identifica la tonalidad de color de ese
pixel. Esta imagen almacena una paleta de colores también.

El problema de este ejemplo llega al querer indicarle a SDL que nuestro color de
transparencia será el color de índice 0 en la paleta. SDL nos permite definir el
color de transparencia mediante la función SDL_SetColorKey, aunque esta función
admite como parámetros las componentes del color que buscamos "hacer
transparente", en lugar de su posición el la paleta de colores.

Lamentablemente, esta imagen que he utilizado como prueba, tiene repetidos
algunos colores:

Imagen

el color de índice 0 en la paleta es idéntico al color ubicado en la posición
63, 64. Todos estos colores tienen las componentes (r=255, g=255, b=255), por lo
tanto si construyes una rutina como la siguiente, buscando definir como
"transparente" el color de índice 0:

Código: Seleccionar todo
indice_0 = tmp->format->palette->colors[0];
colorkey = SDL_MapRGB(ima->format, indice_0.r, indice_0.g, indice_0.b);


SDL hará transparentes todos los píxeles cuyas componentes sean idénticas al
color de índice 0 de tu paleta. Para este ejemplo, obtendrías algo como lo
siguiente:

Imagen


he buscado en la documentación de SDL y no encontré una función similar a
SDL_SetColorKey para imágenes de 8 bits, tal vez exista, pero no la he
encontrado. En su lugar escribí una rutina que podría servirte para adaptar
estas imágenes al juego y poder asignarles un color de transparencia, siguiendo
los procedimientos que nos indicas en tu primer mensajes, es decir, alterar
aquellos colores que tiene la mismas componentes de color que el color 0 de la
paleta.

Encontrarás esta rutina de código en el directorio "posible_solucion" del
archivo que cité anteriormente.

Y en pantalla quedaría de la siguiente manera:

Imagen

Saludos y buena suerte con el juego.

edito: utilicé incorrectamente la etiqueta "code" en la primer
publicación...
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina

Notapor Geo » Mié Ago 08, 2007 10:18 pm

No he revisado la propuesta de Hugo (que me parece da muy buen resultado), lo otro que se me ocurre es, reescribir la función SDL_Blit para el caso de superficies de 8 bits, de manera que tome la transparencia del primer índice en la paleta y no de la estructura SDL_BlitInfo.

No estoy seguro, pero me parece que el código se encuentra en el archivo SDL_blit_0.c, en la función BlitBto1Key

En lugar de esto:
Código: Seleccionar todo
static void BlitBto1Key(SDL_BlitInfo *info) {
// ...
  Uint32 ckey = info->src->colorkey;
// ...
  Uint8 *palmap = info->table;
// ...
}

algo como esto:
Código: Seleccionar todo
static void BlitBto1Key(SDL_BlitInfo *info) {
// ...
  Uint8 *palmap = info->table;
  Uint32 ckey = palmap[ 0 ];
  // o por si alguien se queja de pasar un Uint8 a un Uint32 :P
  // Uint32 ckey = 0x000f & palmap[ 0 ];
// ...
}

---------------------
Edit:
nop, no sería así, sería modificar esta parte de la misma función:
Código: Seleccionar todo
if ( palmap ) {
      while ( height-- ) {
              Uint8  byte = 0, bit;
             for ( c=0; c<width; ++c ) {
            if ( (c&7) == 0 ) {
               byte = *src++;
            }
            bit = (byte&0x80)>>7;
            if ( bit != ckey ) {
              *dst = palmap[bit];
            }
            dst++;
            byte <<= 1;
         }
         src += srcskip;
         dst += dstskip;
      }


Por cierto delaPipol, ¡ánimo con ese proyecto :)! Ojalá pueda participar de alguna forma, lamentablemente estoy ahorcado de tiempo para escribir código :P.
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor delaPipol » Mar Ago 14, 2007 8:13 am

Impresionante, era exactamente lo que decía Hugo :D. He probado el código y funciona a la perfección. Sobre el color que se comenta en los comentarios de sumar y restar 1 en vez de 8 al color azul a 32 bits funciona, tal y como se sospechaba. Parece que a 16 bits hace la distinción de colores cada 4 tonos (edito: según cierta documentación sigue el esquema RGB565) y por tanto el incremento o decremento de 8 lo hace seguro :D. En el código creaba una surface de 8 bits de profundidad donde trabajar luego con la surface de la imagen y tampoco hubo ningún problema. Quien quiera ojear el resultado que acceda por Subversion a http://easyrpg.svn.sourceforge.net/view ... nk/player/ (este es el enlace a la interfaz web viewc)

rcaf escribió:Creo que la solución para estos típicos problemas es que todas las imágenes que van a formar una escena, compartan la misma paleta de colores.
Así es, con tener la paleta en condiciones con un colorkey común se solucionaría sin tanta complicación, pero como dije el problema es que se intenta simular otro sistema existente donde las imágenes ya vienen creadas. De hecho esta parte del proyecto intenta ser una especie de "emulador" como ScummVM pero en este caso de juegos creados con RPG Maker 2000 y por ello la necesidad explícita de adaptarse a sus peculiaridades.

Geo escribió:No he revisado la propuesta de Hugo (que me parece da muy buen resultado), lo otro que se me ocurre es, reescribir la función SDL_Blit para el caso de superficies de 8 bits, de manera que tome la transparencia del primer índice en la paleta y no de la estructura SDL_BlitInfo.
Más adelante se podría reabrir el bug para hacer más eficiente la asignación de la transparencia, de todas formas se podría mandar un parche (es que yo ya me traumé de darle tantas vueltas al mismo bug :oops: y me gustaría centrarme en avanzar la lectura de los mapeados para darle vitalidad al proyecto).
Imagen
Geo escribió:Por cierto delaPipol, ¡ánimo con ese proyecto :)! Ojalá pueda participar de alguna forma, lamentablemente estoy ahorcado de tiempo para escribir código :P.
Muchísimas gracias :D, ya sabes que cuando quieras tener escritura en svn en el proyecto hazlo saber ;). Muchas personas que se interesaron por RPG Maker en el pasado ahora lo han hecho con la programación, y la estrategia de este proyecto es poder atraer más "cantera" de talentos al mundo del software libre, donde podrían portar sus proyectos a más sistemas y plataformas :wink:.


Pues muchísimas gracias Hugo por una explicación tan clara y didáctica, ojalá resulte útil a muchas más personas esta solución. Ya conseguí anteriormente por mi cuenta hacer la primera parte, pero luego ni me imaginaría que a 16 bit daría problemas sumándole tan solo 1 luego. Agradezco enormemente el apoyo, espero estar al nivel de poder responder cuestiones por esta comunidad. ¡Saludos! ;)
Avatar de Usuario
delaPipol
 
Mensajes: 3
Registrado: Mié Jul 18, 2007 7:59 am
Ubicación: Barcelona


Volver a Sobre las bibliotecas multimedia

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron