This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
I have some images that are very large and need to adjust the size of them downward but keep the original aspect ratio.
Can anyone point me to some sample code on how this can be done?
In short, what I need to do is:
1) Load an image from the database (I can handle that). 2) Determine the size of the image. 3) If the image is too large, determine the aspect ratio then resize it. 4) Stream it out to my web app (I can handle that).
Note that the image will be read/processed by a servlet, and I'd like the keep the Image2D stuff to a minimum if possible.
OK, I've done a little digging, but I'm not sure what I'm doing is the right/best way.
My images are stored in a database and I get them back as a byte. I also need to send them back out as a byte from the scaling method.
What I do is convert this byte to an ImageIcon, perform the calculations (see what ratio I need, etc.), use the Image.setScaledInstance, place this into a BufferedImage, and then finally into a ByteArrayOutputStream so I can get the final byte.
What you've done, if it works, is probably fine. We don't get a lot of control over image loading and coversion in Java. I dont see what imageDataDAO is, but I'd probably get the image out of the database result set as an InputStream and feed that directly to ImageIO to get a BufferedImage. In practical terms, it's probably doing the same amount of work you are doing above. Make sure you invoke flush() on all Image instances when you are finished with them. There's some resources which don't get freed automatically.
Joined: Aug 04, 2003
Well this doesn't seem to work.
It does get the image in the correct size and aspect ratio, but the image is displayed as one big black box!
Can anyone see the error of my ways here? I've seen examples that do something very similar to what I am trying so it must be something small.
BTW, thanks Joe, and yes, the ImageDataDAO is what gets the image out of the database as a byte array (uses Spring BTW).
Thanks! [ June 15, 2005: Message edited by: Darrin Smith ]
OK. I looked around in the attic and found a servlet where I was doing the same thing. Looks very much like your code, with the exception of using a -1 argument to the getScaledImage() call (resizes and preserves the aspect ratio):
I stripped out the code where it determines fileDir and fileName and caches the scaled instance since you are using a DB. Are you sure your process to save the image to the DB works? What if you just grab it out of the db? Does it display properly?
Joined: Aug 04, 2003
Thanks for all of your work.
Yes, the image is saved correctly and it will display just fine when I show it full size.
Note though that I think I've got a solution!
I did a little test writing the image out to a file and, sure enough, it too was black. I then changed from a Graphics2D to Graphics and did the same thing...BINGO, now the image gets saved correctly!
Was I doing something wrong by using Graphics2d instead of Graphics?
Here is my test code (doesn't pass back a byte, but that will come next):
That's odd. The only thing I see different is that it doesn't work when you use createGraphics() but works when you use getGraphics() though those methods are documented to do the same thing (i.e. return a graphics instance). I told you this subject was a black hole. Use what works Don't forget to free up those Graphics instances with a call to dispose().
Joined: Aug 04, 2003
Originally posted by Joe Ess: Don't forget to free up those Graphics instances with a call to dispose().
You can do the same thing using AffineTransforms which I have found to consume less memory
you might try:
and then once you have the BufferedImage.. you can manipulate it this way
And this is not really like modifying the same BufferedImage. op.filter returns a BufferedImage and the null value is supposed to be a destination BufferedImage I just overwrite what I was using before.
Anyone see any caveats there? I haven't had any problems yet. This is also used from a servlet. Some other gotchas are trying to manipulate a file before you have it read in. Which is why I used the IIOPReadProgressListener..
also.. I'm not a graphics programming expert.. and this code is just hacked from my real code.. [ July 03, 2005: Message edited by: marcus g. ]