2011-06-25 44 views
11

Tôi muốn biết cách tôi xử lý các hoạt động pixel tốt nhất trong Java. Tôi đang sử dụng swing và vẽ một hình chữ nhật 1 x 1 pixel là khủng khiếp chậm. Tôi cần tối thiểu 60 khung hình/giây, mà không cần sử dụng quá nhiều tài nguyên. Liệu sẽ có một hình ảnh đầu tiên có nghĩa là điều này có thể được lưu thành công không? Hoặc là một ý tưởng tồi nói chung để làm điều này với Java và tôi có cần phải gắn bó với C hay cách khác không?Thao tác với pixel nhanh Java

Tôi đang ở đầu viết một raycaster và kể từ khi mởCL, mà tôi đang sử dụng, có một trình bao bọc cho Java, tôi thích làm việc trong Java.

+1

tôi muốn khuyên bạn nên đọc lên trên khái niệm về hình ảnh trung gian. Đây là một ví dụ - http://www.java2s.com/Code/Java/Advanced-Graphics/IntermediateImages.htm – mre

+0

Tôi nghĩ kỹ thuật Intermidiate Images nằm dọc theo những dòng tôi đã mô tả; một hình ảnh. Tuy nhiên tôi không quen thuộc với các speedresults này trong Java, đó là những gì tôi muốn biết. – RobotRock

+0

Kỹ thuật này sẽ không nhận được kết quả 60fps trong Java, vẫn còn quá chậm. – RobotRock

Trả lời

5

Thêm vào gợi ý @ camickr của:

Tạo một BufferedImage (BI), bọc nó trong một IconImage, thiết lập nó như là biểu tượng cho một JLabel. Vẽ các thay đổi lên BI và gọi lại cho JLabel() để xóa chúng. thay đổi màn hình. Caching hình ảnh một phần trong BI sẽ làm giảm số lượng công việc cho thói quen vẽ. Nó chỉ cần để blit hình ảnh, không làm cho hình ảnh. Sử dụng SwingWorkers để triển khai các chủ đề nền để chạy các phép tính và chuyển kết quả trở lại cho EDT để vẽ.

Miễn là bạn đang nói về một hình ảnh tĩnh, điều đó sẽ hoạt động tốt. Nếu bạn đang xem xét một cái gì đó giống như một trò chơi video (một số hình ảnh cố định và hình ảnh chuyển động khác) hãy xem VolatileImage. Có một mô tả tốt ở đây: http://gpwiki.org/index.php/Java:Tutorials:VolatileImage

Cập nhật:

Sau đây mang lại cho tôi một chút so với 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

Tôi nhận được 10fps lấp đầy màn hình bằng pixel trên hình ảnh 1024x768. Bất kỳ ý tưởng làm thế nào để tăng tốc độ này? Tôi đang sử dụng kỹ thuật như bạn đã nói và chạy một vòng lặp thực sự trong khi hiển thị. – RobotRock

+0

Bạn sẽ nhận được loại hiệu suất nào nếu bạn chỉ hiển thị cho BI và không thực sự vẽ nó lên màn hình? Thông thường các nút cổ chai trong truy tìm tia là nhiều hơn trong các tính toán hơn so với các bản cập nhật màn hình. Hãy thử chỉ xuất ra System.currentTimeMillis() mỗi khi bạn hoàn thành giá trị của màn hình tính toán. –

+0

Tôi đang vẽ các pixel không được tính toán, vì vậy chỉ cần điền đồng bằng pixel màn hình theo pixel. Tại 320x240 tôi nhận được hơn 100 khung hình/giây, ở mức 1024x768 nó giảm xuống 10. Nếu tôi rời khỏi repaint(), nó sẽ không thay đổi kết quả. – RobotRock

4

Sử dụng BufferedImage và phương thức setRGB (...). Sau đó, bạn vẽ toàn bộ hình ảnh trong thói quen vẽ của bạn.

+0

Tôi có thể tuân thủ các yêu cầu (60 khung hình/giây) theo cách này (với độ phân giải 1024x768) không? – RobotRock