All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.britesnow.snow.util.image.ImageProcessor Maven / Gradle / Ivy

There is a newer version: 2.0.9
Show newest version
/* Copyright 2009 Jeremy Chone - Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 */
package com.britesnow.snow.util.image;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Singleton;

@Singleton
public class ImageProcessor {
    static private Logger logger = LoggerFactory.getLogger(ImageProcessor.class);
    
    public static int BUFFER_SIZE = 2048 * 2;

    public void resizeImage(File srcImageFile, File dstImageFile, int width, int height) throws Exception {
        FileInputStream imageInput = new FileInputStream(srcImageFile);
        InputStream newImageInput = scaleImageWithMultisteps(imageInput, width, height);

        FileOutputStream fos = new FileOutputStream(dstImageFile);
        BufferedInputStream newImageBis = new BufferedInputStream(newImageInput);

        try {
            byte[] buffer = new byte[BUFFER_SIZE];
            int len = buffer.length;
            while (true) {
                len = newImageBis.read(buffer);
                if (len == -1)
                    break;
                fos.write(buffer, 0, len);
            }

        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            fos.close();
            newImageBis.close();
        }

    }

    private InputStream scaleImageWithMultisteps(InputStream imageInput, int width, int height) throws Exception {

        InputStream imageStream = new BufferedInputStream(imageInput);
        Image image = (Image) ImageIO.read(imageStream);

        int thumbWidth = width;
        int thumbHeight = height;

        // Make sure the aspect ratio is maintained, so the image is not skewed
        double thumbRatio = (double) thumbWidth / (double) thumbHeight;
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        double imageRatio = (double) imageWidth / (double) imageHeight;
        if (thumbRatio < imageRatio) {
            thumbHeight = (int) (thumbWidth / imageRatio);
        } else {
            thumbWidth = (int) (thumbHeight * imageRatio);
        }

        //create the original BufferedImage
        BufferedImage imageBi = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D imageG = imageBi.createGraphics();
        imageG.drawImage(image, 0, 0, imageWidth, imageHeight, null);

        BufferedImage thumbImage = getScaledInstance(imageBi, thumbWidth, thumbHeight,
                                RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
        /* --------- //Blur the original image for better scaling --------- */

        // Write the scaled image to the outputstream
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        //PNGImageWriter pngWriter = new PNGImageWriter()

        ImageIO.write(thumbImage, "PNG", out);

        // Read the outputstream into the inputstream for the return value
        ByteArrayInputStream bis = new ByteArrayInputStream(out.toByteArray());

        imageG.dispose();

        return bis;
    }

    /**
     * Convenience method that returns a scaled instance of the provided {@code
     * BufferedImage}.
     * 
     * @param img
     *            the original image to be scaled
     * @param targetWidth
     *            the desired width of the scaled instance, in pixels
     * @param targetHeight
     *            the desired height of the scaled instance, in pixels
     * @param hint
     *            one of the rendering hints that corresponds to {@code
     *            RenderingHints.KEY_INTERPOLATION} (e.g. {@code
     *            RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR}, {@code
     *            RenderingHints.VALUE_INTERPOLATION_BILINEAR}, {@code
     *            RenderingHints.VALUE_INTERPOLATION_BICUBIC})
     * @param higherQuality
     *            if true, this method will use a multi-step scaling technique
     *            that provides higher quality than the usual one-step technique
     *            (only useful in downscaling cases, where {@code targetWidth}
     *            or {@code targetHeight} is smaller than the original
     *            dimensions, and generally only when the {@code BILINEAR} hint
     *            is specified)
     * @return a scaled version of the original {@code BufferedImage}
     */
    private static BufferedImage getScaledInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint,
                                                   boolean higherQuality) {
        int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage ret = (BufferedImage) img;
        int w, h;
        if (higherQuality) {
            // Use multi-step technique: start with original size, then
            // scale down in multiple passes with drawImage()
            // until the target size is reached
            w = img.getWidth();
            h = img.getHeight();
        } else {
            // Use one-step technique: scale directly from original
            // size to target size with a single drawImage() call
            w = targetWidth;
            h = targetHeight;
        }

        do {
            if (higherQuality && w > targetWidth) {
                w /= 2;
                if (w < targetWidth) {
                    w = targetWidth;
                }
            }

            if (higherQuality && h > targetHeight) {
                h /= 2;
                if (h < targetHeight) {
                    h = targetHeight;
                }
            }

            BufferedImage tmp = new BufferedImage(w, h, type);
            Graphics2D g2 = tmp.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(ret, 0, 0, w, h, null);
            g2.dispose();

            ret = tmp;
        } while (w != targetWidth || h != targetHeight);

        return ret;
    }

    /*
    private InputStream scaleImageWithBlurTrick(InputStream imageInput, int width, int height) throws Exception {

        InputStream imageStream = new BufferedInputStream(imageInput);
        Image image = (Image) ImageIO.read(imageStream);

        int thumbWidth = width;
        int thumbHeight = height;

        // Make sure the aspect ratio is maintained, so the image is not skewed
        double thumbRatio = (double) thumbWidth / (double) thumbHeight;
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        double imageRatio = (double) imageWidth / (double) imageHeight;
        if (thumbRatio < imageRatio) {
            thumbHeight = (int) (thumbWidth / imageRatio);
        } else {
            thumbWidth = (int) (thumbHeight * imageRatio);
        }
        

        //This is not perfect, but better than not doing it.
        BufferedImage bi = new BufferedImage(imageWidth,imageHeight,BufferedImage.TYPE_INT_ARGB);
        Graphics2D imageG = bi.createGraphics();
        imageG.drawImage(image, 0, 0, imageWidth, imageHeight,null);
        bi = blurImage(bi);

        BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_ARGB);

        Graphics2D thumbG = thumbImage.createGraphics();
        thumbG.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        thumbG.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        thumbG.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        thumbG.drawImage(bi, 0, 0, thumbWidth, thumbHeight, null);
        
        // Write the scaled image to the outputstream
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        //PNGImageWriter pngWriter = new PNGImageWriter()

        
          JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
          JPEGEncodeParam param = encoder.
          getDefaultJPEGEncodeParam(thumbImage); int quality = 100; // Use
          between 1 and 100, with 100 being highest quality quality =
          Math.max(0, Math.min(quality, 100)); param.setQuality((float)quality
          / 100.0f, false); encoder.setJPEGEncodeParam(param);
          encoder.encode(thumbImage); ImageIO.write(thumbImage, "JPG" , out);
         

        ImageIO.write(thumbImage, "PNG", out);

        // Read the outputstream into the inputstream for the return value
        ByteArrayInputStream bis = new ByteArrayInputStream(out.toByteArray());

        imageG.dispose();
        thumbG.dispose();

        return bis;
    }
    */
    
    /*
    @SuppressWarnings("unchecked")
    private static BufferedImage blurImage(BufferedImage image) {
        float ninth = 1.0f / 9.0f;
        float[] blurKernel = { ninth, ninth, ninth, ninth, ninth, ninth, ninth, ninth, ninth };

        Map map = new HashMap();

        map.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        RenderingHints hints = new RenderingHints(map);
        BufferedImageOp op = new ConvolveOp(new Kernel(3, 3, blurKernel), ConvolveOp.EDGE_NO_OP, hints);
        return op.filter(image, null);
    }
    */
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy