Results 1 to 6 of 6
  1. #1
    JxAxMxIxN is offline Member
    Join Date
    Dec 2009
    Posts
    6
    Rep Power
    0

    Question Not Getting Enough FPS

    Hi and thanks in advance!
    I'm just getting into graphics with Java and wrote this code to test pixel buffering and frames per second.
    I've got it running smooth and flickerless but i'm only getting about 12 FPS using an 800x600 image.
    What am I missing here?

    Java Code:
    [FONT="Lucida Console"]// GraphicMesser5 by Jamin Szczesny this one is psychadellic
    
    import java.io.*;
    import javax.imageio.*;
    import java.awt.*;
    import java.awt.image.*;
    import javax.swing.*;
    
    public class GraphicMesser5 extends JFrame
    {
    	final static int FWIDTH = 800, FHEIGHT = 600;
    
    	static BufferedImage myImg = null;
    	static StringBuffer myTime = new StringBuffer("");
    	
    	public GraphicMesser5()
    	{
    		super("Graphic Messer Prog");
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		setSize(FWIDTH, FHEIGHT);
    		setLocationRelativeTo(null);
    		setVisible(true);
    
    		this.createBufferStrategy(2);
    	}
    
    	public void paint(Graphics g)
    	{
    		//super.paint(g);
    		Graphics2D g2 = (Graphics2D)g;
            g2.drawImage(myImg, 0, 0, null);
    		g2.drawString(myTime.toString(), 10, 40);
    	}
    
    	public static void main(String[] args) throws InterruptedException
    	{
    		GraphicMesser5 frame = new GraphicMesser5();
    				
    		try
    		{
    			File f = new File("galaxy.jpg"); // Path to an image here
    			myImg = ImageIO.read(f);
    		}
    		catch(Exception e)
    		{
    			JOptionPane.showMessageDialog(null, "image load error");
    			System.exit(0);
    		}
    		
    		int mIW = myImg.getWidth();
    		int mIH = myImg.getHeight();
    		
    		//Set up an Array to hold Image info
    		int[][][] rgb = new int[mIW + 1][mIH + 1][3];
    		
    		//Build the image data array (not worried about alpha)
    		for(int x = 1; x < mIW; ++x)
    		{
    			for(int y = 1; y < mIH; ++y)
    			{
    				rgb[x][y][0] = ((myImg.getRGB(x,y) >> 16) & 0xFF);
    				rgb[x][y][1] = ((myImg.getRGB(x,y) >> 8) & 0xFF);
    				rgb[x][y][2] = ((myImg.getRGB(x,y)) & 0xFF);
    			}
    		}
    
    		//begin infinite draw loop
    		do
    		{
    			long startTime = System.currentTimeMillis();
    			
    			//Do some image conversion stuff...
    			for(int x = 1; x < mIW; ++x)
    			{
    				for(int y = 1; y < mIH; ++y)
    				{					
    						rgb[x][y][0] = (rgb[x][y][0] > 0xF4) ? 0 : rgb[x][y][0] + 0xB;
    						rgb[x][y][1] = (rgb[x][y][1] > 0xF2) ? 0 : rgb[x][y][1] + 0xD;
    						rgb[x][y][2] = (rgb[x][y][2] > 0xEF) ? 0 : rgb[x][y][2] + 0x10;
    						
    						myImg.setRGB(x, y, (rgb[x][y][0] << 16) | (rgb[x][y][1] << 8) | rgb[x][y][2]);
    				}
    			}
    			frame.repaint();
                
    			//Calculate frames per second
    			myTime.setLength(0);
    			myTime.append((int)(1000 / (System.currentTimeMillis() - startTime + 0.0000001) ) + " FPS");
    		}while(0==0);
    
    	}
    }
    [/FONT]

  2. #2
    coltragon is offline Senior Member
    Join Date
    Dec 2009
    Posts
    104
    Rep Power
    0

    Default

    what is the fps you want?

  3. #3
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Neat little program here! Here's another version of it using a JPanel and a public domain image:

    Java Code:
    import java.net.URL;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.image.*;
    
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class GraphicMesser5b extends JPanel {
      // Duke playing the guitar
      public static final String IMAGE_PATH = "http://blogs.sun.com/"
          + "manuelcr/resource/jpg/java-duke-guitar.png";
      private static final int MYTIME_X = 10;
      private static final int MYTIME_Y = 40;
      private BufferedImage myImg = null;
      private StringBuffer myTime = new StringBuffer();
      private int[][][] rgb;
      private int imgWidth;
      private int imgHeight;
    
      public GraphicMesser5b() {
        try {
          URL imageUrl = new URL(IMAGE_PATH); // !! added
          myImg = ImageIO.read(imageUrl);
        } catch (Exception e) {
          JOptionPane.showMessageDialog(null, "image load error");
          System.exit(0);
        }
        imgWidth = myImg.getWidth();
        imgHeight = myImg.getHeight();
        setPreferredSize(new Dimension(imgWidth, imgHeight));
    
        rgb = new int[imgWidth + 1][imgHeight + 1][3];
    
        for (int x = 1; x < imgWidth; ++x) {
          for (int y = 1; y < imgHeight; ++y) {
            rgb[x][y][0] = ((myImg.getRGB(x, y) >> 16) & 0xFF);
            rgb[x][y][1] = ((myImg.getRGB(x, y) >> 8) & 0xFF);
            rgb[x][y][2] = ((myImg.getRGB(x, y)) & 0xFF);
          }
        }
        new MySwingWorker().execute();
      }
    
      private class MySwingWorker extends SwingWorker<Void, Void> {
        private static final long SLEEP_DELAY = 8;
    
        protected Void doInBackground() throws Exception {
          while (true) {
            long startTime = System.currentTimeMillis();
    
            Thread.sleep(SLEEP_DELAY);
            for (int x = 0; x < imgWidth; x++) {
              for (int y = 0; y < imgHeight; y++) {
                rgb[x][y][0] = (rgb[x][y][0] > 0xF4) ? 0 : rgb[x][y][0] + 0xB;
                rgb[x][y][1] = (rgb[x][y][1] > 0xF2) ? 0 : rgb[x][y][1] + 0xD;
                rgb[x][y][2] = (rgb[x][y][2] > 0xEF) ? 0 : rgb[x][y][2] + 0x10;
                myImg.setRGB(x, y, (rgb[x][y][0] << 16) | (rgb[x][y][1] << 8)
                    | rgb[x][y][2]);
              }
            }
            SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                GraphicMesser5b.this.repaint();
              }
            });
            myTime.setLength(0);
            myTime.append((int) (1000 / (System.currentTimeMillis() - startTime + 0.0000001))
                    + " FPS");
          }
          // return null;
        }
      }
    
      protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        if (myImg != null) {
          g2.drawImage(myImg, 0, 0, null);
        }
        g2.drawString(myTime.toString(), MYTIME_X, MYTIME_Y);
      }
    
      private static void createAndShowUI() {
        JFrame frame = new JFrame("Graphic Messer Prog");
        frame.getContentPane().add(new GraphicMesser5b());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
          public void run() {
            createAndShowUI();
          }
        });
      }
    }
    Thanks for sharing this with us!

  4. #4
    JxAxMxIxN is offline Member
    Join Date
    Dec 2009
    Posts
    6
    Rep Power
    0

    Default

    Quote Originally Posted by coltragon View Post
    what is the fps you want?
    coltragon,
    I think my question would have to be: how many more could i get if the code could be written more efficiently (if it can be written more efficiently).

  5. #5
    JxAxMxIxN is offline Member
    Join Date
    Dec 2009
    Posts
    6
    Rep Power
    0

    Default

    Fubarable,

    I like some of the new implementations, especially making it a more portable code.
    I've noticed however that the FPS is a little lower with the new code (from 12 to about 10 on my computer with my original 800x600 image - even when removing the time delay and some other things that could possibly make it lag).
    Do you think I'd be able to get it to go any faster, or do you think i've maxed out the processing speed for this implementation.
    (i mean it's still pretty darn fast but...)


    Thanks again and i'm glad you liked my code!

  6. #6
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default

    I changed fubarables code like the following to try to test how long it takes to actually modify the image:

    Java Code:
            long start = (System.currentTimeMillis());
    
            for (int x = 0; x < imgWidth; x++) {
              for (int y = 0; y < imgHeight; y++) {
                rgb[x][y][0] = (rgb[x][y][0] > 0xF4) ? 0 : rgb[x][y][0] + 0xB;
                rgb[x][y][1] = (rgb[x][y][1] > 0xF2) ? 0 : rgb[x][y][1] + 0xD;
                rgb[x][y][2] = (rgb[x][y][2] > 0xEF) ? 0 : rgb[x][y][2] + 0x10;
                myImg.setRGB(x, y, (rgb[x][y][0] << 16) | (rgb[x][y][1] << 8) | rgb[x][y][2]);
              }
            }
    
            String generate = "Generate: " + (System.currentTimeMillis() - start);
            System.out.println(generate);
    I also added the same type of code around the drawImage() method. I was surprised to get wide variances 60-93ms for updating the image and 47-78ms for drawing the image. Then I realized the variance was probably caused between the thread switching between the EDT to paint the image and the worker Thread to change the image.

    I also noticed a diagonal line appearing in the image. I assume this is because the image is being repainted before the complete image has been updated.

    I then changed the code to the following. Now all the code is executing on the EDT. I no longer see the diagonal lines. The timings are constant for painting the image and updating the image. On my computer the times are 32 and 47, for a total of 79ms which would imply a best possible frame rate of about 12.

    So unless you can optimize the loop that updates the image I don't think you can do any better.

    Java Code:
    import java.net.URL;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.image.*;
    import java.awt.event.*;
    
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class GraphicMesser5c extends JPanel
      implements ActionListener
    {
      // Duke playing the guitar
      public static final String IMAGE_PATH = "http://blogs.sun.com/"
          + "manuelcr/resource/jpg/java-duke-guitar.png";
      private static final int MYTIME_X = 10;
      private static final int MYTIME_Y = 40;
      private BufferedImage myImg = null;
      private StringBuffer myTime = new StringBuffer();
      private int[][][] rgb;
      private int imgWidth;
      private int imgHeight;
      private Timer timer;
    
      public GraphicMesser5c() {
        try {
          URL imageUrl = new URL(IMAGE_PATH); // !! added
          myImg = ImageIO.read(imageUrl);
        } catch (Exception e) {
          JOptionPane.showMessageDialog(null, "image load error");
          System.exit(0);
        }
        imgWidth = myImg.getWidth();
        imgHeight = myImg.getHeight();
        setPreferredSize(new Dimension(imgWidth, imgHeight));
    
        rgb = new int[imgWidth + 1][imgHeight + 1][3];
    
        for (int x = 1; x < imgWidth; ++x) {
          for (int y = 1; y < imgHeight; ++y) {
            rgb[x][y][0] = ((myImg.getRGB(x, y) >> 16) & 0xFF);
            rgb[x][y][1] = ((myImg.getRGB(x, y) >> 8) & 0xFF);
            rgb[x][y][2] = ((myImg.getRGB(x, y)) & 0xFF);
          }
        }
    
    	new Timer(100, this).start();
    
      }
    
    	public void actionPerformed(ActionEvent e)
    	{
    		repaint();
    
    		long start = System.currentTimeMillis();
    		int dim0 = 0;
    
            for (int x = 0; x < imgWidth; x++) {
              for (int y = 0; y < imgHeight; y++) {
                rgb[x][y][0] = (rgb[x][y][0] > 0xF4) ? 0 : rgb[x][y][0] + 0xB;
                rgb[x][y][1] = (rgb[x][y][1] > 0xF2) ? 0 : rgb[x][y][1] + 0xD;
                rgb[x][y][2] = (rgb[x][y][2] > 0xEF) ? 0 : rgb[x][y][2] + 0x10;
                myImg.setRGB(x, y, (rgb[x][y][0] << 16) | (rgb[x][y][1] << 8) | rgb[x][y][2]);
              }
            }
    
    		String generate = "Generate: " + (System.currentTimeMillis() - start);
    		System.out.println(generate);
    
            myTime.setLength(0);
    		myTime.append(generate);
    	}
    
      protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
    
    
    	long start = System.currentTimeMillis();
    
        if (myImg != null) {
          g2.drawImage(myImg, 0, 0, null);
        }
    
    	System.out.println("Repaint: " + (System.currentTimeMillis() - start));
    
        g2.drawString(myTime.toString(), MYTIME_X, MYTIME_Y);
      }
    
      private static void createAndShowUI() {
        JFrame frame = new JFrame("Graphic Messer Prog");
        frame.getContentPane().add(new GraphicMesser5c());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
          public void run() {
            createAndShowUI();
          }
        });
      }
    }

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •