[C con Clase] [Windows API] Transformación Afín
Steven Davidson
srd4121 en njit.edu
Sab Abr 14 06:09:22 CEST 2012
Hola Lourdes,
On 4/12/2012 11:32 PM, Lourdes Celene Haros Becerra wrote:
> Muchas gracias Steven, pero tal vez no me di a entender, trataré de
> detallar más mi pregunta:
>
> Creo que lo de checar si hay pixel ahí, si no para pintar negro, el
> programa ya lo hace porque sí estamos manejando coordenadas y tenemos
> una imagen que estamos repintando cada vez que se mueve, por tanto
> con los pixeles no tenemos problemas.
>
> Entonces especificamente queremos saber el orden de la multiplicacion
> de las matrices de transformación para que la imagen se pueda
> trasladar arriba-abajo-izquierda-derecha pero tambien pueda rotar con
> respecto a un punto fuera de la imagen sin que éste se desplace al
> realizar la traslacion.
>
En principio, deberás aplicar una o varias traslaciones. Posteriormente,
la rotación centrada en un punto en particular equivale a una traslación
de tal centro, C, al origen: T(-Cx,-Cy), la rotación: R(alfa), seguida
de una traslación desde el origen a ese centro: T(Cx,Cy). Al final,
obtendremos la siguiente matriz:
T = traslación arriba, abajo, izquierda, y/o derecha
R(C,alfa) = T(-Cx,-Cy) * R(alfa) * T(Cx,Cy)
M = T * R(C,alfa)
Esta matriz funcionará correctamente si usas "matrices-fila"; es decir,
la información de cada vértice se guarda en una fila. Esto implicará que
la multiplicación matricial se realizará así:
pixel_nuevo = pixel_original * M
que viene a ser,
(x' y' 1) = (x y 1) * M
De todas maneras, como expliqué en mi correo-e anterior, es mejor
aplicar el proceso inverso y por tanto, necesitas calcular la inversa de
la matriz resultante, M; esto es,
M' : inversa de M
(x y 1) = (x' y' 1) * M'
> Nuestro problema es el siguiente:
> Siendo:
> T: Traslación de la imagen fuente
> S: Escalación de la imagen fuente
> R: Rotación de la imagen fuente
> Tc: Traslación al centro de la imagen fuente
> Tic: Traslación inversa de la anterior
> Tcd: Traslación de la imagen fuente al centro de la imagen destino
> Ticd: Traslación inversa de la anterior Rd: Rotación de la imagen
> fuente respecto al centro de la imagen destino
>
> Tenemos:
> CMatrix3D T,R,Tc,Tic,Tcdest,Ticdest,Rdest,S,Sdest;
> CMatrix3D::Rotation(Rd, g_Thetadest); CMatrix3D::Rotation(R, g_Theta);
> CMatrix3D::Traslation(T,(int)g_Tx,(int)g_Ty);
> CMatrix3D::Traslation(Tc,-(int)g_pImagenSource->SizeX()/2,-(int)g_pImagenSource->SizeY()/2);
> CMatrix3D::Traslation(Tic,g_pImagenSource->SizeX()/2,g_pImagenSource->SizeY()/2);
> CMatrix3D::Traslation(Tcd,-(int)g_pImagen->SizeX()/2,-(int)g_pImagen->SizeY()/2);
> CMatrix3D::Traslation(Ticd,g_pImagen->SizeX()/2,g_pImagen->SizeY()/2);
> CMatrix3D::Scalation(S,g_Zoom,g_Zoom);
>
En primer lugar, no es necesario hacer un cásting a 'int', porque la
división entre enteros resulta en otro entero. Como estás dividiendo
entre dos, sugiero usar la operación de desplazamiento a la derecha a
nivel de bits: >>. Como además realizas estas divisiones varias veces,
sugiero usar una variable para guardar cada resultado en lugar de estar
invocando 'SizeX()' y 'SizeY()' constantemente para dividirlos. Al
final, tendrías esto,
int nMitadAnchuraOrigen = g_pImagenSource->SizeX() >> 1;
int nMitadAlturaOrigen = g_pImagenSource->SizeY() >> 1;
int nMitadAnchuraDestino = g_pImagen->SizeX() >> 1;
int nMitadAlturaDestino = g_pImagen->SizeY() >> 1;
Y ahora puedes usar estas variables para las operaciones.
> M=T*Tcd*Rd*Ticd*Tc*S*R*Tic //se desplaza el punto de rotacion
>
> y si tenemos:
> M=Tcd*Rd*Ticd*T*Tc*S*R*Tic //se giran los ejes y la traslacion que
> genera T, al rotar la imagen por ejemplo 45°, se giran los ejes 45° y
> la traslacion se hace en ese sentido de los ejes
>
Según entiendo por este código que presentas, quieres realizar unas
transformaciones de la imagen original y luego al copiar su resultado a
la imagen destinataria, vuelves a realizar otra serie de
transformaciones. El problema es que estás en dos espacios (sistemas de
coordenadas) diferentes. Tienes el S.C. de la imagen original y el S.C.
de la imagen destinataria. En algún momento, necesitas realizar ese
cambio de sistemas de coordenadas. Esto es casi como presentar tu imagen
en una vista en particular; consulta el capítulo 6 acerca del tema de la
"vista" yendo a:
http://graficos.conclase.net/curso/index.php?cap=006c#Vista
Posteriormente, podemos aplicar cualesquier otras transformaciones en el
S.C. de la imagen destinataria.
Quiero advertirte que, en general, es posible que estas transformaciones
eliminen información de tu imagen, ya que las imágenes se guardan en
espacios limitados, como por ejemplo, de [0,511] x [0,511]. Una rotación
de 45 grados por el centro de tal cuadrado (255,255) resultará en una
imagen de [0,723] x[0,723] que no se puede guardar en una imagen de 512
x 512 píxeles. Por lo tanto, sugiero que agrandes la imagen original
para así poder guardar los resultados sin pérdida de información. Claro
está, si sabes que el total de las operaciones resulta en una imagen sin
pérdidas, entonces obviamente no tienes problemas de este tipo.
Espero que lo anterior te ayude.
Steven
Más información sobre la lista de distribución Cconclase