What is the fastest way to draw pixels in Java
Asked Answered
E

5

8

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.

Execratory answered 30/11, 2012 at 3:56 Comment(1)
Though maybe a slight tangent from what you had in mind, you might want to try some GPU programming techniques. You can read here for an adaptation of the Million Particle example using OpenCL.Situation
H
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

Haiku answered 4/12, 2012 at 9:50 Comment(0)
S
1

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

So answered 4/12, 2012 at 10:7 Comment(0)
M
1

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.

Marbleize answered 14/12, 2012 at 23:19 Comment(0)
D
1

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

Decided answered 7/5, 2016 at 19:26 Comment(0)
T
-2

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

}
}
Twain answered 27/1, 2016 at 3:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.