/*
* @(#)Images.java
*
* Copyright (c) 1996-2010 The authors and contributors of JHotDraw.
* You may not use, copy or modify this file, except in compliance with the
* accompanying license terms.
*/
package org.jhotdraw.util;
import java.awt.*;
import java.awt.image.*;
import java.net.*;
import javax.swing.*;
/**
* Image processing methods.
*
* @author Werner Randelshofer
* @version $Id$
*/
public class Images {
/** Prevent instance creation. */
private Images() {
}
public static Image createImage(Class<?> baseClass, String resourceName) {
URL resource = baseClass.getResource(resourceName);
if (resource == null) {
throw new InternalError("Ressource \"" + resourceName + "\" not found for class " + baseClass);
}
Image image = Toolkit.getDefaultToolkit().createImage(resource);
return image;
}
public static Image createImage(URL resource) {
if (resource == null) {
throw new IllegalArgumentException("resource must not be null");
}
Image image = Toolkit.getDefaultToolkit().createImage(resource);
return image;
}
/**
* Converts an Image to BufferedImage. If the Image is already a
* BufferedImage, the same image is returned.
*
* @param rImg An Image.
* @return A BufferedImage.
*/
public static BufferedImage toBufferedImage(RenderedImage rImg) {
BufferedImage image;
if (rImg instanceof BufferedImage) {
image = (BufferedImage) rImg;
} else {
Raster r = rImg.getData();
WritableRaster wr = WritableRaster.createWritableRaster(
r.getSampleModel(), null);
rImg.copyData(wr);
image = new BufferedImage(
rImg.getColorModel(),
wr,
rImg.getColorModel().isAlphaPremultiplied(),
null);
}
return image;
}
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage) image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
// Create a buffered image with a format that's compatible with the screen
BufferedImage bimage = null;
if (System.getProperty("java.version").startsWith("1.4.1_")) {
// Workaround for Java 1.4.1 on Mac OS X.
// For this JVM, we always create an ARGB image to prevent a class
// cast exception in
// sun.awt.image.BufImgSurfaceData.createData(BufImgSurfaceData.java:434)
// when we attempt to draw the buffered image.
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
} else {
// Determine if the image has transparent pixels; for this method's
// implementation, see e661 Determining If an Image Has Transparent Pixels
boolean hasAlpha;
try {
hasAlpha = hasAlpha(image);
} catch (IllegalAccessError e) {
// If we can't determine this, we assume that we have an alpha,
// in order not to loose data.
hasAlpha = true;
}
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try {
// Determine the type of transparency of the new buffered image
int transparency = Transparency.OPAQUE;
if (hasAlpha) {
transparency = Transparency.TRANSLUCENT;
}
// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(
image.getWidth(null), image.getHeight(null), transparency);
} catch (Exception e) {
//} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
if (hasAlpha) {
type = BufferedImage.TYPE_INT_ARGB;
}
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
}
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
/**
* This method returns true if the specified image has transparent pixels
*
* Code taken from the Java Developers Almanac 1.4
* http://javaalmanac.com/egs/java.awt.image/HasAlpha.html
*/
public static boolean hasAlpha(Image image) {
// If buffered image, the color model is readily available
if (image instanceof BufferedImage) {
BufferedImage bimage = (BufferedImage) image;
return bimage.getColorModel().hasAlpha();
}
// Use a pixel grabber to retrieve the image's color model;
// grabbing a single pixel is usually sufficient
PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
// Get the image's color model
ColorModel cm = pg.getColorModel();
return cm.hasAlpha();
}
/**
* Splits an image into count subimages.
*/
public static BufferedImage[] split(Image image, int count, boolean isHorizontal) {
BufferedImage src = Images.toBufferedImage(image);
if (count == 1) {
return new BufferedImage[]{src};
}
BufferedImage[] parts = new BufferedImage[count];
for (int i = 0; i < count; i++) {
if (isHorizontal) {
parts[i] = src.getSubimage(
src.getWidth() / count * i, 0,
src.getWidth() / count, src.getHeight());
} else {
parts[i] = src.getSubimage(
0, src.getHeight() / count * i,
src.getWidth(), src.getHeight() / count);
}
}
return parts;
}
/** Creates a scaled instanceof the image.
* <p>
* If either width or height is a negative number then a value is s
* ubstituted to maintain the aspect ratio of the original image dimensions.
* If both width and height are negative, then the original image dimensions
* are used.
* <p>
* On Mac OS X 10.6, this method has a much better performance than
* BufferedImage.getScaledInstance.
*
*
* @param image the image.
* @param width the width to which to scale the image.
* @param height the height to which to scale the image.
*/
public static BufferedImage getScaledInstance(Image image, int width, int height) {
int w, h;
if (width<0&&height<0) {
w=image.getWidth(null);
h=image.getHeight(null);
} else if (width<0) {
w=image.getWidth(null)*height/image.getHeight(null);
h=height;
} else if (height<0) {
w=width;
h=image.getHeight(null)*width/image.getWidth(null);
} else {
w=width;
h=height;
}
BufferedImage scaled = new BufferedImage(w,h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = scaled.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.drawImage(image, 0, 0, w, h, null);
g.dispose();
return scaled;
}
}