What is the fastest way to draw pixels in Java

*爱你&永不变心* 提交于 2019-12-04 08:12:36

问题


I have some code that generates particles at random locations, and moving in random directions and speed.

Each iteration through a loop, I move all the particles, and call repaint on my jpanel.

For 1,000 particles, I'm getting around 20 to 30 frames per second. I plan to eventually have 100,000 to 1,000,000 particles.

In paint, I only create a new bufferedimage if the window has changed size. I draw the pixels to the bufferedimage, and then call drawImage to display the image.

Each particle is a single pixel, and I have determined that all the time is taken up actually drawing the pixels. So, increasing the number of particles will drastically reduce the frame rate.

I've tried g.drawline(x,y,x+1,y), img.setRGB(x,y,color), getting an array of pixels by calling img.getRaster().getDataBuffer().getData(), then setting pixelData[y*width+x] = color.

I only get a small difference in the frame rate with these different ways of drawing the pixels.

Here's my question: What is the fastest way to draw pixels? Is bufferedimage even the way to go?

Thanks.


回答1:


I think the direct pixelmanipulation via the databuffer of the bufferedimage is the fastest way to draw something with the standard-library because you reduce the graphics object overhead to a minimum.

But as Perception said if you want to display 100'000 particles or more you should consider the GPU programming with OpenCl.

LWJGL for a small and easy to use Java-OpenGL/CL/AL binding




回答2:


Try using java.awt.image.VolatileImage. It can potentially be used with full hardware acceleration without any CPU rendering.




回答3:


You should be getting a much faster frame rate on a standard computer when using the img.getRaster().getDataBuffer().getData(). I know this for a fact because I can paint the entire screen in 20-30 frames per second and the screen has 1,000,000 pixels total. I obtained this speed by cutting the rendering routine in two and using two threads. My CPU is 1.5ghz.

For this reason, I think that you may have made a coding error in moving the pixels. Remember: creating a new object is a 100x times longer operation than addition. Also see if you can cut out any if statements.

Also, this may be silly, but I assume you are only calling img.getRaster().getDataBuffer().getData() once per frame?

On a related note, Drawing multi pixel particles will naturally take a long time.




回答4:


I see a huge improvement in setting the bytes the data of a BufferedImage. To do that you'll need get the data from the BufferedImage, turn it into a byte array, set each byte (depending on the type of the image, the byte arrangement will be different. For example: ARGB will have one byte for alpha, one for red, one for green, one for blue. One pixel will be a block of 4 consecutive bytes.) Read more about getting the data here




回答5:


Never call repaint(); that's for noobs, play around with this where you don't have to call repaint();. That method has caused me so much pain and discomfort in the last 2 months, and I am sad nobody told me there is another way. 1,000,000 particles will get expensive real fast, so you may want to consider a Monte Carlo method, see http://raytracey.blogspot.com/ for cheaper rendering options. I don't know if you can afford manipulation of all of these particles while adhering to 20-30fps, I just watched a 10 second fluid simulation that took 3 weeks on a 2.4ghz 6gb ram machine. I apolagise because my only experience in the BufferedImage is importing .png's to draw with Graphics g. I worked on a project that was very computationally expensive very recently and with the timeline I was not able to gpu accelerate my program, so if you're in the same boat, try this package pet;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import javax.swing.*;


public class pet extends JPanel implements MouseListener{
public static JFrame frame = new JFrame("frame");
public pet() throws IOException{
 setPreferredSize(new Dimension(870, 675));         //configuring panel
 addMouseListener(this);
}
public static void main(String[] args) throws IOException{
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JComponent newContentPane = new pet();
    newContentPane.setOpaque(true);
    frame.setContentPane(newContentPane);
    frame.pack();
    frame.setVisible(true);
    frame.addMouseListener(new pet());
}
public void paintRectangleAtPoint(Graphics g, int x, int y){
g.setColor(Color.BLACK);
g.drawRect(x, y, 100,100);
}
public void paintStuff(Graphics g, int x, int y){
g.setColor(Color.BLACK);
g.drawRect(x, y, 100,100);
}
@Override
public void mouseClicked(MouseEvent e) {
paintStuff(frame.getGraphics(),e.getX(), e.getY());

}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub

}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub

}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub

}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub

}
}


来源:https://stackoverflow.com/questions/13638793/what-is-the-fastest-way-to-draw-pixels-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!