I'm not sure, it might depend on a variety of factors. I know Java ImageIO can use disk-backed caching, but that's just for manufacturing the BufferedImage and so I don't know if it's disk-backed-ness carries over into the BufferedImage it produces.
I don't handle DPI -- I create a BufferedImage of mostly the same properties and do a pixel-pixel rescale. I suspect the DPI would only come into play when you need to write it to disk with an image format that supports DPI, however I surely don't know. -Ross On Jan 19, 2010, at 4:09 PM, Naftoli Gugenheim wrote: > Does JAI need everything in RAM? > Also, how do you deal with DPI? > > ------------------------------------- > Ross Mellgren<[email protected]> 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 <[email protected]> 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 [email protected]. >>>> To unsubscribe from this group, send email to >>>> [email protected]. >>>> 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 [email protected]. >>> To unsubscribe from this group, send email to >>> [email protected]. >>> 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 [email protected]. >> To unsubscribe from this group, send email to >> [email protected]. >> 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 [email protected]. > To unsubscribe from this group, send email to > [email protected]. > 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 [email protected]. > To unsubscribe from this group, send email to > [email protected]. > 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 [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
