org.jamwiki.utils.ImageUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.jamwiki.utils.ImageUtil.java

Source

/**
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, version 2.1, dated February 1999.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the latest version of the GNU Lesser General
 * Public License as published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program (LICENSE.txt); if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.jamwiki.utils;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import javax.imageio.ImageIO;
import net.sf.ehcache.Element;
import org.jamwiki.Environment;
import org.jamwiki.model.WikiImage;
import org.jamwiki.model.WikiFile;
import org.springframework.util.Assert;

/**
 * Utility methods for readding images from disk, saving images to disk,
 * resizing images, and returning information about images such as width and
 * height.
 */
public class ImageUtil {

    private static final WikiLogger logger = WikiLogger.getLogger(ImageUtil.class.getName());
    private static final String CACHE_IMAGES = "org.jamwiki.utils.ImageUtils.CACHE_IMAGES";

    /**
     *
     */
    private ImageUtil() {
    }

    /**
     *
     */
    private static int calculateImageIncrement(int maxDimension) {
        int increment = Environment.getIntValue(Environment.PROP_IMAGE_RESIZE_INCREMENT);
        double result = Math.ceil((double) maxDimension / (double) increment) * increment;
        return (int) result;
    }

    /**
     * Convert a Java Image object to a Java BufferedImage object.
     */
    private static BufferedImage imageToBufferedImage(Image image) throws Exception {
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null),
                BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = bufferedImage.createGraphics();
        graphics.drawImage(image, 0, 0, null);
        graphics.dispose();
        return bufferedImage;
    }

    /**
     * Given a virtualWiki and WikiFIle that correspond to an existing image,
     * return the WikiImage object.  In addition, an optional maxDimension
     * parameter may be specified, in which case a resized version of the image
     * may be created.
     *
     * @param wikiFile Given a WikiFile object, use it to initialize a
     *  WikiImage object.
     * @param maxDimension The maximum width or height for the initialized
     *  WikiImage object.  Setting this value to 0 or less will cause the
     *  value to be ignored.
     * @return An initialized WikiImage object.
     * @throws Exception Thrown if an error occurs while initializing the
     *  WikiImage object.
     */
    public static WikiImage initializeImage(WikiFile wikiFile, int maxDimension) throws Exception {
        Assert.notNull(wikiFile, "wikiFile may not be null");
        WikiImage wikiImage = new WikiImage(wikiFile);
        BufferedImage imageObject = null;
        if (maxDimension > 0) {
            imageObject = ImageUtil.resizeImage(wikiImage, maxDimension);
            setScaledDimensions(imageObject, wikiImage, maxDimension);
        } else {
            File imageFile = new File(Environment.getValue(Environment.PROP_FILE_DIR_FULL_PATH),
                    wikiImage.getUrl());
            imageObject = ImageUtil.loadImage(imageFile);
            wikiImage.setWidth(imageObject.getWidth());
            wikiImage.setHeight(imageObject.getHeight());
        }
        return wikiImage;
    }

    /**
     * Given a File object, determine if the file is an image or if it is some
     * other type of file.  Note that this method will read in the entire file,
     * so there are performance implications for large files.
     *
     * @param file The File object for the file that is being examined.
     * @return Returns <code>true</code> if the file is an image object.
     * @throws Exception Thrown if any error occurs while reading the file.
     */
    public static boolean isImage(File file) throws Exception {
        return (ImageUtil.loadImage(file) != null);
    }

    /**
     * Given a file that corresponds to an existing image, return a
     * BufferedImage object.
     */
    private static BufferedImage loadImage(File file) throws Exception {
        BufferedImage image = null;
        String key = file.getPath();
        Element cacheElement = WikiCache.retrieveFromCache(CACHE_IMAGES, key);
        if (cacheElement != null) {
            return (BufferedImage) cacheElement.getObjectValue();
        }
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            image = ImageIO.read(fis);
            WikiCache.addToCache(CACHE_IMAGES, key, image);
            return image;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (Exception e) {
                }
            }
        }
    }

    /**
     * Resize an image, using a maximum dimension value.  Image dimensions will
     * be constrained so that the proportions are the same, but neither the width
     * or height exceeds the value specified.
     */
    private static BufferedImage resizeImage(WikiImage wikiImage, int maxDimension) throws Exception {
        File imageFile = new File(Environment.getValue(Environment.PROP_FILE_DIR_FULL_PATH), wikiImage.getUrl());
        BufferedImage original = ImageUtil.loadImage(imageFile);
        maxDimension = calculateImageIncrement(maxDimension);
        int increment = Environment.getIntValue(Environment.PROP_IMAGE_RESIZE_INCREMENT);
        if (increment <= 0 || (maxDimension > original.getWidth() && maxDimension > original.getHeight())) {
            // let the browser scale the image
            return original;
        }
        String newUrl = wikiImage.getUrl();
        int pos = newUrl.lastIndexOf('.');
        if (pos > -1) {
            newUrl = newUrl.substring(0, pos) + "-" + maxDimension + "px" + newUrl.substring(pos);
        } else {
            newUrl += "-" + maxDimension + "px";
        }
        wikiImage.setUrl(newUrl);
        File newImageFile = new File(Environment.getValue(Environment.PROP_FILE_DIR_FULL_PATH), newUrl);
        if (newImageFile.exists()) {
            return ImageUtil.loadImage(newImageFile);
        }
        int width = -1;
        int height = -1;
        if (original.getWidth() >= original.getHeight()) {
            width = maxDimension;
        } else {
            height = maxDimension;
        }
        Image resized = null;
        try {
            resized = original.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING);
        } catch (Throwable t) {
            logger.severe(
                    "Unable to resize image.  This problem sometimes occurs due to dependencies between Java and X on UNIX systems.  Consider enabling an X server or setting the java.awt.headless parameter to true for your JVM.",
                    t);
            resized = original;
        }
        BufferedImage bufferedImage = null;
        if (resized instanceof BufferedImage) {
            bufferedImage = (BufferedImage) resized;
        } else {
            bufferedImage = ImageUtil.imageToBufferedImage(resized);
        }
        ImageUtil.saveImage(bufferedImage, newImageFile);
        return bufferedImage;
    }

    /**
     * Save an image to a specified file.
     */
    private static void saveImage(BufferedImage image, File file) throws Exception {
        String filename = file.getName();
        int pos = filename.lastIndexOf('.');
        if (pos == -1 || (pos + 1) >= filename.length()) {
            throw new Exception("Unknown image type " + filename);
        }
        String imageType = filename.substring(pos + 1);
        File imageFile = new File(file.getParent(), filename);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(imageFile);
            ImageIO.write(image, imageType, fos);
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
                }
            }
        }
    }

    /**
     *
     */
    private static void setScaledDimensions(BufferedImage bufferedImage, WikiImage wikiImage, int maxDimension) {
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        if (width >= height) {
            height = (int) Math.floor(((double) maxDimension / (double) width) * (double) height);
            width = maxDimension;
        } else {
            width = (int) Math.floor(((double) maxDimension / (double) height) * (double) width);
            height = maxDimension;
        }
        wikiImage.setWidth(width);
        wikiImage.setHeight(height);
    }
}