Convertir imagen a escala de grises

De ChuWiki

Vamos a ver un ejemplo de cómo cargar una imagen JPG y convertirla en una imagen con escala de grises.


Cargar la imagen JPG[editar]

Aunque no forma parte de la API oficial de java, las implementaciones de SUN del JRE y del JDK tienen un paquete com.sun.image.codec.jpeg que nos permite manejar ficheros jpg. Es posible, si usamos otro JDK que no sea de SUN, que no encontremos estas clases o incluso que en futuras versiones desaparezcan.

Con estas clases no estándar cargaremos en un BufferedImage nuestro fichero jpg.

import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
...
InputStream in = new FileInputStream("goku.jpg");
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);
BufferedImage imagen = decoder.decodeAsBufferedImage();

Simplemente creamos un InputStream a partir del fichero imagen, usamos la clase JPEGCodec para obtener un decoder de dicho InputStream y con el método decodeAsBufferedImage() metemos la imagen en un BufferedImage

Otra opción, usando la API oficial, es usar ImageIO

InputStream in = new FileInputStream("goku.jpg");
BufferedImage imagen = ImageIO.read(in);

Cambio de la escala de colores[editar]

Para cambiar la escala de colores, usaremos la clase java ColorConverterOp, a la que pasamos en el constructor espacio de colores que queremos. Hay varias espacios de colores que podemos obtener fácilmente, en concreto usaremos ColorSpace.CS_GRAY

ColorSpace espacioGrises = ColorSpace.getInstance(ColorSpace.CS_GRAY);

Una vez obtenido el espacio de grises, instanciamos el ColorConverterOp

ColorConverterOp ccop = new ColorConverter (espacioGrises, null);

El segundo parámetro null es un RenderingHints que nos permite elegir algoritmos para la transformación de la imagen (filtros antialias, interpolaciones, etc). Pondremos null que es mas sencillo.

Una vez instanciado ColorConverterOp, bastará llamar a su método filter() pasándole el BufferedImage para que se realice la conversión

BufferedImage destino = ccop.filter(imagen, null);

donde nuevamente, el segundo parámetro es null. Si ponemos en ese segundo parámetro un BufferedImage, nos pondrá ahí la transformación.


Código completo del ejemplo[editar]

Si tienes una imagen goku.jpg en el directorio de ejecución, el siguiente ejemplo, cortesía de chusterboy, carga la imagen, la transforma en escala de grises y la dibuja en una ventana.

package chusterboy;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.swing.JFrame;

import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;

public class Imagenes extends JFrame {

    private BufferedImage destino = null;

    public Imagenes() {
        super("Procesamiento de imágenes");
    }

    public void paint(Graphics g) {
        if (destino == null) {
            try {
                // Se carga la imagen del fichero
                InputStream in = new FileInputStream("goku.jpg");
                JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);
                BufferedImage imagen = decoder.decodeAsBufferedImage();

                // Se convierten los colores a escala de grises
                ColorConvertOp ccop = new ColorConvertOp(ColorSpace
                        .getInstance(ColorSpace.CS_GRAY), null);
                destino = ccop.filter(imagen, null);
                // Se dibuja y se cierra.
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ImageFormatException e) {
                e.printStackTrace();
            }
        }
        g.drawImage(destino, 0, 20, this);

    }

    /**
     * Dibuja la ventana
     * 
     * @param args
     */
    public static void main(String args[]) {
        Imagenes v = new Imagenes();
        v.setDefaultCloseOperation(EXIT_ON_CLOSE);
        v.setSize(640, 480);
        v.setVisible(true);
        v.setLocationRelativeTo(null);
        v.setBackground(Color.white);
    }
}

Y aquí las dos imágenes, antes y después:

http://foro.chuidiang.com/index.php?action=dlattach;topic=1431.0;attach=115;image

http://foro.chuidiang.com/index.php?action=dlattach;topic=1431.0;attach=117;image