Problema pra carregar imagens

12 respostas
MelissaN

Então... o outro tópico eu fechei, aquela parte ta resolvida xD agora tem outro problema...

A transição de imagens fica piscando...alguma idéia de alguém?

Classe do efeito (extende JXImagePanel):

package demo;

import java.awt.AlphaComposite;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import org.jdesktop.swingx.JXImagePanel;

public class Efeito2 extends JXImagePanel {

   private Contador contador;
   private BufferedImage img1, img2, img3, img4, img5;
   private volatile float alpha = 1.0f;
   private float add = -0.02f;
   private Image imgAux;
   private Image imagem1, imagem2;

   public Efeito2() {
    
      setSize(800, 600);
      setIgnoreRepaint(true);
      final String endereco[] = new String[5];

      endereco[0] = "/demo/images/imagem1.jpg";
      endereco[1] = "/demo/images/imagem2.jpg";
      endereco[2] = "/demo/images/imagem3.jpg";
      endereco[3] = "/demo/images/imagem4.jpg";
      endereco[4] = "/demo/images/imagem5.jpg";


      img1 = carregarImagem(endereco[0]);
      img2 = carregarImagem(endereco[1]);
      img3 = carregarImagem(endereco[2]);
      img4 = carregarImagem(endereco[3]);
      img5 = carregarImagem(endereco[4]);

      setVisible(true);

      //Iniciamos a thread que fará a imagem se repintar várias vezes
      //Isso dá o efeito de animação.
      Thread t = new Thread(new DemoThread(), "Thread de demonstração");
      t.setDaemon(true);
      t.start();

      contador = new Contador(new Image[]{img1, img2, img3, img4, img5});

      imgAux = contador.next();

      imagem1 = imgAux;

      imagem2 = contador.next();

   }

   private BufferedImage carregarImagem(String image) {
      try {
         //Carrega a imagem do disco
         BufferedImage img = ImageIO.read(getClass().getResource(image));

         //Converte ela para o formato da tela. Isso aumenta muito as chances do seu desenho ser acelerado por hardware.
         //O processo de covers�o � simples. Simplesmente criamos uma imagem com a configura��o da tela, e desenhamos
         //a imagem carrega sobre esta.
         //Tamb�m j� farei aqui o redimensionamento para o tamanho da tela, evitando gastar tempo com isso na hora de
         //desenhar na tela.
         BufferedImage imagem = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(getWidth(), getHeight(), Transparency.TRANSLUCENT);

         Graphics2D g2d = imagem.createGraphics();
         g2d.drawImage(img, 0, 0, imagem.getWidth(), imagem.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null);
         g2d.dispose();

         //Retornamos a imagem redimensionada e otimizada
         return imagem;
      } catch (IOException e) {
         throw new RuntimeException("Não foi possível carregar a imagem");
      }
   }

   @Override
   public void paint(Graphics g) {

      Graphics2D g2d = (Graphics2D) g.create();
      //Desenhamos a imagem 1
      g2d.drawImage(/*img1*/imagem1, 0, 0, null);

      //Nesta linha, alteramos a transpar�ncia de tudo que ser� desenhado
      //sobre o graphics.
      g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));

      //contador.next();

      //E então desenhamos a imagem 2, sobre a imagem 1.
      g2d.drawImage(/*img2*/imagem2, 0, 0, null);

      //Variamos o alpha
      alpha += add;

      if (alpha < 0.02) {
         add = 0.02f;
      } else if (alpha > 0.98) {
         add = -0.02f;
      }

      g2d.dispose();
   }

   public class DemoThread implements Runnable {

      @Override
      public void run() {

         try {

            //Para fazer a animação, simplesmente chamamos o repaint várias vezes
            //Essa é uma forma bem rudimentar de animar. O Ponto V! descreve mecanismos
            //melhores.
            while (true) {

               repaint();

               Thread.sleep(1000 / 15); //15 fps

               if (alpha < 0.02 || alpha > 0.98) {

                  System.out.println("ENTROU!");

                  Thread.sleep(2000);

                  imagem1 = imagem2;

                  ((Graphics2D) imagem1.getGraphics()).setComposite(AlphaComposite.SrcOver.derive(0.98F));

                  imagem2 = contador.next();

                  ((Graphics2D) imagem2.getGraphics()).setComposite(AlphaComposite.SrcOver.derive(0.02F));

               }

            }



         } catch (InterruptedException e) {
            //JOptionPane.showMessageDialog(getContentPane(), e);
         }
      }
   }

   public static void main(String[] args) {
      EventQueue.invokeLater(new Runnable() {

         @Override
         public void run() {
            new Efeito2().setVisible(true);
         }
      });
   }
}
Classe pra mudar as imagens... (esse método next() ai xD):
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package demo;

import java.awt.Image;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
 *
 * @author melissa
 */
public class Contador {

   private ArrayList<Image> imgs;
   private int pointer;

   public Contador(Image[] images) {

      imgs = new ArrayList<Image>(Arrays.asList(images));

      pointer = 0;

      System.out.println("Tamanho: " + images.length);

   }

   public Contador(Collection<Image> col) {

      imgs = new ArrayList<Image>(col);

      pointer = 0;

   }

   public Image next() {

      if (pointer >= imgs.size()) {
         pointer = 0;
      }

      Image next = imgs.get(pointer);

      System.out.println("next(): " + next.toString() + " (" + pointer + ")");

      pointer++;

      return next;

   }
}

Alguma idéia?

12 Respostas

ViniGodoy

Oi.

Só um comentário, antes de entrar no problema mesmo. Sempre que você sobrescreve um componente (como nesse caso), você deve sobrescrever o método paintComponent e não o paint.

O paint em componentes faz mais coisas do que simplesmente pinta-lo na tela, e você pode ter um comportamento inconveniente se sobrescreve-lo. A parte encarregada só do componente em si fica no paintComponent.

MelissaN
ViniGodoy:
Só um comentário, antes de entrar no problema mesmo. Sempre que você sobrescreve um componente (como nesse caso), você deve sobrescrever o método paintComponent e não o paint.

Ops! Arrumei já. ^^

@Override
   public void paintComponent(Graphics g) {

      Graphics2D g2d = (Graphics2D) g.create();
      //Desenhamos a imagem 1
      g2d.drawImage(/*img1*/imagem1, 0, 0, null);

      //Nesta linha, alteramos a transpar&#65533;ncia de tudo que ser&#65533; desenhado
      //sobre o graphics.
      g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));

      //contador.next();

      //E então desenhamos a imagem 2, sobre a imagem 1.
      g2d.drawImage(/*img2*/imagem2, 0, 0, null);

      //Variamos o alpha
      alpha += add;

      if (alpha &lt; 0.02) {
         add = 0.02f;
      } else if (alpha &gt; 0.98) {
         add = -0.02f;
      }

      g2d.dispose();
   }

Mas não mudou muita coisa '-'

ViniGodoy

Não, não tinha muito a ver com o problema. Na verdade, essa é uma daquelas coisas que se der erro, é só de vez enquanto.
O mesmo vale para o tipo de manipulação que você fez dentro do “run” da thread.

Infelizmente não estou com muito tempo para te mostrar como evitar o flickering. =/

MelissaN

O problema é que nem é flickering… (eu tinha dado uma olhada no ponto V! sobre isso) é que ele ta chamando a próxima imagem e desbotando ela, ao invés de desbotar a anterior

MelissaN

Hey people! xD

Meu problema mudou '-' com uma ajuda aqui a gente refez essa parte que tava com problema, e agora ela funciona ^^ Problema agora é diferente:

1-A imagem perde qualidade .-.

2-A imagem tá crescendo sozinha o.O

O código tá aqui se alguém quiser olhar... (não sei se serve pra alguma coisa porque to fazendo no FreeDesign)

package demo;

import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;

public class FrameTeste extends javax.swing.JFrame {

   private Image[] images;
   private float alpha = 1.0F;
   private int pointer = 0;
   private int tempoExibicao = 3000;
   private int framesPerSecond = 1000 / 15;
   private float alphaTax = 0.02F;
   private Image curr;

   public FrameTeste() {


      initComponents();
      labelImagem.setSize(panelImg.getSize());

      setExtendedState(JFrame.MAXIMIZED_BOTH);

      final String endereco[] = new String[5];

      images = new Image[5];

      endereco[0] = "/demo/images/imagem1.jpg";
      endereco[1] = "/demo/images/imagem2.jpg";
      endereco[2] = "/demo/images/imagem3.jpg";
      endereco[3] = "/demo/images/imagem4.jpg";
      endereco[4] = "/demo/images/imagem5.jpg";

      images[0] = carregarImagem(endereco[0]);
      images[1] = carregarImagem(endereco[1]);
      images[2] = carregarImagem(endereco[2]);
      images[3] = carregarImagem(endereco[3]);
      images[4] = carregarImagem(endereco[4]);

      initTimer();
      
   }

   public FrameTeste(Collection<Image> imgs) {

      initComponents();

      images = imgs.toArray(new Image[]{});

   }

   private void initTimer() {

      new Thread() {

         @Override
         public void run() {

            try {
               Thread.sleep(1000);
            } catch (InterruptedException ex) {
               Logger.getLogger(FrameTeste.class.getName()).log(Level.SEVERE, null, ex);
            }

            while (true) {

               labelImagem.setSize(panelImg.getSize());

               curr = getNext();

               System.out.println("Largura: " + labelImagem.getWidth() + ", Altura: " + labelImagem.getHeight());

               labelImagem.setIcon(new ImageIcon(curr.getScaledInstance(labelImagem.getWidth(), labelImagem.getHeight(), 0)));

               while (alpha > 0.0F) {

                  panelImg.setAlpha(alpha);

                  try {
                     Thread.sleep(framesPerSecond);
                  } catch (InterruptedException ex) {
                     Logger.getLogger(FrameTeste.class.getName()).log(Level.SEVERE, null, ex);
                  }

                  alpha -= alphaTax;

               }

               alpha = 0.0F;

               System.out.println("Alpha: " + alpha);

               curr = getNext();

               System.out.println("Largura: " + labelImagem.getWidth() + ", Altura: " + labelImagem.getHeight());

               labelImagem.setIcon(new ImageIcon(curr.getScaledInstance(labelImagem.getWidth(), labelImagem.getHeight(), 0)));

               panelImg.setAlpha(alpha);

               while (alpha < 1.0F) {

                  panelImg.setAlpha(alpha);

                  try {
                     Thread.sleep(framesPerSecond);
                  } catch (InterruptedException ex) {
                     Logger.getLogger(FrameTeste.class.getName()).log(Level.SEVERE, null, ex);
                  }

                  alpha += alphaTax;

               }

               alpha = 1.0F;

               System.out.println("Alpha: " + alpha);

               try {
                  Thread.sleep(tempoExibicao);
               } catch (InterruptedException ex) {
                  Logger.getLogger(FrameTeste.class.getName()).log(Level.SEVERE, null, ex);
               }

               while (alpha > 0.0F) {

                  panelImg.setAlpha(alpha);

                  try {
                     Thread.sleep(framesPerSecond);
                  } catch (InterruptedException ex) {
                     Logger.getLogger(FrameTeste.class.getName()).log(Level.SEVERE, null, ex);
                  }

                  alpha -= alphaTax;

               }

               alpha = 0.0F;

               System.out.println("Alpha: " + alpha);

            }

         }
      }.start();

   }

   /** This method is called from within the constructor to
    * initialize the form.
    * WARNING: Do NOT modify this code. The content of this method is
    * always regenerated by the Form Editor.
    */
   @SuppressWarnings("unchecked")
   // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
   private void initComponents() {

      panelImg = new org.jdesktop.swingx.JXImagePanel();
      labelImagem = new org.jdesktop.swingx.JXLabel();

      setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

      panelImg.setBorder(javax.swing.BorderFactory.createEtchedBorder());
      panelImg.setMaximumSize(new java.awt.Dimension(1024, 768));
      panelImg.setPreferredSize(new java.awt.Dimension(600, 480));

      labelImagem.setBorder(javax.swing.BorderFactory.createEtchedBorder());

      javax.swing.GroupLayout panelImgLayout = new javax.swing.GroupLayout(panelImg);
      panelImg.setLayout(panelImgLayout);
      panelImgLayout.setHorizontalGroup(
         panelImgLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addGroup(panelImgLayout.createSequentialGroup()
            .addContainerGap()
            .addComponent(labelImagem, javax.swing.GroupLayout.DEFAULT_SIZE, 1472, Short.MAX_VALUE)
            .addContainerGap())
      );
      panelImgLayout.setVerticalGroup(
         panelImgLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addGroup(panelImgLayout.createSequentialGroup()
            .addContainerGap()
            .addComponent(labelImagem, javax.swing.GroupLayout.DEFAULT_SIZE, 1472, Short.MAX_VALUE)
            .addContainerGap())
      );

      javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
      getContentPane().setLayout(layout);
      layout.setHorizontalGroup(
         layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addComponent(panelImg, javax.swing.GroupLayout.DEFAULT_SIZE, 1500, Short.MAX_VALUE)
      );
      layout.setVerticalGroup(
         layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addComponent(panelImg, javax.swing.GroupLayout.DEFAULT_SIZE, 1500, Short.MAX_VALUE)
      );

      pack();
   }// </editor-fold>                        

   /**
    * @param args the command line arguments
    */
   public static void main(String args[]) {

      java.awt.EventQueue.invokeLater(new Runnable() {

         public void run() {
            new FrameTeste().setVisible(true);
         }
      });

   }
   // Variables declaration - do not modify                     
   private org.jdesktop.swingx.JXLabel labelImagem;
   private org.jdesktop.swingx.JXImagePanel panelImg;
   // End of variables declaration                   

   private BufferedImage carregarImagem(String image) {

      try {
        
         BufferedImage img = ImageIO.read(getClass().getResource(image));

         BufferedImage imagem = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(getWidth(), getHeight(), Transparency.TRANSLUCENT);

         Graphics2D g2d = imagem.createGraphics();
         g2d.drawImage(img, 0, 0, imagem.getWidth(), imagem.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null);
         g2d.dispose();

         return img;

      } catch (IOException e) {

         throw new RuntimeException("Não foi possível carregar a imagem");

      }

   }

   private Image getNext() {

      System.out.println("Pointer: " + pointer);

      Image i = images[pointer];

      pointer++;

      if (pointer >= images.length) {

         pointer = 0;

      }

      return i;

   }
}

Alguma idéia? Ou melhor, alguma coisa que eu deixei passar e não vi? XD

vlw! ^^

ViniGodoy

Quanto a imagem crescer sozinha, leia os comentários da linha 70. :wink:

Quanto à imagem perder qualidade, é porque você usa jpg. E os algorítmos de jpg do Java usam um nível muito agressivo de compactação. Aqui mostra como evitar tanta compactação:
http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-compression-quality-when-saving-images-in-java

E aqui mostra como definir os rendering hints do Graphics2D para priorizar qualidade ao invés de performance:
http://download.oracle.com/javase/tutorial/2d/advanced/quality.html

ViniGodoy

Cuidado que existe um erro muitíssimo grave no seu código. Você está fazendo atualizações nos componentes gráficos por fora da Thread do Swing. O método run() ali deveria somente conter o comando de repaint.

Para entender melhor sobre isso:
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
http://java.sun.com/products/jfc/tsc/articles/painting/#swing

Se você persistir nesse erro, sua aplicação pode dar crashes inesperados, ou simplesmente não funcionar em todos os computadores. O Swing não é Thread-safe, e não pode ser manipulado por mais de uma Thread simultânea, além da dele mesmo.

MelissaN

Isso que tem na linha 70 o.o

@Override  
         public void run() {  
  
            try {  
               Thread.sleep(1000);  //Linha 70 xD
            } catch (InterruptedException ex) {  
               Logger.getLogger(FrameTeste.class.getName()).log(Level.SEVERE, null, ex);  
            }

Valeu vini! Vou dar uma olhada! ^^

MelissaN

ViniGodoy:
Cuidado que existe um erro muitíssimo grave no seu código. Você está fazendo atualizações nos componentes gráficos por fora da Thread do Swing. O método run() ali deveria somente conter o comando de repaint.

Para entender melhor sobre isso:
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
http://java.sun.com/products/jfc/tsc/articles/painting/#swing

Se você persistir nesse erro, sua aplicação pode dar crashes inesperados, ou simplesmente não funcionar em todos os computadores. O Swing não é Thread-safe, e não pode ser manipulado por mais de uma Thread simultânea, além da dele mesmo.

Opa! Vou dar um jeito nisso! ^^

ViniGodoy
Ops, desculpe, era do código que você abriu o tópico:
//Também já farei aqui o redimensionamento para o tamanho da tela, evitando gastar tempo com isso na hora de  
          //desenhar na tela.

Como seu código ainda está igual ao meu, ele ainda está redimensionando.

Você pode alterar o carregar imagem para:

private BufferedImage carregarImagem(String image) {  
   try {  
      BufferedImage img = ImageIO.read(getClass().getResource(image));  
      BufferedImage imagem = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(img.getWidth(), img.getHeight(), Transparency.TRANSLUCENT);  
      Graphics2D g2d = imagem.createGraphics();  
      g2d.drawImage(img, 0, 0, null);  
      g2d.dispose();  

      return img;  
   } catch (IOException e) {  
      throw new RuntimeException("Não foi possível carregar a imagem", e);  
   }  
}
MelissaN

Ah ta xD

Troquei, mas não adiantou ‘-’

Olha a saída do tamanho:

run: Pointer: 0 Largura: 1280, Altura: 647 Alpha: 0.0 Pointer: 1 Largura: 1284, Altura: 651 Alpha: 1.0 Alpha: 0.0 Pointer: 2 Largura: 1316, Altura: 683 Alpha: 0.0 Pointer: 3 Largura: 1316, Altura: 683 Alpha: 1.0 Alpha: 0.0 Pointer: 4 Largura: 1348, Altura: 715 Alpha: 0.0 Pointer: 5 Largura: 1348, Altura: 715 Alpha: 1.0 Alpha: 0.0 Pointer: 0 Largura: 1380, Altura: 747 Alpha: 0.0 Pointer: 1 Largura: 1380, Altura: 747 Alpha: 1.0 Alpha: 0.0 Pointer: 2 Largura: 1412, Altura: 779 Alpha: 0.0 Pointer: 3 Largura: 1412, Altura: 779 BUILD SUCCESSFUL (total time: 49 seconds)

Continua crescendo sozinha ‘-’

MelissaN

Descobri porque a imagem estava crescendo sozinha…FreeDesign tava me zoando xD troquei para BorderLayout e problema resolvido ^^

Criado 14 de dezembro de 2010
Ultima resposta 17 de dez. de 2010
Respostas 12
Participantes 2