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.
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?
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().
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. ]