X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Fgui%2FImageUtils.java;fp=src%2Ftim%2Fprune%2Fgui%2FImageUtils.java;h=c3c4c2088d796e71d9ca2bcf9aaec1c6f35b9076;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/gui/ImageUtils.java b/src/tim/prune/gui/ImageUtils.java new file mode 100644 index 0000000..c3c4c20 --- /dev/null +++ b/src/tim/prune/gui/ImageUtils.java @@ -0,0 +1,139 @@ +package tim.prune.gui; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.ConvolveOp; +import java.awt.image.Kernel; + +import javax.swing.ImageIcon; + +/** + * Class for providing generic image processing functions + */ +public abstract class ImageUtils +{ + private static final float SMOOTH_FACTOR = 0.008f; + private static ConvolveOp CONVOLVER = null; + + /** Static block for initialization */ + static + { + float[] smoothMatrix = { + 0, SMOOTH_FACTOR, 0, + SMOOTH_FACTOR, 1-(SMOOTH_FACTOR*4), SMOOTH_FACTOR, + 0, SMOOTH_FACTOR, 0 + }; + CONVOLVER = new ConvolveOp(new Kernel(3, 3, smoothMatrix)); + } + + + /** + * Create a scaled and smoothed image according to the specified size + * @param inImage image to scale + * @param inWidth width to scale to + * @param inHeight height to scale to + * @return BufferedImage containing scaled result + */ + public static BufferedImage createScaledImage(Image inImage, int inWidth, int inHeight) + { + if (inWidth <= 0 || inHeight <= 0) { + return null; + } + // create smaller image and force its loading + Image smallerImage = inImage.getScaledInstance(inWidth, inHeight, Image.SCALE_SMOOTH); + Image tempImage = new ImageIcon(smallerImage).getImage(); + tempImage.getWidth(null); + + // create buffered image to do transform + BufferedImage buffer = new BufferedImage(inWidth, inHeight, BufferedImage.TYPE_INT_RGB); + // copy scaled picture into buffer + Graphics buffG = buffer.getGraphics(); + buffG.drawImage(smallerImage, 0, 0, inWidth, inHeight, null); + buffG.dispose(); + + // clear variables + smallerImage = null; tempImage = null; + // smooth scaled image using a normalized 3x3 matrix - taking next neighbour + buffer = CONVOLVER.filter(buffer, null); + + return buffer; + } + + + /** + * Work out the max size of a thumbnail + * @param inOrigWidth width of original picture + * @param inOrigHeight height of original picture + * @param inMaxWidth max width of thumbnail + * @param inMaxHeight max height of thumbnail + * @return size of thumbnail as Dimension + */ + public static Dimension getThumbnailSize(int inOrigWidth, int inOrigHeight, int inMaxWidth, int inMaxHeight) + { + if (inMaxWidth <= 0 || inMaxHeight <= 0) {return new Dimension(1, 1);} + // work out maximum zoom ratio available so that thumbnail isn't too big + double xZoom = inMaxWidth * 1.0 / inOrigWidth; + double yZoom = inMaxHeight * 1.0 / inOrigHeight; + double zoom = (xZoom > yZoom?yZoom:xZoom); + // Don't make thumbnail bigger than picture + if (zoom > 1.0) {return new Dimension(inOrigWidth, inOrigHeight);} + + // calculate new width and height + final int xSize = (int) (zoom * inOrigWidth); + final int ySize = (int) (zoom * inOrigHeight); + if (xSize <= 0 || ySize <= 0) {return new Dimension(1, 1);} + return new Dimension (xSize, ySize); + } + + + /** + * Create a new image by rotating and scaling the given one + * @param inImage input image + * @param inMaxWidth maximum width of output image + * @param inMaxHeight maximum height of output image + * @param inRotationDegrees number of degrees to rotate clockwise (0, 90, 180 or 270) + * @return rotated, scaled image + */ + public static BufferedImage rotateImage(Image inImage, int inMaxWidth, int inMaxHeight, int inRotationDegrees) + { + // Create scaled image of suitable size + boolean isRotated = (inRotationDegrees % 180 != 0); + int origWidth = inImage.getWidth(null); + int origHeight = inImage.getHeight(null); + int thumbWidth = isRotated?origHeight:origWidth; + int thumbHeight = isRotated?origWidth:origHeight; + Dimension scaledSize = getThumbnailSize(thumbWidth, thumbHeight, inMaxWidth, inMaxHeight); + BufferedImage result = new BufferedImage(scaledSize.width, scaledSize.height, BufferedImage.TYPE_INT_RGB); + // Do different things according to rotation angle (a bit messy, sorry!) + if (inRotationDegrees == 0) + { + // Not rotated, so just copy image directly + result.getGraphics().drawImage(inImage, 0, 0, scaledSize.width, scaledSize.height, null); + } + else + { + // Need to use Graphics2D for rotation, not Graphics + Graphics2D g2d = result.createGraphics(); + switch (inRotationDegrees) + { + case 90: + g2d.rotate(Math.PI / 2, 0.0, 0.0); + g2d.drawImage(inImage, 0, -scaledSize.width, scaledSize.height, scaledSize.width, null); + break; + case 180: + g2d.rotate(Math.PI, scaledSize.width/2.0, scaledSize.height/2.0); + g2d.drawImage(inImage, 0, 0, scaledSize.width, scaledSize.height, null); + break; + case 270: + g2d.rotate(Math.PI * 3/2, 0.0, 0.0); + g2d.drawImage(inImage, -scaledSize.height, 0, scaledSize.height, scaledSize.width, null); + } + // Clear up memory + g2d.dispose(); + } + return result; + } +}