package net.sourceforge.javautil.common;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
/**
* Utilities for image manipulation.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: ImageUtil.java 1536 2009-12-03 22:51:08Z ponderator $
*/
public class ImageUtil {
/**
* This will produce a high quality scaled version of the original image.
*
* @param original The original image
* @param width The new width
* @param height The new height
* @return The new image in the specified format
*
* @see #getScaledInstance(BufferedImage, int, int, Object, boolean)
*/
public static byte[] scaleImage (byte[] original, String format, int width, int height) {
try {
BufferedImage bsrc = ImageIO.read(new ByteArrayInputStream(original));
if (bsrc == null) throw new UnsupportedOperationException("Format of original image not supported");
int newwidth = width == -1 ? (( bsrc.getWidth() / ( bsrc.getHeight() / height ) )) : width;
int newheight = height == -1 ? (( bsrc.getHeight() / ( bsrc.getWidth() / width ) )) : height;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(getScaledInstance(bsrc, newwidth, newheight, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true), format, baos);
return baos.toByteArray();
} catch (IOException e) {
throw ThrowableManagerRegistry.caught(e);
}
}
/**
* @param img The original image
* @param targetWidth The target width
* @param targetHeight The target height
* @param hint @see {@link RenderingHints}
* @param higherQuality True if a more processing expensive operation should be used to provide higher quality, otherwise false
* @return The new scaled image.
*/
public 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;
}
}