2011-06-25 17 views
11

Mi piacerebbe sapere come gestirò le operazioni pixel meglio in Java. Sto usando swing e disegnare un rettangolo di 1 a 1 pixel è terribilmente lento. Ho bisogno di ottenere almeno 60 fps, senza usare troppe risorse. Blittare un'immagine potrebbe significare che questo potrebbe essere ottenuto con successo? O è una cattiva idea in generale fare questo con Java e devo attenermi a C o un'altra alternativa?Operazioni pixel veloci Java

Sono all'inizio della scrittura di un raycaster e dal momento che openCL, che sto usando, ha un wrapper per Java, preferisco lavorare in Java.

+1

io suggerirei di leggere sul concetto di immagini intermedie. Ecco un esempio: http://www.java2s.com/Code/Java/Advanced-Graphics/IntermediateImages.htm – mre

+0

Penso che la tecnica Intermidiate Images sia sulla falsariga che ho descritto; blitting un'immagine. Tuttavia non ho familiarità con i risultati di velocità di questo in Java, che è quello che voglio sapere. – RobotRock

+0

Questa tecnica non otterrà risultati a 60fps in Java, ancora troppo lenti. – RobotRock

risposta

5

aggiunta al suggerimento di @ camickr:

Creare un BufferedImage (BI), avvolgerlo in un iconImage, impostarlo come l'icona di un JLabel. Dipingi le modifiche nella BI e chiama JLabel's repaint() per svuotare quelle. cambia allo schermo. La memorizzazione nella cache dell'immagine parziale in una BI riduce la quantità di lavoro per la routine di pittura. Ha solo bisogno di fondere l'immagine, non rendere l'immagine. Utilizzare SwingWorkers per distribuire thread in background per eseguire i calcoli e restituire i risultati all'EDT per la verniciatura.

Finché si parla di un'immagine statica, funzionerà correttamente. Se stai considerando qualcosa di più simile a un videogioco (alcune immagini fisse e altre immagini in movimento) dai un'occhiata a VolatileImage. C'è una buona descrizione qui: http://gpwiki.org/index.php/Java:Tutorials:VolatileImage

Aggiornamento:

Di seguito mi dà un po 'più di 80 fps:

public class Demo extends javax.swing.JPanel { 
    private Image src = null; 
    public Demo() { 
     new Worker().execute(); 
    } 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (src != null) g.drawImage(src, 0, 0, this); 
    } 
    private class Worker extends SwingWorker<Void, Image>{ 
     private final Color[] colors = { Color.red, Color.green, Color.blue }; 
     protected void process(List<Image> chunks){ 
      for (Image bufferedImage : chunks){ 
       src = bufferedImage; 
       repaint(); 
      } 
     } 
     protected Void doInBackground() throws Exception{ 
      int frames = 0; 
      int[] mem = new int[1024 * 768]; 
      long start = System.currentTimeMillis(); 
      long end = start + 15000; 
      long last = start; 
      while (last < end){ 
       int col = colors[frames % colors.length].getRGB(); 
       for (int y = 0; y < 768; y++) 
        for (int x = 0; x < 1024; x++) 
         mem[x + y * 1024] = col; 
       Image img = createImage(new MemoryImageSource(1024, 768, mem, 0, 1024)); 
       BufferedImage bi = new BufferedImage(1024, 768, BufferedImage.TYPE_INT_ARGB); 
       Graphics2D g2 = bi.createGraphics(); 
       g2.drawImage(img, 0, 0, null); 
       g2.dispose(); 
       publish(bi); 
       last = System.currentTimeMillis(); 
       frames++; 
      } 
      System.err.println("Frames = " + frames + ", fps = " + ((double) frames/(last - start) * 1000)); 
      return null; 
     } 
    } 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run(){ 
       JFrame jf = new JFrame(); 
       jf.getContentPane().add(new Demo(), BorderLayout.CENTER); 
       jf.setSize(1024, 768); 
       jf.setVisible(true); 
      } 
     }); 
    } 
} 
+0

Ottengo 10 fps riempiendo lo schermo con pixel su un'immagine 1024x768. Qualche idea su come accelerare questo? Sto usando la tecnica come hai detto tu e eseguendo un loop while while per il rendering. – RobotRock

+0

Che tipo di prestazioni ottieni se esegui il rendering sulla BI e non la dipingi effettivamente sullo schermo? In genere i colli di bottiglia nella ray tracing sono più nei calcoli rispetto agli aggiornamenti dello schermo. Prova ad emettere solo System.currentTimeMillis() ogni volta che completi i calcoli di una schermata. –

+0

Sto disegnando pixel non calcolati, quindi riempi semplicemente lo schermo pixel per pixel. A 320x240 ottengo 100+ fps, a 1024x768 si scende a 10. Se tralascio il repaint(), non cambierà i risultati. – RobotRock

4

Utilizzare un metodo BufferedImage e il metodo setRGB (...). Quindi disegni l'intera immagine nella tua routine di pittura.

+0

Posso rispettare i requisiti (60 fps) in questo modo (con una risoluzione di 1024x768)? – RobotRock

Problemi correlati