Como deixar uma imagem em tons de cinza em J2ME
Mostrarei um código básico para deixar uma imagem em tons de cinza, ou grayscale.
O algoritmo para deixar uma imagem em tons de cinza é muito simples. Levando-se em conta que cada pixel de uma imagem possui 4 valores ARGB, representando o canal de transparência (A=Alpha), o canal de vermelho (R=Red), o canal de verde (G=Green), e o canal de azul (B=Blue), devemos alterar os canais RGB, mantendo o canal alpha inalterado.
Mas como calcular o tom de cinza de um pixel pelos canais RGB? Basta calcular a média aritmética dos 3 canais e usar esse valor como o novo valor de R, G e B.
Canal Cinza = ((R+G+B) / 3 )
Por exemplo, um pixel que tenha:
A=10, R=120, G=30, B=45
Calcularíamos o canal cinza assim: (120 + 30 + 45) /3 = 56.
Então montaríamos a nova cor do pixel repetindo o canal cinza nos canais RGB, ficando assim:
A=10, R=56, G=56, B=56
Fazendo isso com todos os pixels da imagem, deixando os valores RGB iguais, com o valor da médias dos 3 canais de cores, fará com que a imagem fique em tons de cinza, como mostra a imagem ao lado.
O código é bem simples. Ele trabalha em cima do array ARGB da imagem. Veja:
public Image grayscaleImage(Image imgOriginal, int porcentagem) {
//Guarda a largura e altura da imagem
int largura = imgOriginal.getWidth();
int altura = imgOriginal.getHeight();
//Cria o vetor RGB da imagem destino, com o mesmo tamanho da imagem origem
int[] rgb = new int[largura * altura];
//Preenche o vetor RGB com as cores dos pixels da imagem origem
imgOriginal.getRGB(rgb, 0, largura, 0, 0, largura, altura);
//Deixa a imagem em tons de cinza
int gray;
for (int i = 0; i < rgb.length; ++i) {
gray = (((rgb[i] >> 16) & 0xff) + ((rgb[i] >> 8) & 0xff) + (rgb[i] & 0xff)) / 3;
rgb[i] = (((rgb[i] >> 24) & 0xff) << 24) | (gray << 16) | (gray << 8) | gray;
}
//Cria a imagem final com base no vetor RBG com transparência alteradareturn Image.createRGBImage(rgb, largura, altura, true);
}
Para usar esse método, basta eu chamá-lo da seguinte forma:
Image imagem = Image.createImage(”\foto.png”);
imagem = grayscaleImage(imagem);
Isso fará com que a imagem fique em tons de cinza.
O núcleo do método, é o for, que percorre todos os pixels da imagem, agindo sobre cada um deles. Para cada um faz o cálculo da nova cor. Antes de montar a nova cor, guarda na variável gray a média dos 3 canais RGB, e duplica essa média nos valores dos 3 canais quando monta a nova cor.
O colega Danilo Cesar, no comentário abaixo, sugeriu que se use a seguinte fórmula para conversão em tons de cinza, pois ela faz com que a imagem fique um pouco mais clara: C = 0.3*R +0.59*G +0.11*B. Essa fórmula, além de fazer a conversão, mexe no contrate da imagem. Valeu Danilo.
É isso! Agora você já sabe como fazer para deixar suas imagens em tons de cinza em J2ME.
Bons códigos!
Sobre o Autor
Nelson é desenvolvedor há 12 anos. Hoje desenvolve aplicações Web e Móveis na Abacomm Brasil cuidando do desenvolvimento server-side J2EE, banco de dados, design de aplicações móveis, e desenvolvimento móvel usando várias plataformas como BlackBerry, J2ME, FlashLite, Android, etc. Para conversar com o autor use o e-mail, MSN e GTalk npereirajr@gmail.com.

Danilo Cesar:
http://www.freepatentsonline.com/5671023.html
C = 0.3*R +0.59*G +0.11*B
2 Junho 2008, 1:47 pmAyran:
Olá Nelson,
Sobe seu codigo, fiquei com uma duvida:
Depois q vc calcula o gray na segunda linha do for, pq vc faz:
rgb[i] = (((rgb[i] >> 24) & 0xff) << 24) | (gray << 16) | (gray << 8) | gray;
na segunda linha? Num seria so atribuir o valor gray ao vetor? Tipo:
9 Fevereiro 2009, 11:34 amrgb[i]=gray;
Nelson Pereira Junior:
Faço isso pra manter os pixels semi-transparentes da imagem.
10 Fevereiro 2009, 11:32 pmaline:
Boa tarde,
não entendi muito a linha
rgb[i] = (((rgb[i] >> 24) & 0xff) << 24) | (gray << 16) | (gray << 8) | gray;
o que seria o o 24 e 0xff
eu poderia substituir pela formula:
29 Abril 2009, 2:48 pmC = 0.3*R +0.59*G +0.11*B