Você está na página 1de 5

13/08/13

Aldeia Numaboa - Applet Espelhando Imagens

Informtica Numaboa - Tutoriais e Programao


Applet Espelhando Imagens
Sex
10
Abr
2009

21:41
(4 votos, mdia 5.00 de 5)

Categoria: Aprenda Java fazendo applets


Atualizao: Sexta, 10 Abril 2009 22:43
Autor: vov Vicki
Acessos: 4323

O espelhamento de imagens um efeito interessante e muito fcil de ser obtido quando as


ferramentas certas so utilizadas. Neste caso, o conhecimento e o domnio do mtodo copyArea essencial
para obter o resultado desejado, portanto, a leitura de Os segredos de copyArea altamente recomendada.

Objetivo do projeto
1. Criar e controlar threads
2. Entender a estrutura de matrizes
3. Trabalhar com a interface grfica
4. Trabalhar com o MediaTracker
5. Criar mensagens na barra de status
6. Criar efeitos grficos interessantes

O cdigo Java
import java.applet.*; import java.awt.*; public class espelhoImg extends Applet implements
Runnable { Thread linha = null; boolean vivo = true; Image origImg = null; int larg = 0, alt = 0;
public void init() { String s = getParameter("imagem"); if (s != null) { Image img =
getImage(getCodeBase(), s); if (img != null) { MediaTracker mt = new MediaTracker(this);
mt.addImage(img, 0); try { mt.waitForID(0); } catch(InterruptedException _ex) { } larg =
img.getWidth(this); alt = img.getHeight(this); origImg = createImage(larg << 1, alt); Graphics g
= origImg.getGraphics(); g.drawImage(img, 0, 0, this); } } } public void start() { if (linha == null &&
origImg != null) { linha = new Thread(this); linha.start(); } vivo = (origImg != null); } public void
run() { while (vivo) { Graphics g = origImg.getGraphics(); g.setColor(Color.white); g.fillRect(larg,
0, larg, alt); for (int i = 0; i < larg; i++) { g.copyArea(i, 0, 1, alt, (larg << 1) - i * 2, 0);
showStatus("copia " + i + " para " + ((larg << 1) - i)); repaint(); try { linha.sleep(100); }
www.numaboa.com.br/informatica/tutos/java/1095-espelhando-imagens?tmpl=component&print=1&page=

1/5

13/08/13

Aldeia Numaboa - Applet Espelhando Imagens

catch(InterruptedException _ex) { } } try { linha.sleep(1000); } catch(InterruptedException _ex) { }


} } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { if(origImg != null)
g.drawImage(origImg, 0, 0, this); } public void stop() { vivo = false; } } // fim da classe
O applet funcionando
O cdigo Java foi compilado para um arquivo de bytecodes de nome espelhoImg.class. Crie um documento
HTML e insira este applet. A altura e a largura do applet devem ser a altura e a largura da imagem que deve ser
espelhada. O resultado o seguinte:

Aproveite e d uma olhada no rodap do seu browser. L voc poder ver a sequncia da cpia das colunas
de pixels.

Explicaes que podem ser teis


H algumas novidades neste applet alm do uso do mtodo copyArea: usamos a interface grfica de um objeto
Image para atualiz-la antes de mostr-la na janela do applet, um objeto MediaTracker para monitorar a leitura
de uma imagem e usamos operadores de deslocamento bit-a-bit.

A declarao da classe
Precisamos apenas dos pacotes java.applet.* e java.awt.*. Este applet tambm Runnable, quer dizer, o applet
vai conter um mtodo run que ir gerenciar o seu comportamento. Para isto criamos um thread adicional. Se
voc ainda no leu O que so threads e como dom-los, aproveite a oportunidade agora. Neste ponto, o
tutorial Brincando com Cores tambm uma boa pedida. O thread para controlar o comportamento do applet
declarado como Thread linha = null e boolean vivo = true o acompanha.
Alm disto, declaramos um objeto Image origImg = null e int larg (largura da imagem) e int alt (altura da
imagem).

O mtodo init()
No mtodo init() lemos o parmetro "imagem" e atribumos seu valor varivel local String s. Se s no for null,
temos o nome do arquivo que contm a imagem desejada. Instanciamos ento o objeto Image img, o qual
conter a imagem grfica. Se o arquivo mencionado no existir, img ser igual a null e as linhas seguintes no
sero executadas.
De posse da imagem, criamos o objeto MediaTrack er mt (do pacote AWT). O MediaTracker permite monitorar e
controlar o carregamento de objetos de mdia (imagens e sons), mas, atualmente, o MediaTracker rastreia
apenas os objetos Image. Adicionamos o objeto Image img ao nosso rastreador usando seu mtodo addImage mt.addImage(img, 0). O mtodo exige dois parmetros: a imagem que deve ser monitorada e um nmero de
identidade (id). Este id qualquer nmero inteiro e poder ser utilizado para obter informaes da imagem
correspondente. Podemos adicionar quantas imagens quisermos ao MediaTracker e, desta forma, monitorar seu
pre-carregamento. Se atribuirmos o mesmo id a um grupo de imagens, podemos obter informaes sobre o
grupo todo. Os mtodos waitForAll (espere por todas) e waitForID (espere pelo id), tambm do MediaTracker,
retornaro o controle ao chamador apenas quando a(s) imagen(s) esteja(m) carregada(s). No nosso applet
utilizamos mt.waitForID(0) dentro de um bloco try/catch.
www.numaboa.com.br/informatica/tutos/java/1095-espelhando-imagens?tmpl=component&print=1&page=

2/5

13/08/13

Aldeia Numaboa - Applet Espelhando Imagens

Com a imagem em mos, atribumos varivel larg a largura da imagem e alt a sua altura. Em seguida
criamos o objeto Image origImg com o dobro da largura da imagem enviada como parmetro - origImg =
createImage(larg << 1, alt) (veja o operador << em "Funes e Operadores Matemticos"). Em seguida,
obtemos a interface grfica Graphics g do objeto Image recm-criado (Graphics g = origImg.getGraphics()) e
aplicamos a ela a imagem do nosso grfico a partir das coordenadas 0,0 (g.drawImage(img, 0, 0, this)).
Com o applet inicializado, est tudo pronto para o mtodo start.

O mtodo start()
No mtodo start() criamos nossa linha de execuo, a Thread linha. A esta altura j sabemos que o mtodo
start() executado toda vez que a pgina que contm o applet se tornar ativa no browser. Portanto, se a linha de
execuo no existir e se a imagem origImg foi obtida no mtodo init (if (linha == null && origImg != null) ),
criamos uma nova (linha = new Thread(this) - "this" significa "este applet") e a tornamos ativa com linha.start(). A
seguir, atribumos varivel vivo o valor true (vivo = true;), a qual indica que o thread se encontra no estado ativo
(executvel).

O mtodo run()
Se o applet implementa a interface Runnable e j possui um thread adicional, a presena de um mtodo run()
obrigatria, porm o mtodo run() s atua se o thread de execuo estiver ativo (while(vivo)), e vivo s
verdadeiro se a pgina que contm o applet estiver ativa. Caso o usurio mude de pgina, o thread desativado
pela Java, assim como todos os procedimentos a ele associados. No sobra "lixo" e os recursos da mquina do
usurio so liberados. claro que nossa varivel vivo precisa indicar esta nova situao. Como sabemos que o
mtodo stop() chamado quando o thread "morre", neste ponto que atualizamos nossa varivel.
A primeira coisa que o mtodo run() faz obter a interface grfica do objeto Image origImg com Graphics g =
origImg.getGraphics(). Esta interface grfica uma tela de pixels com tantas linhas quanto for a altura e tantas
colunas quanto for a largura da imagem. No exemplo, temos 80 linhas e 240 colunas. No podemos esquecer
que as coordenadas desta tela se iniciam em x = 0 e y = 0. Isto significa que as coordenadas das linhas vo de
0 a 79 (80 linhas) e as das colunas vo de 0 a 239 (240 colunas). Portanto, quando quiser se referir 10a. linha,
por exemplo, sua coordenada y igual a 9 e que sua 58a. coluna tem x = 57.
Na inicializao do applet colocamos na metade da esquerda da interface grfica g imagem origImg. A metade
da direita est livre e nela que inicialmente desenhamos um retngulo preenchido de branco:
g.setColor(Color.white) e g.fillRect(larg, 0, larg, alt). As coordenadas da imagem na metade esquerda so 0,0 at
119,80. O retngulo branco desenhado a partir de 120, 0 com uma largura (x) de 120 e altura (y) de 80.
Portanto, ocupa toda a metade direita da interface grfica.
Tendo preparado a interface grfica para receber nossa imagem espelhada, iniciamos um loop com valores de i
que vo de 0 a 119, que so as coordenadas x da imagem original. Dentro deste loop colocamos o mtodo
copyArea, que far todo o trabalho de espelhamento: g.copyArea(i, 0, (larg << 1) - i * 2, 0). O formato de
copyArea o seguinte:

copyArea(int x, int y, int largura, int altura, int desloca_x, int desloca_y)
onde x e y so as coordenadas do ponto de origem (onde comea o retngulo que deve ser copiado); int largura
e int altura so a largura e a altura do retngulo a ser copiado; int desloca_x o deslocamento do retngulo
copiado no eixo x a partir das coordenadas do ponto de origem; int desloca_y o deslocamento do retngulo
copiado no eixo y a partir das coordenadas do ponto de origem.
www.numaboa.com.br/informatica/tutos/java/1095-espelhando-imagens?tmpl=component&print=1&page=

3/5

13/08/13

Aldeia Numaboa - Applet Espelhando Imagens

Copiamos a imagem original em "fatias", coluna por coluna, e transportamos a cpia do fim para o comeo da
metade direita do ambiente grfico. Veja o exemplo abaixo:
Quando copiamos o retngulo com as coordenadas de origem x = 0 e y = 0, largura 1 e altura 5, e o
deslocamos para a 10a. coluna, o deslocamento de x 10 (pois 0 + 10 = 10).
Quando copiamos o retngulo com as coordenadas de origem x = 1 e y = 0, largura 1 e altura 5, e o
deslocamos para a 9a. coluna, o deslocamento de x 8 (pois 1 + 8 = 9), e assim sucessivamente.
A frmula que calcula o deslocamento largura total - 2 * coluna, ou seja,
dsoa =1 -2*0=1
elc0
0
0
dsoa =1 -2*1=8
elc1
0
..
.
dsoa =1 -2*4=2
elc4
0

10
8
6
4
2

0,0

1,0

2,0

3,0

4,0

5,0

6,0

7,0

8,0

9,0

10,0

No nosso applet, o clculo (larg << 1) - i * 2 indica o deslocamento da coluna i. A cada cpia, a barra de status
indica qual coluna foi copiada para onde e solicitamos que a imagem recm modificada seja mostrada na tela do
applet. Para isto, basta utilizar o mtodo showStatus("mensagem") e o mtodo repaint(), o qual acionar os
mtodos update e paint. Precisamos de repaint porque o ambiente grfico de origImg apenas um buffer de
trabalho que s mostrado na tela do applet quando o copiamos para o ambiente grfico da tela do applet.
Como o procedimento de copiar a imagem original em "fatias" e transport-la para a metade direita MUITO
rpido, precisamos introduzir um tempo de espera atravs de linha.sleep(100), que faz com que o thread fique
"dormindo" 0.1 segundo.
Terminado o loop, toda a imagem esquerda transportada "ao contrrio" para a direita e o espelhamento
horizontal obtido. Fazemos uma pausa de 1 segundo com linha.sleep(1000) e reiniciamos o processo.

O mtodo update()
O mtodo update(Graphics g) nada mais faz do que chamar o mtodo paint(). No h necessidade de
implementar cdigo por que no precisamos refazer o fundo da nossa imagem, principal funo do update.

O mtodo paint()
Neste applet, a nica funo do mtodo paint(Graphics g) desenhar na tela do mesmo a imagem origImg, se
ela existir. Caso a imagem no tenha sido encontrada e/ou carregada, o mtodo paint no faz nada.
www.numaboa.com.br/informatica/tutos/java/1095-espelhando-imagens?tmpl=component&print=1&page=

4/5

13/08/13

Aldeia Numaboa - Applet Espelhando Imagens

O mtodo stop()
Quando o usurio abandona a pgina onde est o applet (ou por motivos outros), o mtodo stop() invocado. No
nosso caso, sua nica e importantssima misso "desligar" nossa linha de execuo e deixar que a Java faa
a faxina (liberando variveis, threads ocultos, etc) antes de "matar" o thread que ns criamos... ou seja, no
sobra lixo e os recursos da mquina so liberados. Basta dizer que a varivel vivo falsa para que o mtodo
run() seja interrompido e para que a Java assuma o comando.

Lio de casa
Modifique e amplie o cdigo deste applet. Sugestes:
1. Passe parmetros para controlar as pausas.
2. Passe um parmetro para indicar a cor de fundo da metade direita do applet.
3. Experimente fazer um espelhamento vertical da imagem. praticamente o mesmo applet, basta alterar as
referncias no loop for do mtodo run. Se voc no conseguir, d uma olhada em "Reflexo, o espelhamento
vertical".

Finalmentes
Ufa!!! Haja explicao! Mas, para o bem de todos e felicidade geral da nao, estes conceitos serviro de base
para muitos outros applets, dos mais simples aos mais elaborados.
Este applet bastante simples, a explicao que precisou ser longa. O que importa que o efeito obtido
interessante e pode ser utilizado em applets mais complexos, como aquele do lago... sabe qual ?
Voc pode baixar o texto deste tutorial, o cdigo fonte e a classe deste applet na seo de downloads em
tutoriais/java.
Grande abrao e sucesso!
v Vicki

www.numaboa.com.br/informatica/tutos/java/1095-espelhando-imagens?tmpl=component&print=1&page=

5/5