/* ****************************************************************************** * Copyright (c) 2006-2013 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.de.erichseifert.vectorgraphics2d.util; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.HeadlessException; import java.awt.Image; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.PixelGrabber; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.WritableRaster; import java.util.Hashtable; import javax.swing.ImageIcon; /** * Abstract class that contains utility functions for working with graphics. For * example, this includes font handling. * * @author Jason Wong */ public abstract class GraphicsUtils { /** * Default constructor that prevents creation of class. */ protected GraphicsUtils() { throw new UnsupportedOperationException(); } /** * This method returns {@code true} if the specified image has the * possibility to store transparent pixels. Inspired by * http://www.exampledepot.com/egs/java.awt.image/HasAlpha.html * * @param image * Image that should be checked for alpha channel. * @return {@code true} if the specified image can have transparent pixels, * {@code false} otherwise */ public static boolean hasAlpha(Image image) { ColorModel cm; // If buffered image, the color model is readily available if (image instanceof BufferedImage) { BufferedImage bimage = (BufferedImage) image; cm = bimage.getColorModel(); } else { // 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) { return false; } // Get the image's color model cm = pg.getColorModel(); } return cm.hasAlpha(); } /** * This method returns {@code true} if the specified image has at least one * pixel that is not fully opaque. * * @param image * Image that should be checked for non-opaque pixels. * @return {@code true} if the specified image has transparent pixels, * {@code false} otherwise */ public static boolean usesAlpha(Image image) { if (image == null) { return false; } BufferedImage bimage = toBufferedImage(image); Raster alphaRaster = bimage.getAlphaRaster(); if (alphaRaster == null) { return false; } DataBuffer dataBuffer = alphaRaster.getDataBuffer(); for (int i = 0; i < dataBuffer.getSize(); i++) { int alpha = dataBuffer.getElem(i); if (alpha < 255) { return true; } } return false; } /** * Converts an arbitrary image to a {@code BufferedImage}. * * @param image * Image that should be converted. * @return a buffered image containing the image pixels, or the original * instance if the image already was of type {@code BufferedImage}. */ public static BufferedImage toBufferedImage(RenderedImage image) { if (image instanceof BufferedImage) { return (BufferedImage) image; } ColorModel cm = image.getColorModel(); WritableRaster raster = cm.createCompatibleWritableRaster( image.getWidth(), image.getHeight()); boolean isRasterPremultiplied = cm.isAlphaPremultiplied(); Hashtable<String, Object> properties = null; if (image.getPropertyNames() != null) { properties = new Hashtable<String, Object>(); for (String key : image.getPropertyNames()) { properties.put(key, image.getProperty(key)); } } BufferedImage bimage = new BufferedImage(cm, raster, isRasterPremultiplied, properties); image.copyData(raster); return bimage; } /** * This method returns a buffered image with the contents of an image. Taken * from http://www.exampledepot.com/egs/java.awt.image/Image2Buf.html * * @param image * Image to be converted * @return a buffered image with the contents of the specified 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(); // Determine if the image has transparent pixels boolean hasAlpha = hasAlpha(image); // Create a buffered image with a format that's compatible with the // screen BufferedImage bimage = null; 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 (HeadlessException e) { // The system does not have a screen bimage = null; } 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; } }