• Post Reply Bookmark Topic Watch Topic
  • New Topic

Using a BufferImage to ImageIO.write() results in no image in file  RSS feed

 
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The code below, mostly from another source, produces a line graph to the screen perfectly (please see attachment (OutputToScreen) - when writing to a local file, the file is colored with no data in it (see attached MyFile).
I tried to resolve this for several hours, and I did eventually try Graphics2D graphics2D = image.createGraphics() and it did work, but the output was horrendous.

My expectation is to create a line graph in a Jpg/png format. But, somehow, I seem to be missing the mark. Where am I going amok?


OutputToScreen.png
[Thumbnail for OutputToScreen.png]
Output screen shot
MyFile.jpg
[Thumbnail for MyFile.jpg]
JPG file which was produced
 
Rancher
Posts: 3169
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You don't want to build an image and write it in the paint method.  You've got all the code but in the wrong places.
Create a separate method that defines the BufferedImage, gets a Graphics object from that and call the paintComponent (not paint) to draw on your BI.  Then write the BI to a file.
 
Master Rancher
Posts: 2712
92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are doing the scaling manually. You can let java do all the hard work. Have a look at the AffineTransform class and if g is a Graphics2D, g.setTransform(...). You can obtain a Graphics2D instance with: Graphics2D g2d = (Graphics2d) g.createGraphics())

Also: two possible strategies come to mind:

1) draw the BufferedImage first, and use it in the paintComponent method. In this paintComponent, draw the BI according to the current size of the panel.
2) do the complete drawing in a separate method, with parameter Graphics g. Then in the paintComponent, you call it with the supplied Graphics, and if you want to create a BufferedImage that fits the current size of the panel, you call the method with the Graphics from the BufferedImage (like: buf.createGraphics). If necessary, use a Graphics2D.
 
Robert Bray
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Gentlemen

Thank you for the comments (including Norm - I don't know how to reply to all yet  - I will work on the scaling as soon as I finish the saving of the file. Unfortunately, I cannot profess to understand all of the comments - but I've played with this all day - I, alas, am able to write a black box as a file, while the graph appears on the screen.

I really don't need image to go the display - just to the file. New code is below.

Piet Souris wrote:You are doing the scaling manually. You can let java do all the hard work. Have a look at the AffineTransform class and if g is a Graphics2D, g.setTransform(...). You can obtain a Graphics2D instance with: Graphics2D g2d = (Graphics2d) g.createGraphics())

Also: two possible strategies come to mind:

1) draw the BufferedImage first, and use it in the paintComponent method. In this paintComponent, draw the BI according to the current size of the panel.
2) do the complete drawing in a separate method, with parameter Graphics g. Then in the paintComponent, you call it with the supplied Graphics, and if you want to create a BufferedImage that fits the current size of the panel, you call the method with the Graphics from the BufferedImage (like: buf.createGraphics). If necessary, use a Graphics2D.



 
Sheriff
Posts: 23602
48
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Robert Bray wrote:I really don't need image to go the display - just to the file. New code is below.



Then do like Norm said. Create the BufferedImage and get a Graphics object from it. Right now you're doing that but you ignore (and discard) the Graphics object. What you should do next is to use the code which is now in the paint() method and use that to update the Graphics object which is returned from BI.createGraphics(). Once you've done that you can write the BI to your disk file.

Also, since you don't need the image to go to the display, there's no need for your Plat class to be a JPanel. I don't think you need a GUI at all to create this image file.
 
Piet Souris
Master Rancher
Posts: 2712
92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, you don't need a GUI. But since writing to a JPanel is exactly the same as writing to a BufferedImage, why not? Writing to a JPanel before saving has the advantage of simply adjusting the size of it to what you like, before saving to disk. At least I would suggest to determine the size of the BufferedImage in such way that x and y axis are scaled with the same factor, thus keeping the aspect ratio.
 
Robert Bray
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul -

I feel like a total dunce. But, I really don't know what I need to do  to "update the Graphics object which is returned from BI.createGraphics().
so I inserted directly under the BufferedImage (which is what I think I am reading)


and to  update I entered


I am out of memoryheap

Paul Clapham wrote:

Robert Bray wrote:I really don't need image to go the display - just to the file. New code is below.



Then do like Norm said. Create the BufferedImage and get a Graphics object from it. Right now you're doing that but you ignore (and discard) the Graphics object. What you should do next is to use the code which is now in the paint() method and use that to update the Graphics object which is returned from BI.createGraphics(). Once you've done that you can write the BI to your disk file.

Also, since you don't need the image to go to the display, there's no need for your Plat class to be a JPanel. I don't think you need a GUI at all to create this image file.

 
Norm Radder
Rancher
Posts: 3169
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I am out of memoryheap


Where are the recursive calls? Is there a path where methods  call each other directly or indirectly?

There should not be any calls to your methods from the paintComponent method.
 
Piet Souris
Master Rancher
Posts: 2712
92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It is the new 'paint(g2)'  that causes the loop. Indeed, forget about panels and gui, that'll have to come later. Perhas we should make it a bit more clear what has to be done, since OP seems to struggle a little
 
Norm Radder
Rancher
Posts: 3169
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let me make my suggestion as a list:
Create a separate method that defines the BufferedImage,
gets a Graphics object from that BI
and call the paintComponent (not paint) to draw on your BI. 
Then write the BI to a file.

Then call that new method after the call to setVisible
 
Paul Clapham
Sheriff
Posts: 23602
48
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Norm Radder wrote:Where are the recursive calls? Is there a path where methods  call each other directly or indirectly?



Yes, the paint() method calls saveMe() at the end. So having saveMe() call paint() makes it recursive.
 
On top of spaghetti all covered in cheese, there was this tiny ad:
Why should you try IntelliJ IDEA ?
https://coderanch.com/wiki/696337/IntelliJ-IDEA
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!