Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (121)
games submitted by our members
Games in WIP (577)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  BINARY BufferedImage and memory consumption  (Read 3071 times)
0 Members and 1 Guest are viewing this topic.
Offline Adoendithas

Junior Newbie





« Posted 2009-09-06 10:06:34 »

My first post here so hi everyone!

I have a rather difficult question for you guys:

I have a relatively large binary (black & white) image on disk. Dimensions 8000x4000 px.
But because its binary, my math says its not that big in memory (8000x4000bits = around 3.81 MB).

When i load it into BufferedImage, memory consumption rises for expected amount.
But when i resize it, regardless of the ratio (be it 1 pixel resize), memory usage jumps for 250 MB!

So what's going on and how can i make it stop? Smiley

Here is a little example i prepared to illustrate above situation:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
 
public class BufferedImageTest {
    public static void main(String[] args) {
        try {
            // initial: 7.8 MB
           
            BufferedImage image = ImageIO.read(new File("images/world_test.png"));         // image is 8000x4000 binary (black and white only)
            // 14.4 MB
           
            BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
            // 18.9 MB
           
            Graphics2D g = result.createGraphics();
            // 21.5 MB
           
            g.drawImage(image, 0, 0, 8000, 4000, null);
            // 21.5 MB
 
            g.drawImage(image, 0, 0, 7999, 4000, null);
            // 277.7 MB
        } catch (IOException ex) {
            Logger.getLogger(BufferedImageTest.class.getName()).log(Level.SEVERE, null, ex);
        }
 
    }
}
Offline Supamagier

Senior Newbie





« Reply #1 - Posted 2009-09-06 16:22:22 »

Does this also happen when you resize to.. let's say 2000 or 16000?

Could be because it has to calculate the new color for each pixel which might be easier if you simply double it.
Just speculating.
Offline Adoendithas

Junior Newbie





« Reply #2 - Posted 2009-09-07 09:16:03 »

Does this also happen when you resize to.. let's say 2000 or 16000?

Could be because it has to calculate the new color for each pixel which might be easier if you simply double it.
Just speculating.

Ok, if that would be the case, than memory usage would rise for 8 MB, not 250 MB!

But maybe you got the point. It's possible that drawImage method is internaly transforming image from binary to "desktop color" which is in my case 32 bit.
One image would than take 122 MB, and if it makes a copy, thats 244 MB! Then it creates final image in 1-bit color, thats additional 3.81 MB.

Now thats a "green" method  Grin
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Stranger

Senior Duke


Medals: 7



« Reply #3 - Posted 2009-09-07 14:20:27 »

Hi,

Try to replace

1  
2  
            g.drawImage(image, 0, 0, 7999, 4000, null); 
            // 277.7 MB


with

1  
2  
3  
            BufferedImageOp op = new ColorConvertOp(image.getColorModel(),result.getColorModel(),null);
            BufferedImage img1 = op.filter(image, null);
            g.drawImage(img1, new AffineTransform(7999f/8000f,0f,0f,1f,0,0), null);


Maybe this will help.

Regards

Anton
Offline delt0r

JGO Knight


Medals: 27
Exp: 18 years


Computers can do that?


« Reply #4 - Posted 2009-09-07 14:58:13 »

How are you measuring the ram consumption?

However I suspect that rescaling operation is taking place in a temporary buffer/Image which will probably use a more plain pixel format (ie 24-32 bits per pixel ~128M).  I had this problem with rotations. In fact I would say that using java2D you would need to be careful with what you do to avoid these kind of intermediate steps. You could try turning on java2d debug call tracing or whatever its called. 

Other things to check: Antialising settings and interpolation settings. Nearest neighbour is the only thing that keeps intermediate results binary. Others result in gray scale .

I have no special talents. I am only passionately curious.--Albert Einstein
Offline Adoendithas

Junior Newbie





« Reply #5 - Posted 2009-09-07 16:03:15 »

Hi,

Try to replace

1  
2  
            g.drawImage(image, 0, 0, 7999, 4000, null); 
            // 277.7 MB


with

1  
2  
3  
            BufferedImageOp op = new ColorConvertOp(image.getColorModel(),result.getColorModel(),null);
            BufferedImage img1 = op.filter(image, null);
            g.drawImage(img1, new AffineTransform(7999f/8000f,0f,0f,1f,0,0), null);


Maybe this will help.

Regards


Thank you for the suggestion, but it didn't work. It ate 400 MB and was extremly slow.
Offline Adoendithas

Junior Newbie





« Reply #6 - Posted 2009-09-07 16:05:35 »

How are you measuring the ram consumption?

However I suspect that rescaling operation is taking place in a temporary buffer/Image which will probably use a more plain pixel format (ie 24-32 bits per pixel ~128M).  I had this problem with rotations. In fact I would say that using java2D you would need to be careful with what you do to avoid these kind of intermediate steps. You could try turning on java2d debug call tracing or whatever its called. 

Other things to check: Antialising settings and interpolation settings. Nearest neighbour is the only thing that keeps intermediate results binary. Others result in gray scale .

Thank you for your answer!

Is seems that is what happens.
i'm still searching for a way how to avoid it.
Offline Adoendithas

Junior Newbie





« Reply #7 - Posted 2009-09-08 07:43:30 »

I found that this is a java related bug and is already reported.

http://bugs.sun.com/view_bug.do?bug_id=6716560
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

theagentd (20 views)
2014-10-25 15:46:29

Longarmx (53 views)
2014-10-17 03:59:02

Norakomi (47 views)
2014-10-16 15:22:06

Norakomi (35 views)
2014-10-16 15:20:20

lcass (39 views)
2014-10-15 16:18:58

TehJavaDev (69 views)
2014-10-14 00:39:48

TehJavaDev (69 views)
2014-10-14 00:35:47

TehJavaDev (61 views)
2014-10-14 00:32:37

BurntPizza (74 views)
2014-10-11 23:24:42

BurntPizza (47 views)
2014-10-11 23:10:45
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!