package me.chenyi.mm.util;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
/**
* General utility methods for doing stuff to images, such as resizes
*
* @author $Author:$
* @version $Revision:$
*/
public class ImageUtils
{
/**
* Load the named image off disk and pre-scale it to the requested maximum
* dimensions. The max is assuming a square image and will rescale the
* incoming image so that is the max in either direction, while maintaining
* the aspect ratio.
*
* @param file The name of the files to load
* @param maxDimension The maximum size to allow
* @return A loaded, but not cached image of the correct size or null if it failed
*/
public static BufferedImage loadScaledImage(File file, int maxDimension)
{
BufferedImage ret_val = null;
try
{
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int readLength = -1;
while ((readLength = fis.read(buffer)) != -1)
{
baos.write(buffer, 0, readLength);
}
ret_val = ImageController.loadUncachedImage(baos.toByteArray());
if(ret_val.getWidth(null) > maxDimension ||
ret_val.getHeight(null) > maxDimension)
{
ret_val = ImageUtils.resizeImage(ret_val, maxDimension);
}
}
catch(FileNotFoundException ex)
{
ex.printStackTrace();
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
return ret_val;
}
/**
* Convert a Jawa image to the underlying byte array.
*
* @param img The imput image to process
* @return A corresponding byte array
*/
public static byte[] imageToBytes(BufferedImage img)
{
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try
{
ImageIO.write(img, "jpg", buffer);
}
catch(IOException e)
{
e.printStackTrace();
}
return buffer.toByteArray();
}
/**
* Scale an image. Generally used to scale an image to a power of 2.
*
* @param image The image to scale
* @param maxDimension The maximum size to allow
* @return A loaded, but not cached image of the correct size
*/
public static BufferedImage resizeImage(Image image, int maxDimension) throws IOException
{
BufferedImage ret_val = null;
if(image instanceof BufferedImage)
ret_val = resizeImage((BufferedImage)image, maxDimension);
else if(image != null)
{
// need to convert the image to a buffered image
BufferedImage b_img = new BufferedImage(image.getWidth(null),
image.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
Graphics g = b_img.getGraphics();
g.drawImage(image, 0, 0, null);
ret_val = resizeImage(b_img, maxDimension);
}
return ret_val;
}
/**
* Scale an image. Generally used to scale an image to a power of 2.
*
* @param image The image to scale
* @param maxDimension The maximum size to allow
* @return A loaded, but not cached image of the correct size
*/
public static BufferedImage resizeImage(BufferedImage image, int maxDimension) throws IOException
{
int newWidth = 0;
int newHeight = 0;
float srcWidth = image.getWidth();
float srcHeight = image.getHeight();
if(srcWidth > srcHeight)
{
float scale = maxDimension / srcWidth;
newWidth = maxDimension;
newHeight = (int)(srcHeight * scale);
}
else
{
float scale = maxDimension / srcHeight;
newWidth = (int)(srcWidth * scale);
newHeight = maxDimension;
}
boolean hasAlpha = image.getColorModel( ).hasAlpha( );
if(hasAlpha && (newWidth <= 64) && (newHeight <= 64))
{
return scalePretty(image, newWidth, newHeight);
}
double xScale = (float)newWidth / (float)srcWidth;
double yScale = (float)newHeight / (float)srcHeight;
AffineTransform at = AffineTransform.getScaleInstance( xScale, yScale );
AffineTransformOp atop = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
BufferedImage ret_image = null;
if(hasAlpha)
{
ret_image = atop.filter( image, null );
}
else
{
ret_image = new BufferedImage( newWidth, newHeight, image.getType( ) );
atop.filter( image, ret_image );
}
return ret_image ;
}
/**
* Scale an image. Generally used to scale an image to a power of 2.
*
* @param image The image to scale
* @param newWidth The new width
* @param newHeight The new height
*/
private static BufferedImage scalePretty(BufferedImage image, int newWidth, int newHeight)
{
Image rimg = image.getScaledInstance(newWidth, newHeight,
Image.SCALE_AREA_AVERAGING);
boolean hasAlpha = image.getColorModel().hasAlpha();
BufferedImage ret_image = null;
// Not sure why .getType doesn't work right for this
if(hasAlpha)
{
ret_image = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
}
else
{
ret_image = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
}
Graphics2D g2 = ret_image.createGraphics();
g2.drawImage(rimg, 0, 0, null);
return ret_image;
}
}