1

I need to hold ~50 images in memory (this is a must and a condition I cannot change). However, at some point I want to draw thumbnails of these images on a JFrame.

Using

graphics.drawImage(picture, 100, 100, 100, 100, null);

to draw a resized version of an image works well since there is no (or very sparse) memory consumed in doing so. But it is known that the scaling algorithm in drawImage is not the best and looks poor.

I've tried Thumbnailator, JMagick and imgscalr to produce better quality, neat-looking thumbnail results. However, there is a problem: Their calls consume some memory since they are creating new BufferedImage objects.

That being said, the following code holds a nearly constant memory usage:

BufferedImage i = null;
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setVisible(true);

try {
    i = ImageIO.read(new File("season.jpg"));
} catch (IOException e1) {}

while (true)
{
    frame.getGraphics().drawImage(i, 100, 100, 100, 100, null);

    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {}
}

However, the following code will continue to rise and rise and rise the memory consumption:

BufferedImage i = null;
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setVisible(true);

try {
    i = ImageIO.read(new File("season.jpg"));
} catch (IOException e1) {}

while (true)
{
    BufferedImage x;
    try {
        x = Thumbnails.of(i).size(100, 100).keepAspectRatio(false).asBufferedImage();
        frame.getGraphics().drawImage(x, 100, 100,  null);
    } catch (IOException e1) {}

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {}
}

So, what I am asking, is:

Is there a) a good memory-efficient alternative to draw a resized version of an image to a JFrame? or b) is it possible to resize images in-place, manipulating the internal structure without creating new Image objects (for example: scaleInPlace(image, 100, 100) instead of image = scale(image, 100, 100))?

Thank you for any help! :)

PS: I know that my code examples are not the recommended way of drawing images to a JFrame, it is just a quick example.

Above
  • 235
  • 2
  • 3
  • 9

1 Answers1

2
  1. use Icon/ImageIcon in JLabel in the case that this contianer doesn't contains JComponent, you can to use getScaledInstance to store Images with (only) reasonable pixels ratio, then memory requitements too, then is possible to store those images in local variables

  2. frame.getGraphics().drawImage(x, 100, 100, null); isn't proper of ways, you have to, is required for todays Swing to put there JPanel (override getPreferredSize), and inside paitComponent to drawImage from stored as local varibble from getScaledInstance

  3. getScaledInstance is pretty asynchronous,

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • 1
    Agree on `getGraphics()`; more alternatives are cited [here](http://stackoverflow.com/a/18101059/230513). – trashgod Oct 28 '13 at 13:14
  • I do not want to be offensive, but I think you did not understand my question.   1. getScaledInstance consumes much memory. Try replacing line 13 and 14 in the second example with the following: `Image d = i.getScaledInstance(100, 100, Image.SCALE_DEFAULT); frame.getGraphics().drawImage(d, 100, 100, null);` The memory will rise and rise as if I used Thumbnailator (second example). The documentation for this method says "A new Image object is returned" and this is where the memory consumption stems from and what I try to avoid. – Above Oct 28 '13 at 18:03
  • 2. "PS: I know that my code examples are not the recommended way of drawing images to a JFrame, it is just a quick example [to demonstrate the memory use]." ^^ 3. Please elaborate how this could help me :/ – Above Oct 28 '13 at 18:04
  • 1. did you save scalled image to local variable, or arrays of images 2. is against all rulles, then output is as it is 3. no idea what your point – mKorbel Oct 28 '13 at 19:28