Does JAI need everything in RAM?
Also, how do you deal with DPI?

-------------------------------------
Ross Mellgren<dri...@gmail.com> wrote:

Well, it has to keep the whole source (packed) in memory and the target 
(unpacked / 32 bit RGBA) in memory, so I would assume that as long as 
AffineTransformOp is not doing something untoward it's probably around (src 
width * src height * src bytes/pixel) + (dest width * dest height * 4 bytes) 
plus a little bit extra.

I'm not a Java2D guru or anything, so I'm not sure how that could be improved 
offhand.

If you want to wrap it up and put it in, that'd be awesome!

-Ross

On Jan 15, 2010, at 10:17 AM, Timothy Perrett wrote:

> Cool stuff Ross, whats the overhead like in terms of memory etc? 
> 
> I might have a bit of time to put this into a module and stuff it on review 
> board. 
> 
> Cheers, Tim
> 
> On 15 Jan 2010, at 15:03, Ross Mellgren wrote:
> 
>> According to Jon on the call, he said he was putting together just such a 
>> lift module (for image stuff), so I figured I'd toss this over in case it 
>> was of use to him in that module.
>> 
>> If anyone else wants to use it independently, consider it a contribution to 
>> lift, and licensed the same way.
>> 
>> -Ross
>> 
>> On Jan 15, 2010, at 9:51 AM, Peter Robinett wrote:
>> 
>>> Ross, this looks nice. Imagine resizing code is something that I've
>>> personally had to do many times and is always annoying, so perhaps
>>> this would make a good Lift module? Anyway, this is probably best
>>> discussed on the main list...
>>> 
>>> Peter
>>> 
>>> On Jan 14, 3:01 am, Ross Mellgren <dri...@gmail.com> wrote:
>>>> Oh I nearly forgot I said on the conference call the other day that I'd 
>>>> send the image resize code we built at work, in case it would be helpful. 
>>>> Here it is:
>>>> 
>>>> import java.awt.{Graphics, RenderingHints, Transparency}
>>>> import java.awt.geom.AffineTransform
>>>> import java.awt.image.{AffineTransformOp, BufferedImage, ColorModel, 
>>>> IndexColorModel}
>>>> 
>>>> /**
>>>> * Helpers for manipulating images
>>>> */
>>>> object ImageHelpers
>>>> {
>>>> // Some code here omitted -- Ed.
>>>> 
>>>>   /** Rendering hints set up for the highest quality rendering */
>>>>   val highQualityHints = {
>>>>       val h = new RenderingHints(null)
>>>>       h.put(RenderingHints.KEY_ALPHA_INTERPOLATION, 
>>>> RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)
>>>>       h.put(RenderingHints.KEY_COLOR_RENDERING, 
>>>> RenderingHints.VALUE_COLOR_RENDER_QUALITY)
>>>>       h.put(RenderingHints.KEY_INTERPOLATION, 
>>>> RenderingHints.VALUE_INTERPOLATION_BICUBIC)
>>>>       h.put(RenderingHints.KEY_ANTIALIASING, 
>>>> RenderingHints.VALUE_ANTIALIAS_ON)
>>>>       h.put(RenderingHints.KEY_RENDERING, 
>>>> RenderingHints.VALUE_RENDER_QUALITY)
>>>>       h
>>>>   }
>>>> 
>>>> // Some code here omitted -- Ed.
>>>> 
>>>>   /**
>>>>    * Resize an image of the given source type by the given ratios, 
>>>> properly handling GIF transparency, giving back the resized
>>>>    * image and the new image format type that should be used.
>>>>    *
>>>>    * The image type might change if the input type is an indexed color 
>>>> model, because it is a hard problem to choose an optimized
>>>>    * palette, and currently we don't. This function will return "png" as 
>>>> the new type in this case.
>>>>    *
>>>>    * If the input image is not using an indexed color model with 
>>>> transparency, then the target format and color model will be
>>>>    * identical to the source.
>>>>    */
>>>>   def resize(source: BufferedImage, inputFormat: String, dx: Double, dy: 
>>>> Double): (BufferedImage, String) = {
>>>>       var sourceColorModel = source.getColorModel
>>>>       val targetColorModel = source.getColorModel
>>>>       val standardColorModel = ColorModel.getRGBdefault
>>>> 
>>>>       val (targetWidth, targetHeight) = (((source.getWidth: Double) * 
>>>> dx).asInstanceOf[Int], ((source.getHeight: Double) * dy).asInstanceOf[Int])
>>>> 
>>>>       def resize(src: BufferedImage, dst: BufferedImage) {
>>>>           val g = dst.createGraphics
>>>>           try {
>>>>               g.setRenderingHints(highQualityHints)
>>>>               g.drawImage(src, new 
>>>> AffineTransformOp(AffineTransform.getScaleInstance(dx, dy), 
>>>> AffineTransformOp.TYPE_BICUBIC), 0, 0)
>>>>           } finally {
>>>>               g.dispose
>>>>           }
>>>>       }
>>>> 
>>>>       // GIF support in Java is very ornery. For GIFs we have to manually 
>>>> do the masking on input, and then just punt on outputting GIFs and instead 
>>>> output PNGs.
>>>>       if (sourceColorModel.isInstanceOf[IndexColorModel] &&
>>>>           sourceColorModel.hasAlpha &&
>>>>           sourceColorModel.getTransparency == Transparency.BITMASK &&
>>>>           
>>>> sourceColorModel.asInstanceOf[IndexColorModel].getTransparentPixel >= 0) {
>>>> 
>>>>           val indexColorModel = 
>>>> sourceColorModel.asInstanceOf[IndexColorModel]
>>>>           val transparent = 
>>>> indexColorModel.getRGB(indexColorModel.getTransparentPixel)
>>>> 
>>>>           val masked = new BufferedImage(standardColorModel, 
>>>> standardColorModel.createCompatibleWritableRaster(source.getWidth, 
>>>> source.getHeight), standardColorModel.isAlphaPremultiplied, null)
>>>>           var w = masked.getWidth
>>>>           var h = masked.getHeight
>>>> 
>>>>           val buf  = new Array[Int](w)
>>>> 
>>>>           var y = 0
>>>>           while (y < h) {
>>>>               source.getRGB(0, y, w, 1, buf,  0, 1)
>>>> 
>>>>               var x = 0
>>>>               while (x < w) {
>>>>                   val c = buf(x)
>>>>                   if (c == transparent) {
>>>>                       buf(x) = 0
>>>>                   }
>>>>                   x += 1
>>>>               }
>>>> 
>>>>               masked.setRGB(0, y, w, 1, buf, 0, 1)
>>>>               y += 1
>>>>           }
>>>> 
>>>>           val resized = new BufferedImage(standardColorModel, 
>>>> standardColorModel.createCompatibleWritableRaster(targetWidth, 
>>>> targetHeight), standardColorModel.isAlphaPremultiplied, null)
>>>>           resize(masked, resized)
>>>>           (resized, "png")
>>>>       } else if (sourceColorModel.isInstanceOf[IndexColorModel]) {
>>>>           // The input color model is indexed, and we know we won't be 
>>>> able to generate a tolerable palette to make another indexed color model, 
>>>> so use sRGB and upgrade to PNG.
>>>>           val resized = new BufferedImage(standardColorModel, 
>>>> standardColorModel.createCompatibleWritableRaster(targetWidth, 
>>>> targetHeight), standardColorModel.isAlphaPremultiplied, null)
>>>>           resize(source, resized)
>>>>           (resized, "png")
>>>>       } else {
>>>>           val resized = new BufferedImage(targetColorModel, 
>>>> targetColorModel.createCompatibleWritableRaster(targetWidth, 
>>>> targetHeight), targetColorModel.isAlphaPremultiplied, null)
>>>>           resize(source, resized)
>>>>           (resized, inputFormat)
>>>>       }
>>>>   }
>>>> 
>>>> }
>>>> 
>>>> It isn't perhaps the ideal implementation, as mentioned in some of the 
>>>> comments, but perhaps Jon or others might find it useful in whole or part.
>>>> 
>>>> -Ross
>>> -- 
>>> You received this message because you are subscribed to the Google Groups 
>>> "Lift-committers" group.
>>> To post to this group, send email to lift-committ...@googlegroups.com.
>>> To unsubscribe from this group, send email to 
>>> lift-committers+unsubscr...@googlegroups.com.
>>> For more options, visit this group at 
>>> http://groups.google.com/group/lift-committers?hl=en.
>>> 
>>> 
>> 
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Lift" group.
>> To post to this group, send email to lift...@googlegroups.com.
>> To unsubscribe from this group, send email to 
>> liftweb+unsubscr...@googlegroups.com.
>> For more options, visit this group at 
>> http://groups.google.com/group/liftweb?hl=en.
>> 
>> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Lift" group.
> To post to this group, send email to lift...@googlegroups.com.
> To unsubscribe from this group, send email to 
> liftweb+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/liftweb?hl=en.
> 
> 

-- 
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.


-- 
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.


Reply via email to