8/3/11

Imagen en Blanco y Negro en Java

 (Imagen A: Color, B: Escala de Grises, C: Blanco y Negro)
Una imagen en Blanco y Negro (Black and White) a diferencia de las imagenes en escala de grises donde cada color RGB tiene su tonalidad equivalente en gris, la imagen en blanco/negro es monocromo, es decir solo acepta el blanco y el negro sin ninguna escala intermedia.

Java nos permite trabajar con imagenes en blanco y negro y realizar la conversion facilmente utilizando la clase BufferedImage.TYPE_BYTE_BINARY. En este tutorial, veremos dos maneras de realizar la conversion a Blanco/Negro.

Primer metodo: 
Para convertir una imagen en color a su equivalente en Blanco/Negro, basta con crear una imagen en memoria del tipo BufferedImage utilizando BufferedImage.TYPE_BYTE_BINARY, despues se debe pasar pixel a pixel los valores de la imagen a colores a la nueva imagen blanco/negro, la clase BufferedImage.TYPE_BYTE_BINARY hara el resto.
Este metodo tiene un inconveniente, dependiendo de la luminosidad de la imagen, la calidad u otros factores, el resultado puede variar.

Segundo metodo
Este segundo metodo es una extension del primer metodo, ya que igualmente se utiliza la clase BufferedImage.TYPE_BYTE_BINARY para crear una imagen monocroma, pero tambien para poder controlar la cantidad de negro o blanco que deseemos en la imagen, se hace uso de una variable de tipo entero que llamaremos "umbral", esta variable puede tomar valores entre 0 y 255 y su valor por defecto sera 127.
Seudocodigo:

umbral = 127
color = imagen_color.getColorRGB(i,j);

R = color.leer_Rojo
G = color.leer_Verde
B = color.leer_Azul

si R > umbral entonces
   R = 255
sino
   R = 0
fin si

si G > umbral entonces
   G = 255
sino
   G = 0
fin si

si B > umbral entonces
   B = 255
sino
   B = 0
fin si

imagen_blanco_negro.setColor(i,j, color(R,G,B) )


Cuando se utliza la clase BufferedImage.TYPE_BYTE_BINARY para obtener una imagen monocroma, en realidad los pixeles aun contienen valores RGB diferentes de 0 y 255, aunque en pantalla vemos solo el blanco y negro, aprovechando esto, leeremos los valores RGB de cada pixel de la imagen y dependiendo de sus valores se los colocara en 0 o en 255, (ver seudocodigo). Asi podremos obtener varias imagenes con diferentes resultados, dependiendo del valor que tome "umbral".


El Codigo de la clase WB.java con ambos metodos


import java.awt.Color;
import java.awt.image.BufferedImage;
/**
 * @web http://jc-mouse.blogspot.com/
 * @author Mouse
 */
public class WB {    
    private int r,g,b;
    private Color color;
    int umbral = 127;// 

    public WB(){}

   public BufferedImage set_Blanco_y_Negro(BufferedImage f){
        BufferedImage bn = new BufferedImage(f.getWidth(),f.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
        //se traspasan los colores Pixel a Pixel
        for(int i=0;i<f.getWidth();i++)
          for(int j=0;j<f.getHeight();j++)
               bn.setRGB(i, j, f.getRGB(i, j));
        return bn;
   }

   public BufferedImage set_Blanco_y_Negro_con_Umbral(BufferedImage f){
        BufferedImage bn = new BufferedImage(f.getWidth(),f.getHeight(), BufferedImage.TYPE_BYTE_BINARY);        
        //se traspasan los colores Pixel a Pixel
        for(int i=0;i<f.getWidth();i++){
          for(int j=0;j<f.getHeight();j++){
               color = new Color(f.getRGB(i, j));
               //se extraen los valores RGB
                r = color.getRed();
                g = color.getGreen();
                b = color.getBlue();
                //dependiendo del valor del umbral, se van separando los
                // valores RGB a 0 y 255  
                r =(r>umbral)? 255: 0;
                g =(g>umbral)? 255: 0;
                b =(b>umbral)? 255: 0;
                bn.setRGB(i, j, new Color(r,g,b).getRGB());            
          }
        }        
        return bn;
    }
 
}


2 comentarios:

  1. Fantastico, gracias! Me pase media hora buscando una forma 'estandard' pero al parecer java no la tiene,

    Saludos

    ResponderEliminar