PDA

Ver la versión completa : Voltear imagenes en SDL



gade
19/03/2006, 22:43
Buenas ! alquien conoce, tiene alguna libreria / codigo, para voltear imagenes, efecto espejo o como quieran llamarlo. Por mucho que busco no encuentro nada y me paraece muy raro pues me parece algo comun en cualquier juego, la mayoria parece que recurren a opengl, o a incluir directamente los graficos volteados. Ninguna me parece una buena opcion, pues eso haber si me ayudais, gracias!.

Uncanny
19/03/2006, 23:10
Si lo que quieres es obtener el "reflejo" de una superficie, a modo de espejo, puedes mirar esto (http://www.gamedev.net/community/forums/topic.asp?topic_id=308570&whichpage=1&#1968185). Si lo que quieres es rotar a diferentes angulos las superficies tienes las funciones de la librería auxiliar SDL_gfx (http://www.ferzkopp.net/Software/SDL_gfx-2.0/).

gade
19/03/2006, 23:15
Por fin!!!!! =) GRACIAS! era el primer ejemplo, lo sdl_gfx solo permite rotar, ***** por mucho que he buscado y no habia encontrado nada!! graciasssss[Ahhh]

Uncanny
19/03/2006, 23:35
Me alegro :)

De todas formas no eres el primero que pregunta por una función así (con una busqueda en los foros verás que ya di antes la misma respuesta), siempre puedes currarte tu propia función claro, pero creo que puede ser una función util que no parece incluir ninguna librería auxiliar para SDL de las que conozco.

Arcnor
20/03/2006, 02:19
Hombre, si necesitas velocidad a tope, yo creo que setpixel y getpixel incluyen una sobrecarga (o "overhead", como dirían nuestros amigos yankies [wei5]) que se puede evitar tratando directamente el buffer. Yo lo he hecho en alguna ocasión (acceder directamente al buffer y modificarlo. En este caso sería hacer un "for" e ir sustituyendo, nada complicado) pero el problema está en si debes usar mas de una profundidad de color, en cuyo caso ya estarías igual que con get y setpixel, usando case y demás :).

Sólo una anotación, no me estoy metiendo con tu respuesta, maestro Uncanny ;)

Uncanny
20/03/2006, 02:29
Sólo una anotación, no me estoy metiendo con tu respuesta, maestro Uncanny ;)Ni que fuera el gran Yoda xDDD

Faltaría más que dieras tu opinión, de hecho es una de las formas que tenemos de aprender, gracias a los conocimientos e ideas de otros :D

BuD
20/03/2006, 04:14
Siempre puedes copiar el codigo que hay en esta web:
http://www.gamedev.net/community/forums/topic.asp?topic_id=308570&whichpage=1&#1968185

Arcnor
20/03/2006, 04:27
BuD, justo ese es el link que dio antes Uncanny :loco:

BuD
20/03/2006, 04:51
BuD, justo ese es el link que dio antes Uncanny :loco:Juas, pues es cierto. No lo habia visto.:rolleyes:
Lo que pasa es que he hechado un vistazo rapido a ver si alguien habia dado este link, pero como Uncanny ha metido ese link en una palabra de una frase, pues ni me habia dao cuenta. :D

Damizean
20/03/2006, 10:56
Precalcula las imagenes volteadas y ya está :o

Arcnor
20/03/2006, 17:02
Buenas ! alquien conoce, tiene alguna libreria / codigo, para voltear imagenes, efecto espejo o como quieran llamarlo. Por mucho que busco no encuentro nada y me paraece muy raro pues me parece algo comun en cualquier juego, la mayoria parece que recurren a opengl, o a incluir directamente los graficos volteados. Ninguna me parece una buena opcion, pues eso haber si me ayudais, gracias!.

A ver si leemos un poco más ;)

Puck2099
21/03/2006, 01:02
¿Necesitas una función muy optimizada? Si te vale algo poco optimizado (pero capaz de dar 60 fps en el Lady Killer), dímelo y te pego unas funciones que me curré a partir de varios ejemplos que posteo Uncanny.

Saludos

gade
21/03/2006, 01:43
¿Necesitas una función muy optimizada? Si te vale algo poco optimizado (pero capaz de dar 60 fps en el Lady Killer), dímelo y te pego unas funciones que me curré a partir de varios ejemplos que posteo Uncanny.

Saludos

Pues si Puck la verdad me vendrian genial, cuantos mas ejemplos mejor!, todavia no he heco pruebas porque estoy hasta los co**** de examnes y tal, haber si esta noche me pongo:rolleyes:. Quizas dentro de 3-4 dias suelte un binario para linux de lo poco que tengo hecho, nuse espero que no se me complique todo!. gracias!

Puck2099
21/03/2006, 01:56
Aviso, no son optimizadas, así que no me llaméis chapucero ;)

Por cierto, sé que varios parámetros son inútiles, pero está hecha de forma que sea "más o menos" compatible con el SDK oficial de la GP32, para ahorrarme trabajo cuando porté el Lady Killer a las SDL (sí, soy un vago :D ):



void setpixel(SDL_Surface *screen, int x, int y, Uint32 newcolor )
{
Uint8 *ubuff8;
Uint16 *ubuff16;
Uint32 *ubuff32;
Uint32 color = newcolor;
char c1, c2, c3;

/* Lock the screen, if needed */
if(SDL_MUSTLOCK(screen))
{
if(SDL_LockSurface(screen) < 0)
return;
}

/* How we draw the pixel depends on the bitdepth */
switch(screen->format->BytesPerPixel)
{
case 1:
ubuff8 = (Uint8*) screen->pixels;
ubuff8 += (y * screen->pitch) + x;
*ubuff8 = (Uint8) color;
break;

case 2:
ubuff8 = (Uint8*) screen->pixels;
ubuff8 += (y * screen->pitch) + (x*2);
ubuff16 = (Uint16*) ubuff8;
*ubuff16 = (Uint16) color;
break;

case 3:
ubuff8 = (Uint8*) screen->pixels;
ubuff8 += (y * screen->pitch) + (x*3);

if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {
c1 = (color & 0xFF0000) >> 16;
c2 = (color & 0x00FF00) >> 8;
c3 = (color & 0x0000FF);
} else {
c3 = (color & 0xFF0000) >> 16;
c2 = (color & 0x00FF00) >> 8;
c1 = (color & 0x0000FF);
}

ubuff8[0] = c3;
ubuff8[1] = c2;
ubuff8[2] = c1;
break;

case 4:
ubuff8 = (Uint8*) screen->pixels;
ubuff8 += (y*screen->pitch) + (x*4);
ubuff32 = (Uint32*)ubuff8;
*ubuff32 = color;
break;

default:
fprintf(stderr, "Error: Unknown bitdepth!\n");
}

/* Unlock the screen if needed */
if(SDL_MUSTLOCK(screen)) {
SDL_UnlockSurface(screen);
}
}

Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp) {
case 1:
return *p;

case 2:
return *(Uint16 *)p;

case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;

case 4:
return *(Uint32 *)p;

default:
return 0; /* shouldn't happen, but avoids warnings */
}
}

int GpTransUDBlt (int * nulo1, int nulo2[2], int x, int y, int w, int h, SDL_Surface * img, int x2, int y2, int imgw, int imgh, unsigned char color) {
int i;
int j;

SDL_Surface* newimg = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, img->format->BitsPerPixel, img->format->Rmask, img->format->Gmask, img->format->Bmask, img->format->Amask);
for( j = 0; j < h; j++ ) {
for( i = 0; i < w; i++ ) {
setpixel( newimg, i, j, getpixel( img, i+x2, h+y2-1-j) );
}
}
SDL_SetColorKey (newimg, SDL_SRCCOLORKEY, SDL_MapRGB(newimg->format, 248, 64, 248));
SDL_Rect dest;
dest.x = x;
dest.y = y;
SDL_Rect src;
src.x = 0;
src.y = 0;
src.w = w;
src.h = h;
SDL_BlitSurface (newimg, &src, screen, &dest);
SDL_FreeSurface(newimg);
return 1;
}

int GpTransLRBlt (int * nulo1, int nulo2[2], int x, int y, int w, int h, SDL_Surface * img, int x2, int y2, int imgw, int imgh, unsigned char color) {
int i;
int j;

SDL_Surface* newimg = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, img->format->BitsPerPixel, img->format->Rmask, img->format->Gmask, img->format->Bmask, img->format->Amask);
for( j = 0; j < h; j++ ) {
for( i = 0; i < w; i++ ) {
setpixel( newimg, i, j, getpixel( img, w+x2-1-i, j+y2) );
}
}
SDL_SetColorKey (newimg, SDL_SRCCOLORKEY, SDL_MapRGB(newimg->format, 248, 64, 248));
SDL_Rect dest;
dest.x = x;
dest.y = y;
SDL_Rect src;
src.x = 0;
src.y = 0;
src.w = w;
src.h = h;
SDL_BlitSurface (newimg, &src, screen, &dest);
SDL_FreeSurface(newimg);
return 1;
}


Este código tiene licencia GPL, así que, si lo mejoras, please, comparte los cambios ;)

Saludos

Arcnor
21/03/2006, 02:30
Una pequeña mejora en el código de getpixel y setpixel puede ser usar una macro para los if que comprueban la "endianness" (no se como ponerlo en castellano, lo siento :D) de la máquina. Si en vez de "if (SDL_BYTEORDER..." usas #if (SDL_BYTEORDER..." para mi que algo optimizará, porque estas funciónes se llama muchíííísimas veces.

Claro, eso siempre que usen 24 bits (¿alguien los usa? [wei5])

Otra optimización sería eliminar el case de setpixel y getpixel si siempre usas el mismo bitdepth, y quedarte con el return que te interesa. Ejemplo con 32 bits:



Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 4;
return *(Uint32 *)p;
}

Y ya en caso de que quisieras velocidad total, si siempre usas el mismo bitdepth puedes tratar directamente los pixels como ya dije en un post anterior e ir sustituyendo "manualmente" los bytes. ¿Pero quien necesita tanto? :D

P.D. Si la necesitas y no sabes (es muy sencillo, de todas maneras) avisa y pongo un ejemplo de lo que digo