Thumbnail.java Source code

Java tutorial

Introduction

Here is the source code for Thumbnail.java

Source

//package net.gqu.utils;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.OutputStream;

import javax.swing.ImageIcon;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class Thumbnail {
    /**
    * Reads an image in a file and creates a thumbnail in another file.
    * largestDimension is the largest dimension of the thumbnail, the other dimension is scaled accordingly.
    * Utilises weighted stepping method to gradually reduce the image size for better results,
    * i.e. larger steps to start with then smaller steps to finish with.
    * Note: always writes a JPEG because GIF is protected or something - so always make your outFilename end in 'jpg'.
    * PNG's with transparency are given white backgrounds
    */
    public String createThumbnail(String inFilename, String outFilename, int largestDimension) {
        try {
            double scale;
            int sizeDifference, originalImageLargestDim;
            if (!inFilename.endsWith(".jpg") && !inFilename.endsWith(".jpeg") && !inFilename.endsWith(".gif")
                    && !inFilename.endsWith(".png")) {
                return "Error: Unsupported image type, please only either JPG, GIF or PNG";
            } else {
                Image inImage = Toolkit.getDefaultToolkit().getImage(inFilename);
                if (inImage.getWidth(null) == -1 || inImage.getHeight(null) == -1) {
                    return "Error loading file: \"" + inFilename + "\"";
                } else {
                    //find biggest dimension       
                    if (inImage.getWidth(null) > inImage.getHeight(null)) {
                        scale = (double) largestDimension / (double) inImage.getWidth(null);
                        sizeDifference = inImage.getWidth(null) - largestDimension;
                        originalImageLargestDim = inImage.getWidth(null);
                    } else {
                        scale = (double) largestDimension / (double) inImage.getHeight(null);
                        sizeDifference = inImage.getHeight(null) - largestDimension;
                        originalImageLargestDim = inImage.getHeight(null);
                    }
                    //create an image buffer to draw to
                    BufferedImage outImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); //arbitrary init so code compiles
                    Graphics2D g2d;
                    AffineTransform tx;
                    if (scale < 1.0d) //only scale if desired size is smaller than original
                    {
                        int numSteps = sizeDifference / 100;
                        int stepSize = sizeDifference / numSteps;
                        int stepWeight = stepSize / 2;
                        int heavierStepSize = stepSize + stepWeight;
                        int lighterStepSize = stepSize - stepWeight;
                        int currentStepSize, centerStep;
                        double scaledW = inImage.getWidth(null);
                        double scaledH = inImage.getHeight(null);
                        if (numSteps % 2 == 1) //if there's an odd number of steps
                            centerStep = (int) Math.ceil((double) numSteps / 2d); //find the center step
                        else
                            centerStep = -1; //set it to -1 so it's ignored later
                        Integer intermediateSize = originalImageLargestDim,
                                previousIntermediateSize = originalImageLargestDim;
                        Integer calculatedDim;
                        for (Integer i = 0; i < numSteps; i++) {
                            if (i + 1 != centerStep) //if this isn't the center step
                            {
                                if (i == numSteps - 1) //if this is the last step
                                {
                                    //fix the stepsize to account for decimal place errors previously
                                    currentStepSize = previousIntermediateSize - largestDimension;
                                } else {
                                    if (numSteps - i > numSteps / 2) //if we're in the first half of the reductions
                                        currentStepSize = heavierStepSize;
                                    else
                                        currentStepSize = lighterStepSize;
                                }
                            } else //center step, use natural step size
                            {
                                currentStepSize = stepSize;
                            }
                            intermediateSize = previousIntermediateSize - currentStepSize;
                            scale = (double) intermediateSize / (double) previousIntermediateSize;
                            scaledW = (int) scaledW * scale;
                            scaledH = (int) scaledH * scale;
                            outImage = new BufferedImage((int) scaledW, (int) scaledH, BufferedImage.TYPE_INT_RGB);
                            g2d = outImage.createGraphics();
                            g2d.setBackground(Color.WHITE);
                            g2d.clearRect(0, 0, outImage.getWidth(), outImage.getHeight());
                            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                            tx = new AffineTransform();
                            tx.scale(scale, scale);
                            g2d.drawImage(inImage, tx, null);
                            g2d.dispose();
                            inImage = new ImageIcon(outImage).getImage();
                            previousIntermediateSize = intermediateSize;
                        }
                    } else {
                        //just copy the original
                        outImage = new BufferedImage(inImage.getWidth(null), inImage.getHeight(null),
                                BufferedImage.TYPE_INT_RGB);
                        g2d = outImage.createGraphics();
                        g2d.setBackground(Color.WHITE);
                        g2d.clearRect(0, 0, outImage.getWidth(), outImage.getHeight());
                        tx = new AffineTransform();
                        tx.setToIdentity(); //use identity matrix so image is copied exactly
                        g2d.drawImage(inImage, tx, null);
                        g2d.dispose();
                    }
                    //JPEG-encode the image and write to file.
                    OutputStream os = new FileOutputStream(outFilename);
                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(os);
                    encoder.encode(outImage);
                    os.close();
                }
            }
        } catch (Exception ex) {
            String errorMsg = "";
            errorMsg += "<br>Exception: " + ex.toString();
            errorMsg += "<br>Cause = " + ex.getCause();
            errorMsg += "<br>Stack Trace = ";
            StackTraceElement stackTrace[] = ex.getStackTrace();
            for (int traceLine = 0; traceLine < stackTrace.length; traceLine++) {
                errorMsg += "<br>" + stackTrace[traceLine];
            }
            return errorMsg;
        }
        return ""; //success
    }
}