|
|
Artículo realizado por
David Isla "CID"
Tratamiento de Imágenes: Rotación Y Escalación
Saludos de nuevo, en este recién salido número diez de Macedonia, os quiero hablar sobre un tema importante, el tratamiento de las imágenes y más específicamente de la rotación y escalación de las mismas.
En un principio se puede pensar en que estos procesos solo obtengan resultados con imágenes fijas, pero el uso de estas técnicas en sprites por ejemplo, es muy normal, sobre todo podremos encontrar en muchos juegos la rotación de un sprite, que no deja de ser la rotación de una imagen, para conseguir de esa imagen, todas las demás posiciones posibles.
A continuación haremos un breve repaso de las matemáticas que se van a utilizar en el siguiente documento (no os preocupéis, que veréis que sencillo), seguiremos con un planteamiento del problema y su solución lógica, y terminaremos con una solución mas depurada.
LAS MATEMATICAS PARA ROTAR Y ESCALAR
Bien, empecemos por la escalación, proceso que es muy sencillo y que seguro a nadie le cueste nada asimilar. Para escalar una imagen tan solo tenemos que multiplicar esa imagen por una constante, por ejemplo por dos, si estamos hablando de una imagen 320x200 pixeles y escalasemos por dos tendríamos una imagen de 640x400 y si por ejemplo escalasemos la imagen por 0.5 tendríamos una imagen 160x100, fácil no?. Pues ahora el código, supongamos que es cierto que tenemos una imagen en pantalla de 320x200 y deseamos escalarla, el código seria como sigue a continuación:
for( j = 0; j < 200; j++ )
{
Bueno, el código no necesita muchas explicaciones no?, pero tranquilos que si hay algún despistado lo explico encantado :)
El codigo recorre la imagen para cada i (que seria la X de la imagen) y cada j (la Y de la imagen) calcula un nuevo punto multiplicando (o dividiendo tambien es posible) estas variables por la constante FactorEscalar, que podra tomar valores con varios decimales. Entonces, recorriendo toda la imagen y calculando la nueva posición de los puntos recorridos podemos aumentar el tamaño de una imagen o reducirla.
Ahora nos llega la parte a la rotación de la imagen, donde entra en juego el seno y el coseno, pero os prometo que no es nada complicado. Para rotar una imagen nos basamos en lo mismo de antes, vamos a recorrer la imagen y por cada punto de esta, vamos a calcular una nueva posicion, que vendra dada por los angulos que deseemos rotar la imagen. Para explicar el siguiente proceso os quiero comentar que si despues de esto no lo comprendeis os deis una paseo hasta una de nuestra seccione, Matematicas Basicas, donde se comentan mas ampliamente el sencillo proceso de la ratacion y de las tres dimensiones.
Bien, para rotar un punto de pantalla, usaremos un sencillo proceso que yo utilizo a menudo como podeis imaginar :), el cual consiste en multiplicar el punto por una matriz de rotacion. Existen tres matrices para rotar un punto en pantalla, una matriz por cada dimensión del espacio, es decir, una para rotar en el eje de las X, otra para rotar en el eje de las Y y otra para en eje de las Z, esta ultima matriz es la que nos interesa. Y como se multiplica un punto por una matriz? Direis ustedes no? Pues gracias a dios es facilisimo!!, tanto que hasta yo se hacerlo ;).
Bien, hagamos las presentaciones y expliquemoslo con un ejemplo, esta es la matriz de rotacion Z:
float RotarZ[4][4] =
{
Como veis es una matriz muy simple, en ella podemos ver una variable, nAngulo, que son los grados que deseemos rotar el punto, ademas esta variable la multiplicamos por 6.28/360, esto se debe a que deseamos pasar los angulos a Radianes, una unidad mas acorde con esta matematica.
Y como se multiplica esta matriz por un punto? Dira mas de uno, pues aquí teneis el codigo de la funcion completa, se basa en multiplicar x e y por filas, pero mejor sera que lo veais vosotros mismos.
//Bien, como podeis observar la matriz Rotadora se multiplica por el vector aMatCoo donde hemos introducido las variables y la multiplicación se guarda en Vector. Cuando finaliza la multiplicación tenemos en la posición 0 y 1 de Vector la x y la y respectivamente ya rotadas según los angulos que introducimos anteriormente.
Y ya esta, estamos preparados para realizar un programa que escale y rote a nuestro antojo, y para ello hemos creado la demostración 1, en el que se recoje lo anteriormente citado. Para observar el codigo y la demostración tendras que bajartela, aquí tan solo explicaremos por encima las distintas partes de la que se compone, ya que no creo necesario mas explicaciones. El programa comienza con la creacion de dos buffer de pantalla, uno lo utilizaremos para cargar un PCX que nos servira como imagen a rotar, esta rotacion la guardaremos en el buffer ESC y este buffer que es la imagen rotado la escalaremos, guardando el resultado en la propia pantalla para ver los resultados, este podria ser el funcional:
Lo mejor sera que hagais una pausa para ver la demostración, pues sobre ella seguiremos comentando el enorme error que tiene, asi que si no habeis bajado aun los ZIP ahora es el momento de bajar los dos que se adjuntan con el curso. Lo que se ha visto hasta ahora se proporciana en la demo1.
Pues bien, supongo que todos habeis estado viendo la demo y habreis jugado un poco con ella, pues para el que no se haya fijado, tiene un serio problema, cuando una imagen se escala demasiado, los puntos empiezan a separase, cosa normal por otro lado. Aquí podemos ver dos imágenes, una punteada y otra sin puntear, es decir, como deberia quedar para que la imagen fuera nitida y digamos perfecta.
![]() |
![]() |
Pues si la imagen uno es lo que podemos conseguir hasta ahora, vamos a explicar como conseguir la escalación y rotación como la imagen dos.
FORMA AVANZADA DE ROTACION Y ESCALACIÓN
Bien, llegamos al final del articulo para descubrir el metodo para eliminar esos puntos muertos que aparecen cuando rotamos o escalamos, la solución es bastante sencilla si nos paramos a observar el problema. El proble reside que para que recorriendo la imagen, alterando los puntos mediante los procesos descritos y obteniendo mas tarde la imagen con estos puntos alterados aparecen puntos muertos en la imagen, es decir, puntos x,y que no han sido rellenados por la imagen alterada, y que deseamos nosotros? Pues sencillamente que al procesar la imagen todos los puntos de esta aparezcan, y como conseguirlo? Pues si no podemos recorrer la imagen y calcular las nuevas posiciones para cada punto en pantalla haremos una cosa, recorrer la pantalla y calcular que punto le corresponde la imagen, asi, recorriendo cada uno de los puntos de la pantalla no nos dejaremos atrás ningun punto y la imagen saldra nitida, pero como hacemos el proceso a la inversa? Es decir, como calculamos el punto de la imagen al que corresponde el punto en pantalla? Pues muy facil, pensando al reves :).
Si anteriormente usabamos este codigo para Escalar y rotar:
// Rotar
for( i = 0; i < 320; i++ )
{
ClsVideo( Pantalla );
// Escalar
for( i = 0; i < 320; i++ )
{
Con nuestra filosofia usaremos el siguiente dejando el resto del codigo inalterado.
// Rotar
for( i = 0; i < 320; i++ )
{
ClsVideo( Pantalla );
// Escalar
for( i = 0; i < 320; i++ )
{
Bien, las diferencias son muy sencillas de ver, en las asignaciones de los buffers a pantalla o a buffer, hemos sustituido la i y la j por nXAux y nYAux. Como observareis es un cambio muy sencillo pero con un resultado importantisimo.
Eso es todo en este numero por lo referente a los entornos 2D, pero por supueso no es el unico material que te hemos preparado en este numero, date un paseo por la sección, y ya veras , yo me despido hasta el numero once, que lo disfruteis bien :).
ÚLTIMA REVISIÓN EN
JULIO
DE
1999
|
|