Rotar una imagen en Java
Recientemente he estado trabajando en un proyecto en el que tenía que hacer ciertas manipulaciones sobre imágenes. Una de las operaciones que se requerían era la rotación de las mismas.
La operación en sí es algo más compleja de lo que pueda parecer, por dos razones. En primer lugar porque no solo hay que rotar la imagen sino desplazarla dentro del sistema de coordenadas para conservar las esquinas de la misma, y en segundo lugar porque hay que tener en cuenta los diferentes ángulos de rotación posibles, las esquinas del giro no serán las mismas en los diferentes ángulos.
Buscando por Internet llegué a varias posibles soluciones pero no tenían en cuenta el tema de los diferentes ángulos, solo funcionaban hasta giros de 90 grados, y respecto a la traslación de la imagen para conservar las esquinas no en todos los ejemplos que vi se tenía en cuenta. He decidido explicar el procedimiento que he seguido puesto que las ideas de Internet me ayudaron pero no encontré la solución que tuviera en cuenta los dos problemas comentados; por ello me parece interesante presentar la manera en que logré resolver como rotar una imagen en java.
Introducción
Para realizar las transformaciones de las imágenes usaremos la clase Java llamada AffineTransform que nos servirá para escalar una imagen, rotarla y trasladarla.
Para la rotación de una imagen tendremos que saber los grados (radianes) que se desea rotar y respecto a que, la rotación en la mayoría de los casos será respecto al centro de la imagen, para ello tendremos que saber en ancho y el alto de la imagen.
En la operación de traslación habrá que ver donde quedan las esquinas de las imágenes en los ejes X e Y dependiendo de los ángulos de rotación de la imagen. Lo que yo hice para comprenderlo fue dibujarme en un papel un rectángulo con las esquinas de colores e ir girándolo para ver donde quedaban después de los giros, algo parecido a lo que os trato de ilustrar a continuación.
Rotar una imagen en Java con AffineTransform
Una vez visto el planteamiento del problema “sobre el papel” ya podemos pasar a ver como hacerlo en Java.
En mi caso lo que hice fue construir una clase que tuviera todo lo necesario para hacer las transformaciones con imágenes. La clase tiene como atributos las dimensiones de la imagen en pixeles y un objeto de la clase AffineTransform, el atributo de los grados vendrá dado en grados sexagesimales que habrá que pasar posteriormente a radianes.
Una vez vistos los atributos de la clase Java vamos a ver el método de rotación de una imagen. Veremos que se pasan los grados a radiantes con el método estático de la clase Math y se toma como punto de referencia para la rotación el centro de la imagen que será el ancho y alto de la misma dividido entre dos.
Después de la rotación nos faltará el paso de la traslación como ya hemos comentado. Lo que hará este método es obtener la traslación que se ha de hacer de la imagen dentro del sistema de coordenadas de la misma dependiendo de la rotación para conservar las cuatro esquinas de la misma dentro del rectángulo de la imagen.
Para la realización de esto veremos que lo que se hace es ver las coordenadas X e Y en las que quedan las esquinas de la imagen que darán la coordenada (0,0) del sistema de coordenadas después de haber rotado la imagen porque como vemos se usa el objeto AffineTransform at que fue el mismo sobre el que ya se aplicó la rotación. Una vez hecho esto vemos que se usa otro objeto AffineTransform para hallar la traslación y se une con el que se había usado para la rotación.
Para hacer diferencia entre los ángulos de rotación veremos los métodos que hayan que puntos de la imagen son los que darán la coordenada (0,0) de la imagen, estos datos se obtienen muy fácilmente del esquema que les he presentado en la introducción.
Por ejemplo para una rotación de entre 90 y 180 grados.
- El punto A será el azul que será (0, altoImagen)
- El punto B será el rojo que será (anchoImagen, altoImagen)
Aplicaremos esto para el resto de los casos y veremos que nos quedará un código como el que presento a continuación.
Pues con esto ya estaría acabado, ahora cada vez que queramos rotar una imagen lo podemos hacer con un método estático como el que les enseño a continuación.
Esto dará como resultado un BufferedImage con la imagen rotada y la zona de no datos en negro. Llamamos zona de no datos a la zona que se ha quedado sin información de la imagen ya que está estará encerrada en un rectángulo aunque este rotada (lo podemos ver en la imagen que abre el artículo).
Guardado de la Imagen
Si queremos guardar la imagen será algo tan sencillo como esto.
Lectura de la Imagen
También para los que deseen leer una imagen en Java les dejo el siguiente código. El siguiente código les puede servir para leer una imagen en formato JPEG. Este método es importante puesto que para que funcione bien la rotación debe de estar en un BufferedImage de tipo RGB.
Proyecto de ejemplo
Dejo a vuestra disposición un proyecto de NetBeans totalmente funcional. En el proyecto de ejemplo se usa exactamente el mismo código que ha sido explicado en este artículo. El proyecto tiene un método main preparado para leer una imagen, rotar la imagen y finalmente guardarla.
En el próximo tutorial os enseñaré como hacer transparente la zona de no datos de la imagen (toda la zona negra) y guardar la imagen como PNG que es un formato que conserva la transparencia de la imagen.
0 comentarios:
Publicar un comentario