domingo, 15 de fevereiro de 2009

JAVA: Converter Imagem para Escala de Cinza

Um exemplo básico de processamento de imagens em JAVA é a conversão de uma imagem colorida para escala de cinza.

Esse exemplo (MainClass) mostra como efetuar a leitura dos pixels de uma imagem, converter seus valores para RGBA (red, green, blue, alpha), modificar os pixels e gravar uma nova imagem.




import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class MainClass {

// converte pixels da imagem para tons de cinza
public static int[] imageToGray(int image[]) {
int grayimage[] = new int[image.length];

for (int i = 0; i < image.length; i++) {
// extrai a informação RGBA do valor inteiro
int alpha = (image[i] >> 24) & 0xff;
int red = (image[i] >> 16) & 0xff;
int green = (image[i] >> 8) & 0xff;
int blue = (image[i]) & 0xff;

// média dos valores RGB para tranformar para
// escala de cinza
int mean = (red + green + blue) / 3;

// converte a informação de rgb para inteiro
int gray = ((0 << 24) & 0xFF000000) | ((mean << 16) & 0x00FF0000) | ((mean << 8) & 0x0000FF00) | (mean & 0x000000FF);

// seta o pixel modificado na imagem
grayimage[i] = gray;
}

return grayimage;
}

public static void main(String[] args) throws IOException {

File inputFile = new File("/tmp/tux-ubuntu.jpg");
BufferedImage buffImage = ImageIO.read(inputFile);

int w = buffImage.getWidth();
int h = buffImage.getHeight();

int rgba[] = new int[w * h];
// obtem pixels do bufferedImage
buffImage.getRGB(0, 0, w, h, rgba, 0, w);

// converte para tons de cinza
int gray[] = imageToGray(rgba);
// escreve no bufferedImage
buffImage.setRGB(0, 0, w, h, gray, 0, w);

// escreve nova imagem no disco
ImageIO.write(buffImage, "JPG", new File("/tmp/tux-gray.jpg"));
}
}




O exemplo de utilização da classe:

7 comentários:

forever_juba disse...

Muito legal seu post. Depois de converter em escala de cinza tem como eu trabalhar com essa imagem pegando pixel a pixel em escala de cinza, tipo, imagem[1,1] to pegando o pixel com o valor da escala de cinza na posição 1 1?

Eiti Kimura disse...

Olá forever_juba,

Sim é possível obter o valor da imagem em RGB, na posição X,Y. Dentro em breve pretendo publicar um post de como fazer isso. O valor de um pixel da imagem obtido na posição X,Y, será em RGB, mas já dianto que como a imagem está em escala de cinza, o red, green e blue têm o mesmo valor em todas as camadas de cor, por isso o aspecto de escala de cinza.

Boa sorte,
Abraços,

Eiti

jhon disse...

Oi... me diz uma coisa, porque que tem que fazer um AND com 0xFF ???

Grato.

Eiti Kimura disse...

Olá jhon, na verdade não é um convencional AND, essa é uma operação de bitwise:

http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

Com ela é possível obter a mascara binária de um determinado valor, já que o 0xFF é a mascara total preenchida (1111..), por isso 8bits & 0xFF se obtém os primeiros 8 bits de 0xFF que correspondem a um determinado canal de cor.

vfm disse...

ola, gostaria de saber se é possivel utilizando parte do codigo pegar a matriz e dividir a imagem e depois monta-la (exatamento como a original) exemplo: a imagem ter 1270 bytes eu divido a imagem em 10 partes com a utilização da matriz e depois eu pego as 10 partes e monto. Obrigado, Virgilio. vfmnet@gmail.com

Eiti Kimura disse...

Olá vfm, sim você pode trabalhar o vetor a forma que for mais interessante pra você, é possível fazer um slice da imagem trabalhar em quantas partes quiser, inclusive com processos diferentes e depois juntar tudo em uma imagem só.
Abraços,

< Rutemberg disse...

Olá
(0 << 24), não seria (alpha << 24)? Gostei do post.