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.
