Need to read/paint large images fast. Help!

Hello Java community,
I am having trouble writing a program which can read large image files from disk (~ 1-2 MB) and paint them to the screen while maintaining a frame rate of 15 or 20 fps. Right now I am doing this through a Producer/Consumer scheme. I have one thread which constantly creates ImageIcons (using the constructor which accepts a String file path), and places them on a blocking queue (production) with a maximum capacity of 5 or 10. I have a second thread which removes an image from the queue (consumption) and paints it to the JFrame every so many milliseconds to honor the frame rate.
My problem is that this approach is not fast enough or smooth enough. With smaller images it works fine, but with larger images it cannot maintain a high frame rate. It also seems to consume more memory than it should. I am assuming that once I paint a new ImageIcon, the old one goes out of scope and is freed from memory by the Garbage Collector. However, even with a queue capacity of 5 or 10, I am getting out-of-memory exceptions. I plan on trying the flush() method of the Image class to see if that helps to recover resources. After searching around a bit, I see that there are many different ways to read/load an image, but giving a local path to an ImageIcon and letting it load the image seems to be a safe way to go, especially because in the documentation for ImageIcon, it says that it pre-loads the image using Media Tracker.
Any help, ideas, or links would be appreciated!
Thanks,
Elliot

Thanks for another insightful response.
I've played a bit more, so let me update you. I am preloading images, the blocking queue (FIFO) is full when the animation begins. Right now, the queue capacity is 10, but for smaller images it can be closer to 40 or 50. The image reader queue reads images and places them in this queue. Oddly, the problem does not seem to be that the reader thread can't keep up. I added a print statement which displays the size of the queue before each removal and it remains very close to the capacity, at least for the my test images which are only 400 x 400, approximately 100 KB each.
I've tried animating the images in two distinct ways. My first approach, as I mentioned in the original question, was to animate the images using purely swing components and no manual painting of any kind. This is always nice because it frames the image perfectly and the code is minimal. To accomplish this I simply had the image reader thread pass in the image path to the constructor of ImageIcon and put the resulting ImageIcon in the queue. The animator thread had a simple swing timer which fired an ActionEvent every so-many milliseconds (in the event dispatch thread). In the actionPerformed method I simply wrote a few lines to remove the head of the queue and I used the JLabel setIcon(ImageIcon) to update the display. The code for this was very nice, however the animation was choppy (not flickering).
In my second approach, which was a bit longer, I created a class called AnimationPanel which extended JPanel and implemented Runnable. I simply overrode paintComponent and inside I painted a member Image which was set in the thread loop. Rather than storing ImageIcons, the queue stored Images. The reader thread used ImageIO.read(...) to generate an Image. I used simple logic in the thread loop to monitor the fps and to fire repaints. This approach suffered from the same problem as the one above. The animation was choppy.
I found the following things to be true:
- the reader can keep up with the animator
- if I run the image reader and perform a basic polygon animation, both of my approaches animate smoothly at high frame rates. In other words, it's not the work (disk reads) being done by the reader that is causing the lag
- I believe the slowness can be attributed to the following calls: label.setIcon(imageIcon) or g.drawImage(image, 0, 0, this). This leads me to believe that the images are not fully processed as they are being placed on the queue. Perhaps Java is waiting until they are being used to fully read/process the images.
- I need to find a way to process the images fully before trying to paint them, but the I felt that my approaches above were doing that. I considered have the reader frame actually generate a JLabel or some object that can be displayed without additional processing.
- your idea about AWT components is a good one and I plan on trying that.
Elliot

Similar Messages

  • Read large images fast?

    Hello all,
    I'm not sure if this is the appropriate place to post this but here goes. I am working on creating an image viewer application and so far its going great. But i've noticed one problem when reading large images typically over 1 megabyte in size. These images using <tt> ImageIO.read() </tt> takes anywhere from 1 to two seconds to finish loading. I've searched all over the web for faster methods of reading large images but I haven't had any luck. Here is an example of what code i'm using to read an image.
    try {
         BufferedImage b = ImageIO.read(someLargeImageFile); // this is slow for images over 1MB in size.
    } catch(Exception err) {
    }So my question is does anyone have any tips or tricks I could use to read large images faster. I see programs like iPhoto reading images up to 5MB in size in under one second. Just wondering what I could do to read these kind of images just as fast.
    Thank you for your help :)
    Nathan D.

    user5287726 wrote:
    What version of the JVM are you using? How much RAM is available? What OS are you running? What kind of storage are the images on? How many other users and how many other processes are fighting over that storage?
    And if the JVM is recent and has a lot of RAM available, and you have eliminated any storage bottlenecks, have you tried Java Advanced Imaging?
    http://java.sun.com/javase/technologies/desktop/media/jai/
    I've used it to process image files in the hundreds of MB size range, and while I don't have any benchmarks handy I'd be surprised if those files were processed much if any slower than the processing speed you're getting with your much smaller files.I'm using the most current JVM, lots of RAM is available the application i'm developing can use up to 1.5 GB of RAM on the current machine. I'm using Mac OS 10.6 but the problem occurs on all operating systems i've tested it on including, Windows XP, Windows Vista, Windows 7, Mac OS 10.4, 10.5, 10.6, and Linux. I develop the software on an iMac which I just recently reformatted to factory settings so there are little to no other processes fighting over that storage.
    I've heard of JAI and just really never gave it a second thought cause I never really needed any more features then ImageIO gave me. However does Java Advanced Imaging read images in a different way then ImageIO would? I'm beginning to think that it isn't so much the actual size of the file but the dimensions. Even small files in the 100kilobyte range load slow because there dimensions are large for example 3000x3000. Though i'm assuming those 100 megabyte images you processed with speed also had large dimensions?
    Now for a moment I was thinking it was something in the BufferedImage class that was taking a long time to process and not the ImageIO class. However the following proves that wrong.
    try {
         ImageIO.read(someLargeImageFile);
    } catch(Exception err) {
    }The above code doesn't even use a buffered image so I guess its down to something in the ImageIO class. I'll see if I have better luck with JAI but can someone explain why this might be faster then using ImageIO.read() or if there are any other tips or ticks to reading large images such as these faster?
    Thank you for your help :)
    Edited by: neptune692 on Jan 6, 2011 8:35 AM

  • Need to hold very large number - please help

    Hello all,
    I am working with programming the SSH handshake and need to represent a very large number in order to get it to work correctly. The number is:
    179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194467627007
    which is: 1.7 *10^318
    and we know the largest double is:
    1.7976931348623157E308
    Can someone please help me with representing this number? It is a very large prime number that is used in the key exchange for SSH.
    Thank you all for you time
    Max

    And who's the slowest old sod again?
    This is amazing: I read a new topic, no repliesyet,
    I check it again, nothing yet,
    I craft my reply and presto: some quick fingersbeat
    me to it again ...Grolsch makes slow :P ;)It's still only 11:45ag ... and I'm still waiting ;-)
    Jos

  • Creating Large Image of SWF for Printing

    I need to create very large images of my SWFs for printing
    purposes without a degradation of image quality. Any
    suggestions?

    If anyone else had this problem you can see the neat script that was written to solve it in the Automator forum. Go here:
    http://discussions.apple.com/thread.jspa?threadID=849139&tstart=0

  • Read character from Image area

    Hi every body,
    I need to read character from image area(jpg image).
    regards,
    sundar

    Step 1: Read the "RGB" values of each pixel using getRGB(x,y)
    Step 2: Write this info in an File as *1.txt
    Step 3: Get samples for each character and store it in a separate file.
    Step 4: ........ its a very long process
    so u refer optical character recognition... if interested let me know it.. i have achieved it..
    Regards
    rinaldo

  • Need Oil Paint filter enhancement to work with large images

    As Adobe is not supporting the Oil Paint filter with the next version of PhotoShop, can the code for this filter be made available for open source development?
    I desperately need to utilize effects that can be created using Oil Paint, but I have to have the code altered so I can apply these effects to relatively large image sizes.
    The current filter works fine for relatively small image sizes around 500kb or so, but has little or no effect on images of around 100mb.
    I need to have this capability. I would like to have the code of the current filter altered to be able to achieve this.
    I realize I will need to continue using PhotoShop 6 as the code will not be supported with the next version of PhotoShop.
    If this is not the correct forum to post this, please let me know where I should be asking this question.
    Thank you in advance for any insight and advice you may have.

    What's the problem you're having with applying it to an 80 MB image?  Is it that the effects don't scale up enough?
    Technically it can run on large images if you have the computer resources...  I've just successfully applied it to an 80 MB image, and with the sliders turned all the way up it looks pretty oil painty, though it kind of drops back into a realistic looking photo when zoomed out...
    If it's just that the sliders can't go high enough, given that it's a very abstract look you're trying to achieve, have you considered applying it at a downsized resolution, then upsampling, then maybe applying it again?  This is done that way...
    Oh, and by the way, Oil Paint has been removed from Photoshop CC 2014, so if you're planning a business based on automatically turning people's large photos into oil paintings you should assume you'll be stuck with running the older Photoshop version.
    -Noel

  • Help needed in optimizing painting logic

    Hi,
    I am working on a Applet where i have to do a lot of painting, the applet is kind of microsoft project, where u can define a activity as a rectangle and then u can select the rectangle and drag it to some other date,
    i am posting a code below, which i am using to draw all the rectangles,
    but some times when there is a lot of data scrolling is really very slow
    Can any one look at the code, and let help me optimize it,
    U can copy the code, compile and run it to see what i mean by slow,
    just in class data , change the value 600 to some thing less like 50 and it works very fast
    //start code
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.ArrayList;
    public class TestDisplaySize extends JFrame
         private     JScrollPane scrollPane ;
         private MyPanel panel ;
         public TestDisplaySize()
              super("layered pane");
              this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
              panel = new MyPanel();
              scrollPane = new JScrollPane(panel);
              Container contentPane = this.getContentPane();
              contentPane.add(scrollPane, BorderLayout.CENTER);
              setSize(new Dimension(800,600));
              this.setVisible(true);
              JViewport viewPort = scrollPane.getViewport();
         class MyPanel extends JPanel
              private int height;
              private int last;
              private Data data;
              public MyPanel()
         this.setBackground(Color.white);
         this.setOpaque(true);
         data = new Data();
         int size = data.getSize();
         height = size * 50;     
         last = data.getDataSize(0);
         int last1 = last -1;
         int length = data.getX(0, last1) + 100;
         System.out.println ("Lenght " + length + " height " + height);
         setPreferredSize(new Dimension(length, height) );     
         public void paintComponent(Graphics g)
    super.paintComponent(g);
    setBackground(Color.white);
    Rectangle r = scrollPane.getViewport().getViewRect();
    g.setClip((Shape)r);
    g.setColor(Color.blue);
    int x = 0;
    for(int i = 0; i < last ; i++)
         x +=60;
         g.drawLine(x, 0, x, height);
         g.drawString(String.valueOf(i), x, 10);
    int size = data.getSize();
    int width = 30;
    int height = 20;
    int yAxis = 20;
    g.setColor(Color.cyan);
    for(int i = 0; i < size; i++)
         int dataSize = data.getDataSize(i);
         for(int k = 0; k < dataSize; k++)
              int xAxis = data.getX(i, k);
              g.fill3DRect(xAxis, yAxis, width, height, true);
         yAxis = yAxis + 50;
    private class Data
              private ArrayList totalData = new ArrayList();
              public Data()
                        for(int i = 0; i < 600; i++)
                        ArrayList data = new ArrayList();
                        int l = 50;
                        for(int k = 0; k < 600; k++)
                             data.add(new Integer(l));
                             l = l + 50;
                        totalData.add(data);
              public int getSize()
                   return totalData.size();     
              public int getDataSize(int i)
                   return ((ArrayList)totalData.get(i)).size();     
              public int getX(int x, int y)
                   ArrayList data = (ArrayList)totalData.get(x);
                   Integer i = (Integer)data.get(y);
                   return i.intValue();
         public static void main(String args[])
         new TestDisplaySize();

    You should only paint what is visible. For example if you are presenting a grid of 100 x 100 boxes. And each box is 20 pixels wide and 20 pixels high, then that would create an <image> the size of 2000 x 2000. That is big ;-)
    What you want to do, is calculate what portion of the <image> that is viewable in your scrollpane and then only perform the paint operations on those boxes. For example, if the viewports width is 200 and its hieght is 80, then you should only paint 10 x 4 boxes (40 boxes total, each 20x20 pixels in size) -- The trick is figuring out what boxes need to be painted.!! I'll leave that up to you, but should be able to find code examples on the net doing something of this sort.
    Hope this helps, and makes sense.
    Cory

  • Help redrawing large image

    I have a 600x600 applet that redraws each pixel (drawing the mandelbrot set).
    Right now (just using a for loop and paint() method) it swipes down drawing the pixels and takes a couple seconds.
    I tried to draw an image offscreen and paint that on but it still took the same amount of time since it needed to still draw each pixel to the offscreen image.
    I was wondering what I need to do to make it faster. Would threads be the solution?
    Thanks

    Kurbz wrote:
    iterations = getIterations(real, imaginary);  //method that computes color for each pixel
    if (iterations == maxIterations)
         g.setColor(Color.BLACK);
    else {
         red = (iterations % 32) * 7;
         green = (iterations % 16) * 14;
         blue = (iterations % 128) * 2;
         g.setColor(new Color(red,green,blue));
    g.drawLine(x,y,x,y);
    My experiments show using the WritableRaster of a BufferedImage to be about 3 times faster than using setColor and drawLine (ignore hackish code):
    import java.awt.*;
    import java.awt.image.*;
    import java.util.*;
    import javax.swing.*;
    public class GraphicsTest1 {
       static volatile boolean isPainted = false;
       private static final Dimension dim = new Dimension(800, 800);
       public static void main(String[] args) {
          final JFrame frame = new JFrame();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          final BufferedImage image = GraphicsEnvironment.getLocalGraphicsEnvironment()
             .getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(
                   dim.width, dim.height, BufferedImage.OPAQUE);
          final JPanel panel = new JPanel() {
             @Override
             protected void paintComponent(Graphics g) {
                if ( isPainted ) {
                   g.drawImage(image, 0, 0, null);
                } else {
                   super.paintComponent(g);
          final Thread t = new Thread(new Runnable() {
             @Override
             public void run() {
                WritableRaster raster = image.getRaster();
                Graphics2D gr = image.createGraphics();
                Random rnd = new Random();
                long nanos = System.nanoTime();
                for ( int x = 0; x < dim.width; x++ ) {
                   for ( int y = 0; y < dim.height; y++ ) {
                      int r = rnd.nextInt(128)+128;
                      int g = rnd.nextInt(128)+128;
                      int b = rnd.nextInt(128)+128;
    //                  setPixel(raster, x, y, r, g, b);
    //                  setPixel(image, x, y, r, g, b);
                      setPixel(gr, x, y, r, g, b);
                System.out.printf("Seconds taken: %f%n", (System.nanoTime() - nanos) / 1000000000.0);
                gr.dispose();
                isPainted = true;
                panel.repaint();
          t.start();
          frame.setContentPane(panel);
          frame.setVisible(true);
          frame.setSize(dim.width, dim.height);
       private static void setPixel(WritableRaster raster, int x, int y, int r, int g, int b) {
          raster.setPixel(x, y, new int[] {r, g, b});
       private static void setPixel(BufferedImage image, int x, int y, int r, int g, int b) {
          image.setRGB(x, y, r << 16 | g << 8 | b );
       private static void setPixel(Graphics2D gr, int x, int y, int r, int g, int b) {
          gr.setColor(new Color(r, g, b));
          gr.drawLine(x, y, x, y);
    }

  • Help needed with multiple and seperate image galleries on 1 site

    I'm looking for a simple way to create and manage multiple image galleries (about 100) on a single website. I work for an architect and have a site which has our project portfolio and every project has a page containing a write up with a gallery of only 6 images.  Currently I am using .css to run it. If you hover over one of the 6 thumbnails it opens up a larger image in the same div container. If you move the cursor off the thumbnail the main image goes away leaving a default background. The only problem is my bosses now want each image to be retained in view until you hover over the next thumbnail.
    Any ideas anyone?

    I've never see a performance issue with IsSameObject(), although I understand your issue, it seems to be pretty fast.
    Saving a global reference to a jclass prevents it from being GC'd, I don't think it prevents it from being unloaded.
    I'm not sure I understand your comment about jmethodID's being different for the same method. Technically, the jmethodID is unique for each class image loaded and class loader. So if a class is unloaded and reloaded, or the same class managed to get loaded by two different class loaders, then you might see multiple jmethodID values. But do you know that is happening?
    I have seen some race conditions on the JVMTI event callbacks around Method Entry/Exit and Thread Start/End. If you don't use some rawmonitors to protect yourself, you could be executing your callback code for the methodExit event while the thread goes away out from under you. I don't know if that could be an issue, but it caused me to scratch my head quite a bit when I ran into it.

  • HELP! How do I link small thumbnail to larger image on same page?

    hello, everyone! I'm working in dreamweaver cs4 and am having no luck!
    see below - I'm trying to link the small thumbnails to the larger image on the left. in other words, when a thumbnail is chosen it's corresponding image would open on the left. I have tried mouse-over effects and image swap behaviors but still no luck. either the larger image replaces the thumbnail or a brand new window opens up with the larger image.
    I want all effects to stay on the same page. any help would be greatly appreciated!

    Hi There:
    Not sure how you have designed your page but here is a simple sample code on how you can do this with javascript and on mouseover event:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
    <style type="text/css">
    div#left {
    display:none;
    </style>
    <script language="javascript" type="text/javascript">
    <!--
    function showImage(obj) { //v2.0
    //alert(obj);
    document.getElementById(obj).style.display='block';
    //  return eval(obj)
    function hideImage(obj) { //v2.0
    //alert(obj);
    document.getElementById(obj).style.display='none';
    //  return eval(obj)
    //-->
    </script>
    </head>
    <body>
    <div id="left" style="float:left;width:200px;"><img src="left.jpg" width="180" height="273" alt="large" /></div>
    <div id="right" style="float:right;width:200px;"><img src="thumbnail.jpg" alt="small" style="cursor:pointer;" width="57" height="228" onmouseover="showImage('left');" onmouseout="hideImage('left');"/></div>
    </body>
    </html>
    By default the bigger image is initally not there so I have added a display:none style in the head.
    The above code will show the bigger image on left when you do a mouseover on the smaller left thumbnail image. Vice-versa when you move out the mouse the image goes away (you may not need this part). So on each thumbnail image simlarly pass the id of the image you want to show via the javascript showImage function.
    Note: You can use onclick or other event per your preference.
    Regards,
    Vinay

  • Need fast help printing RGB .pdf to Epson 7880...

    I am forced to print a RGB .pdf from Acrobat.
    And having trouble understanding  how to set the Destination printer/paper/ink profile, here is my best guess but the blue RGB background is considerably lighter than Photoshop Manages Colors and I need to match Photoshop prints.
    Here is my Acrobat CS6 Color Management settings Pro9880_7880 PLPP260 is my Epson profile):
    I don't think I have it because the Epson Advanced Color Settings is giving me CMYK SLIDERS (not "OFF"):
    All filled boxes and text are sRGB, the .pdf is tagged sRGB, Acrobat Object Inspector confirms the RGB profile is embedded.
    I built the original poster in InDesign and Exported PDF (Print).
    Any fast help greatly appreciated (I am on a deadline)...

    Did some more testing.
    Apple's Preview app prints my PDF Source>Print Profile the same as Acrobat 10.1.6.
    But I think I found the point where the problem is occurring in InDesign.
    The screenshot below shows the Photoshop sRGB document (left) with the blue background, 22/56/158.
    The right side shows InDesign blue background (sRGB is Working RGB) with the identical 22/56/158 RGB fill.
    Open the screenshot in Photoshop (use the embedded profile, sRGB), and sample the blue background in each app.
    There is a considerable difference between them that could account for the difference I am complaining about.
    SEEING IS BELIEVING...
    What this tells me is Photoshop is different than InDesign because doesn't display or print my RGB fill the same...
    So I have to wonder which one is actually correct?

  • HELP, PLEASE!!!! I have to paint an image into...

    Hello, anybody can help me?? I have to paint a map (gif image) into a panel and then paint points on this map. Every short period of time I have to change the points' position on the map. I am trying to put a transparent panel over the map and paint the points on the transparent panel. Has anybody a better idea??

    You could do it all on the one Panel, if you want. Just extend a JPanel, create a BufferedImage of the gif file (Just once, in the constructor) and override the paint method of the JPanel, painting the image with the graphics object. After that, just use the GRpahics2D object to draw whatever you want, it will display over the image, and call repaint() every time you want the graphics updated.

  • I need to read data from a text file and display it in a datagrid.how can this be done..please help

    hey ppl
    i have a datagrid in my form.i need to read input(fields..sort of a database) from a text file and display its contents in the datagrid.
    how can this  be done.. and also after every few seconds reading event should be re executed.. and that the contents of the datagrid will keep changing as per the changes in the file...
    please help as this is urgent and important.. if possible please provide me with an example code as i am completely new to flex... 
    thanks.....  

    It's not possible to read from a file without using classes from the core API*. You'll have to get clarification from your instructor as to which classes are and are not allowed.
    [http://java.sun.com/docs/books/tutorial/essential/io/]
    *Unless you write a bunch of JNI code to replicate what the java.io classes are doing.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

  • Just bought a mac air with OS X v.10.7 Lion, for work I need to read and write NTFS drives, I install MacFuse and NTFS-3G, but it can not mount (recognize?) External HDD, in my MBP with Snow Lepard it work just perfectly... help please.

    Just bought a mac air with OS X v.10.7 Lion, for work I need to read and write NTFS drives, I install MacFuse and NTFS-3G, but it can not mount (recognize?) External HDD, in my MBP with Snow lepard it work just perfectly... help please.

    Reinstall MacFuse with the one from http://www.tuxera.com/mac/macfuse-core-10.5-2.1.9.dmg. If that doesn't work, you can use Paragon NTFS for Mac 9.0 which has been designed to work with Lion.

  • Just bought a mac air with OS X v.10.7 Lion, for work I need to read and write NTFS drives, I install MacFuse and NTFS-3G, but it can not mount (recognize?) External HDD, in my MBP with Lion it work just perfectly... help please.

    Just bought a mac air with OS X v.10.7 Lion, for work I need to read and write NTFS drives, I install MacFuse and NTFS-3G, but it can not mount (recognize?) External HDD, in my MBP with Lion it work just perfectly... help please.

    Sorry in my MBP Snow lepard it work.. don't have Lion In MBP

Maybe you are looking for