convert Graphics to BufferedImage

Hi guys,

Have you noticed that when trying to create BufferedImages with big width and height, you get a Java Heap size error?

Do you know a way for my application to be able to change heap size automatically, until BufferedImage can be constructed with increased bounds limit (Cos i think Sun is working for this problem right now)?

[353 byte] By [multika] at [2007-11-26 18:06:35]
# 1
> Have you noticed that when trying to create BufferedImages with big width and height, you get a Java Heap size error? No. What do you consider big?
camickra at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 2
> (Cos i think Sun is working for this problem right now)?What's a Cos?
kirillga at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 3

With desktop applications and WebStart deployed apps you can configure the available heap space via the -Xmx parameter. With applets you're a bit stuck with the default (typically 96Mb) unless you have an Intranet-deployed app where you can explicitly request users to raise the ceiling in their Plugin console.

Regardless, you can still handle some largish images inside an applet, you just have to be a bit clever, and sometimes put up with some degraded performance.

I've used a number of strategies for tackling this ranging from the very simple to the hideously complex - what are you trying to do exactly?

itchyscratchya at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 4

Sorry for being fuzzy...

Let's say i have a Graphics(or Graphics2D) object.

It's original size (scale 1.0) is >10000x2000(pixels?)

To be more specific it draws only black colored lines and shapes.

I'd like to convert it to image (gif,png,jpeg) and write the image to disk, without having to change the heap size manually (that's because i don't want the user to get in such trouble).

The error comes when i call new BufferedImage(WIDTH,HEIGHT,type);

OutOfMemory error : Java Heap Space

thanx for replies

ps. (with "Cos" i meant "because" <sorry>)

multika at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 5

It's original size (scale 1.0) is >10000x2000(pixels?) ... The error comes when i call new BufferedImage(WIDTH,HEIGHT,type);

Mm, that's 80Mb you're looking at right there :o)

Some questions:

1. application or applet?

2. does the saved image really need to be that big?

3 and 4 below may be non-issues, hopefully you are only generating an image for saving purposes..?3. does the on-screen image really need to be that big?

4. do you need to render an on-screen image at all? (ie, can you render the shapes directly to screen, using no raster memory, instead?) - note that this has the added benefit of scaling gracefully instead of pixellating and quantizing

I've not used the tiling functionality in ImageIO, I wonder if that may work? Or is it just for Tiffs?

itchyscratchya at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 6

1.application

2. the jpeg file has to be that big (ie 25m x 2m), to get printed in large printers or plotters that have raster input.

3.no problem at on-screen

4.my source is vector type, the data are stored in an ArrayList and drawed in a loop inside (Graphics2D)paintComponent.

i want to create the jpeg corresponding file at it's actual size(100%)

multika at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 7
Ok, in that case I would suggest your best bet is to look into alternative file formats suitable for this sort of printing. EPS is the obvious one.Take a look at this, it might make your day :o) http://www.jibble.org/epsgraphics/
itchyscratchya at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 8

Thanks very much for your help man.

Something else i want to ask...

Do you know if i can change the BufferedImage's resolution from 72dpi, to 288?

Some people say that scaling my Graphics object by 72/288(not sure maybe 288/72), i can achieve better resolution. But this looks to me as if i'm creating a smaller image (thing i don't want).

Anyway, let's say that i create an image(72dpi) scaled down by 4 from Graphics, using BufferedImage. I then try to increase Image size by 4 from photoshop, but the resolution is very but.

1.I wonder if i can create the same image of 300dpi instead.

2.eps would be a good solution, but EpsGraphics2D library is commercial which i can't afford. I'm currently searching for something similar, or some code that could be helpfull

Any suggestions?

multika at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 9

Raster images are just a bunch of pixels - the pixels are the image data. DPI information is just metadata which is (entirely optionally) used for printing and/or display. The data vs metadata difference is quite important.

So, if you have a 300x300px image, you can save it as a 300dpi image or a 1200dpi image, or whatever. If you print the final image at 1"x1" it makes no difference what the nominal DPI is, you are spreading 300 pixels across one ince, so that's 300dpi. All the nominal DPI determines, really, is a suggested size for printing. You can choose to print at a certain size or at a certain DPI, it's just a three-variable equation and any two need to be fixed to determine the third (number of pixels is obviously a constant for any image, so you pick either DPI or inches).

So, if you want to be able to print the same image at the same size but at 288dpi instead of 72dpi, you will need that image to be four times the width and four times the height, ie sixteen times the size. It's a simple act of creating a bigger image - you can set the DPI to whatever you want when writing the image in a format which supports DPI metadata.

itchyscratchya at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 10

There is no way to avoid using BufferedImage?

Please tell me there is.....:-)

public void paintComponent(Graphics g){//Java's drawing function//

super.paintComponent(g);//needed when repaint() is called//

Graphics2D g2d = (Graphics2D)g;

BufferedImage image =

new BufferedImage((int)(this.gWidth()),

(int)(this.gHeight()),

BufferedImage.TYPE_INT_RGB);

g2d = (Graphics2D)image.createGraphics();

//////////////////Set Background to white/////////////////////

g2d.setBackground(Color.WHITE);

g2d.setColor(Color.WHITE);

g2d.fillRect(0,0,(int)(this.gWidth()),

(int)(this.gHeight()));

///////////////////////////////////////////////////////////////////////////////////

//Set draw color to black///

g2d.setColor(Color.black);

// ~~~ Draw graphics here ~~~ //

for (int i=2; i<commands.size(); i++){

g2d.drawLine()//some lines drawed//

}//for

//*************Graphics Drawed**************//

g.drawImage(image,0,0,null);

if(!fileWritten){

File f = new File("converted.jpg");

try {

System.out.println("ok");

ImageIO.write(image, "jpg", f);

fileWritten=true;

} catch (IOException ex) {

System.out.println("pro");

ex.printStackTrace();

}

}

}//paint

>

multika at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 11

There is no way to avoid using BufferedImage? Please tell me there is.....:-)

Well, as I say, you're best off looking at vector file formats like EPS, SVG etc - raster formats are totally inappropriate for what you're doing. Trying to print a 25m x 2m (!!!) page using rasters is completely and utterly crazy.

itchyscratchya at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 12
i know i'm coming in late here, but why do the onscreen images have to be that big? I saw the question earlier, but don't remember seeing the answer.
Jasprea at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 13
You didn't read the whole topic.The on-screen image doesn't have to be that big but the off-screen has.Anyway, out there seems to be a little info about creating eps from Graphics and Graphics2D...Thanx for responses..
multika at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...
# 14

Anyway, if someone wants to create large images straight from Graphics there should be a way to do so (no matter how crazy this is).

After all, the BufferedImage's documentation should make clear to developers that there is a constructor width and height limit, while additionaly an Exeption should be thrown whenever BufferedImage fails to be created.

And i believe this is a reasonable statement..

I don't know if working with tiles helps 'cause i found the documentation difficult to be understood.

However a solution could arise if BufferedImage's constructor was able to create a tile of the image everytime heap space reaches the end.

What do you think?

Regards...

multika at 2007-7-9 5:37:40 > top of Java-index,Desktop,Core GUI APIs...