En primer lugar os presentaré una imagen original y sobre esta iremos aplicando diversas transformaciones para hacer que parezca una imagen totalmente distinta.
En primer lugar os dejo el código para lanzar nuestra aplicación y a medida que vayamos avanzando, iremos explicando cada una de las transformaciones que hemos aplicado a nuestra imagen original.
package tratamientoImagenes; import javax.swing.JFrame; public class Main { private static void createAndShowGUI() { JFrame frame = new JFrame("Tratamiento de imágenes con Swing"); Expositor panel = new Expositor(); frame.getContentPane().add(panel); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(800, 534); frame.setVisible(true); } public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } }
Este es nuestro panel expositor, mediante un GridLayout añadiremos 4 paneles, cada uno de ellos con una imagen de fondo y un aspecto distinto a pesar de ser la misma imagen de base.
package tratamientoImagenes; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.net.URL; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; public class Expositor extends JPanel { /** * Constructor. */ public Expositor() { /* * Creamos un layout de 4 paneles, en cada uno mostraremos una imagen * "aparentemente" distinta */ super(new GridLayout(2, 2)); setPreferredSize(new Dimension(800, 534)); // Los paneles con las imagenes Original original = new Original(); EscalaDeGrises escalaDeGrises = new EscalaDeGrises(); Espejo espejo = new Espejo(); Translucida translucida = new Translucida(); Dimension photoDimension = new Dimension(400, 267); original.setPreferredSize(photoDimension); escalaDeGrises.setPreferredSize(photoDimension); espejo.setPreferredSize(photoDimension); translucida.setPreferredSize(photoDimension); original.setOpaque(false); escalaDeGrises.setOpaque(false); espejo.setOpaque(false); translucida.setOpaque(false); // Etiquetas JLabel originalLabel = new JLabel("ORIGINAL"); JLabel escalaDeGrisesLabel = new JLabel("ESCALA DE GRISES"); JLabel espejoLabel = new JLabel("ESPEJO"); JLabel translucidaLabel = new JLabel("TRANSLUCIDA"); originalLabel.setForeground(Color.WHITE); escalaDeGrisesLabel.setForeground(Color.WHITE); espejoLabel.setForeground(Color.WHITE); translucidaLabel.setForeground(Color.WHITE); original.add(originalLabel); escalaDeGrises.add(escalaDeGrisesLabel); espejo.add(espejoLabel); translucida.add(translucidaLabel); this.add(original); this.add(escalaDeGrises); this.add(espejo); this.add(translucida); } /** * Para recuperar una imagen de un archivo... * * @param path Ruta de la imagen relativa al proyecto * @return una imagen */ public static ImageIcon createImage(String path) { URL imgURL = Expositor.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn't find file: " + path); return null; } } }
Y ahora empezamos con los paneles, primero presentamos la imagen original para que podáis apreciar los cambios que iremos realizando, el como pintar un panel transparente con una imagen de fondo ya lo tratamos en una entrada anterior JPanel con imagen de fondo.
package tratamientoImagenes; import java.awt.Graphics; import javax.swing.ImageIcon; import javax.swing.JPanel; public class Original extends JPanel { // Cargamos la imagen original private ImageIcon photo = Expositor.createImage("imagenes/ER.jpg"); @Override public void paint(Graphics g) { g.drawImage(photo.getImage(), 0, 0, null); // Pintamos el resto de componentes super.paint(g); } }
Una transformación que personalmente me gusta bastante, pasaremos la imagen original por uno de los filtros de RGBImageFilter, en este caso el filtro de escala de grises. Este tipo de filtro hará que los pixeles se vean mas claros para posteriormente aplicarle tonos grises a la imagen. Así es como lo hemos usado:
package tratamientoImagenes; import java.awt.Graphics; import java.awt.Image; import java.awt.image.FilteredImageSource; import java.awt.image.ImageFilter; import java.awt.image.ImageProducer; import javax.swing.GrayFilter; import javax.swing.ImageIcon; import javax.swing.JPanel; public class EscalaDeGrises extends JPanel { // Cargamos la imagen original private ImageIcon photo = Expositor.createImage("imagenes/ER.jpg"); @Override public void paint(Graphics g) { // Imagen Image img = photo.getImage(); // Filtro de escala de grises ImageFilter filter = new GrayFilter(true, 50); ImageProducer producer = new FilteredImageSource(img.getSource(), filter); ImageIcon newIcon = new ImageIcon(this.createImage(producer)); newIcon.paintIcon(this, g, 0, 0); // Pintamos el resto de componentes super.paint(g); } }
Cuando dibujamos una imagen, podemos aplicarle una transformada para girarla como nos apetezca, usamos para ello el método drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer); del objeto Graphics2D. Este método nos permite cosas como dibujar parte de una imagen en otra imagen, escalar una imagen y otras tantas. Tomamos la imagen y una serie de coordenadas del rectángulo destino (dx, dy) así como del rectángulo origen (sx, sy). Manipulando estas coordenadas podemos hacer que la imagen se voltee como queramos.
En Java las coordenadas empiezan en la esquina superior izquierda y terminan en la inferior derecha, así pues para girar una imagen como si estuviésemos frente a un espejo modificamos las coordenadas del rectángulo origen para que empiecen en el borde superior derecho y terminen en el inferior izquierdo.
En el ejemplo las modificamos para voltear la imagen 180 grados, es decir, como si viésemos un reflejo en un lago. Tomaremos entonces como origen la esquina inferior izquierda y terminamos en la superior derecha.
package tratamientoImagenes; import java.awt.Graphics; import java.awt.Image; import javax.swing.ImageIcon; import javax.swing.JPanel; public class Espejo extends JPanel { // Cargamos la imagen original private ImageIcon photo = Expositor.createImage("imagenes/ER.jpg"); @Override public void paint(Graphics g) { // Imagen Image img = photo.getImage(); int width = photo.getIconWidth(); int height = photo.getIconHeight(); // Rotamos la imagen g.drawImage(img, 0, 0, width, height, 0, height, width, 0, null); // Pintamos el resto de componentes super.paint(g); }
Y por último haremos translucida la imagen original, para ello deberemos cargar todos los pixeles de la imagen en una BufferedImage, y sobre esta aplicar un filtro modificando el componente alpha de cada pixel.
package tratamientoImagenes; import java.awt.AlphaComposite; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.JPanel; public class Translucida extends JPanel { @Override public void paint(Graphics g) { // En este caso tendremos que trabajar con una BufferedImage URL imgURL = Expositor.class.getResource("imagenes/ER.jpg"); BufferedImage img = null; try { img = ImageIO.read(imgURL); } catch (IOException e) { e.printStackTrace(); } int w = img.getWidth(null); int h = img.getHeight(null); // Necesitaremos una imagen auxiliar a la que aplicar un filtro BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics gI = bi.getGraphics(); // Sobre esta imagen dibujaremos la imagen original gI.drawImage(img, 0, 0, null); Graphics2D g2d = (Graphics2D) g; // Establecemos la componente alpha de nuestros graficos 50% g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); /* Draw the image, applying the filter */ g2d.drawImage(bi, null, 0, 0); // Pintamos el resto de componentes super.paint(g); } }
Y así termina todo, espero que os haya resultado útil este mini-tutorial sobre tratamiento de imágenes.
Un saludo y hasta pronto.
5 comentarios:
hola, muy bueno, me ha gutado mucho, pero..
y si tubiera 2 imagenes?
quiero decir, por ejemplo, una con una capa semitrasparente hecha en photoshop, y otra con una foto, saber si se podrian superponer, se podria hacer?
Buenas,
Hay varias maneras de superponer imágenes, por ejemplo podías usar un código similar a este para pintar 2 imágenes sobre el mismo componente. A una de ellas le establecemos cierta transparencia y la superponemos a la otra imagen.
Espero que te sirva.
protected void paintComponent (Graphics g1) {
Graphics2D g = (Graphics2D) g1;
super.paintComponent(g);
float alpha = 0.5;
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
g.drawImage(image1, 0, 0, null);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f - alpha));
g.drawImage(image2, 0, 0, null);
}
gracias, lo intentare
Hola me gustaría que explicases el código para pintar las dos imágenes, y si puedes hacer para que se guarde en un archivo. Muchas gracias
Hola como stan? queria preguntar como puedo obtener el porcentaje de la diferencia que existe entre dos imagenes similares en el modelo RGB de 24 bits???
Publicar un comentario