简体   繁体   中英

Is there a memory-efficient alternative to graphics.drawImage()?

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.

  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,

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM