package com.palantir.ui; import java.awt.Composite; import java.awt.CompositeContext; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; /** * A {@link Composite} implementation that uses the destination RGB and the source alpha. * This can be used to perform alpha gradients. */ public class SourceAlphaComposite implements Composite, CompositeContext { public static SourceAlphaComposite createComposite(final BufferedImage bimage) throws UnsupportedBufferException { return createComposite(bimage.getType()); } /** * This factory currently supports TYPE_4BYTE_ABGR and TYPE_INT_ARGB. */ public static SourceAlphaComposite createComposite(int type) throws UnsupportedBufferException { switch ( type ) { case BufferedImage.TYPE_4BYTE_ABGR: case BufferedImage.TYPE_INT_ARGB: return new SourceAlphaComposite( 3 ); default: throw new UnsupportedBufferException(); } } private final int alphaIndex; public SourceAlphaComposite(final int alphaIndex) { if ( alphaIndex < 0 ) { throw new IllegalArgumentException( "There is no way a negative index will work." ); } this.alphaIndex = alphaIndex; } public int getAlphaIndex() { return alphaIndex; } public CompositeContext createContext( final ColorModel srcColorModel, final ColorModel dstColorModel, final RenderingHints hints ) { return this; } public void dispose() { // Do nothing } public void compose(final Raster src, final Raster dstIn, final WritableRaster dstOut) { final int w = dstOut.getWidth(), h = dstOut.getHeight(); final int n = src.getNumBands(); final int[] spixel = new int[ n ], opixel = new int[ n ], dpixel = new int[ n ]; for ( int x = 0; w > x; x++ ) for ( int y = 0; h > y; y++ ) { src.getPixel( x, y, spixel ); dstIn.getPixel( x, y, dpixel ); // Use the destination color (except use the source alpha, below): System.arraycopy( dpixel, 0, opixel, 0, opixel.length ); final int dalpha = dpixel[ alphaIndex ]; if ( 0 != dalpha ) { // Use the source alpha: opixel[ alphaIndex ] = dalpha * spixel[ alphaIndex ] / 0xFF; } dstOut.setPixel( x, y, opixel ); } } /** * Exception we throw for images that we don't support. */ public static class UnsupportedBufferException extends Exception { public UnsupportedBufferException() { } public UnsupportedBufferException(final Exception cause) { super( cause ); } } }