/***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package com.kitfox.svg.batik; import java.awt.Color; import java.awt.Composite; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferShort; import java.awt.image.DataBufferUShort; import java.awt.image.DirectColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import java.awt.image.renderable.RenderContext; import java.awt.image.renderable.RenderableImage; import java.lang.ref.Reference; import java.lang.ref.WeakReference; /** * * @author kitfox */ public class GraphicsUtil { /** Creates a new instance of GraphicsUtil */ public GraphicsUtil() { } /** * Create a new ColorModel with it's alpha premultiplied state matching * newAlphaPreMult. * @param cm The ColorModel to change the alpha premult state of. * @param newAlphaPreMult The new state of alpha premult. * @return A new colorModel that has isAlphaPremultiplied() * equal to newAlphaPreMult. */ public static ColorModel coerceColorModel(ColorModel cm, boolean newAlphaPreMult) { if (cm.isAlphaPremultiplied() == newAlphaPreMult) return cm; // Easiest way to build proper colormodel for new Alpha state... // Eventually this should switch on known ColorModel types and // only fall back on this hack when the CM type is unknown. WritableRaster wr = cm.createCompatibleWritableRaster(1,1); return cm.coerceData(wr, newAlphaPreMult); } /** * Coerces data within a bufferedImage to match newAlphaPreMult, * Note that this can not change the colormodel of bi so you * * @param wr The raster to change the state of. * @param cm The colormodel currently associated with data in wr. * @param newAlphaPreMult The desired state of alpha Premult for raster. * @return A new colormodel that matches newAlphaPreMult. */ public static ColorModel coerceData(WritableRaster wr, ColorModel cm, boolean newAlphaPreMult) { // System.out.println("CoerceData: " + cm.isAlphaPremultiplied() + // " Out: " + newAlphaPreMult); if (cm.hasAlpha()== false) // Nothing to do no alpha channel return cm; if (cm.isAlphaPremultiplied() == newAlphaPreMult) // nothing to do alpha state matches... return cm; // System.out.println("CoerceData: " + wr.getSampleModel()); int [] pixel = null; int bands = wr.getNumBands(); float norm; if (newAlphaPreMult) { if (is_BYTE_COMP_Data(wr.getSampleModel())) mult_BYTE_COMP_Data(wr); else if (is_INT_PACK_Data(wr.getSampleModel(), true)) mult_INT_PACK_Data(wr); else { norm = 1f/255f; int x0, x1, y0, y1, a, b; float alpha; x0 = wr.getMinX(); x1 = x0+wr.getWidth(); y0 = wr.getMinY(); y1 = y0+wr.getHeight(); for (int y=y0; y= 0) && (a < 255)) { alpha = a*norm; for (b=0; b 0) && (a < 255)) { ialpha = 255/(float)a; for (b=0; b>>24; if ((a>=0) && (a<255)) { pixels[sp] = ((a << 24) | ((((pixel&0xFF0000)*a)>>8)&0xFF0000) | ((((pixel&0x00FF00)*a)>>8)&0x00FF00) | ((((pixel&0x0000FF)*a)>>8)&0x0000FF)); } sp++; } } } protected static void divide_INT_PACK_Data(WritableRaster wr) { // System.out.println("Divide Int"); SinglePixelPackedSampleModel sppsm; sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel(); final int width = wr.getWidth(); final int scanStride = sppsm.getScanlineStride(); DataBufferInt db = (DataBufferInt)wr.getDataBuffer(); final int base = (db.getOffset() + sppsm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(), wr.getMinY()-wr.getSampleModelTranslateY())); int pixel, a, aFP, n=0; // Access the pixel data array final int pixels[] = db.getBankData()[0]; for (int y=0; y>>24; if (a<=0) { pixels[sp] = 0x00FFFFFF; } else if (a<255) { aFP = (0x00FF0000/a); pixels[sp] = ((a << 24) | (((((pixel&0xFF0000)>>16)*aFP)&0xFF0000) ) | (((((pixel&0x00FF00)>>8) *aFP)&0xFF0000)>>8 ) | (((((pixel&0x0000FF)) *aFP)&0xFF0000)>>16)); } sp++; } } } public static boolean is_BYTE_COMP_Data(SampleModel sm) { // Check ColorModel is of type DirectColorModel if(!(sm instanceof ComponentSampleModel)) return false; // Check transfer type if(sm.getDataType() != DataBuffer.TYPE_BYTE) return false; return true; } protected static void mult_BYTE_COMP_Data(WritableRaster wr) { // System.out.println("Multiply Int: " + wr); ComponentSampleModel csm; csm = (ComponentSampleModel)wr.getSampleModel(); final int width = wr.getWidth(); final int scanStride = csm.getScanlineStride(); final int pixStride = csm.getPixelStride(); final int [] bandOff = csm.getBandOffsets(); DataBufferByte db = (DataBufferByte)wr.getDataBuffer(); final int base = (db.getOffset() + csm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(), wr.getMinY()-wr.getSampleModelTranslateY())); int a=0; int aOff = bandOff[bandOff.length-1]; int bands = bandOff.length-1; int b, i; // Access the pixel data array final byte pixels[] = db.getBankData()[0]; for (int y=0; y>8); } sp+=pixStride; } } } protected static void divide_BYTE_COMP_Data(WritableRaster wr) { // System.out.println("Multiply Int: " + wr); ComponentSampleModel csm; csm = (ComponentSampleModel)wr.getSampleModel(); final int width = wr.getWidth(); final int scanStride = csm.getScanlineStride(); final int pixStride = csm.getPixelStride(); final int [] bandOff = csm.getBandOffsets(); DataBufferByte db = (DataBufferByte)wr.getDataBuffer(); final int base = (db.getOffset() + csm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(), wr.getMinY()-wr.getSampleModelTranslateY())); int a=0; int aOff = bandOff[bandOff.length-1]; int bands = bandOff.length-1; int b, i; // Access the pixel data array final byte pixels[] = db.getBankData()[0]; for (int y=0; y>>16); } } sp+=pixStride; } } } }