/*

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */
package org.apache.batik.ext.awt.image;

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;

import org.apache.batik.ext.awt.RenderingHintsKeyExt;
import org.apache.batik.ext.awt.image.renderable.PaintRable;
import org.apache.batik.ext.awt.image.rendered.AffineRed;
import org.apache.batik.ext.awt.image.rendered.Any2LsRGBRed;
import org.apache.batik.ext.awt.image.rendered.Any2sRGBRed;
import org.apache.batik.ext.awt.image.rendered.BufferedImageCachableRed;
import org.apache.batik.ext.awt.image.rendered.CachableRed;
import org.apache.batik.ext.awt.image.rendered.FormatRed;
import org.apache.batik.ext.awt.image.rendered.RenderedImageCachableRed;
import org.apache.batik.ext.awt.image.rendered.TranslateRed;


/**
 * Set of utility methods for Graphics.
 * These generally bypass broken methods in Java2D or provide tweaked
 * implementations.
 *
 * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
 * @version $Id$
 */
public class GraphicsUtil {

    public static AffineTransform IDENTITY = new AffineTransform();

    /**
     * Draws <tt>ri</tt> into <tt>g2d</tt>.  It does this be
     * requesting tiles from <tt>ri</tt> and drawing them individually
     * in <tt>g2d</tt> it also takes care of some colorspace and alpha
     * issues.
     * @param g2d The Graphics2D to draw into.
     * @param ri  The image to be drawn.
     */
    public static void drawImage(Graphics2D g2d,
                                 RenderedImage ri) {
        drawImage(g2d, wrap(ri));
    }

    /**
     * Draws <tt>cr</tt> into <tt>g2d</tt>.  It does this be
     * requesting tiles from <tt>ri</tt> and drawing them individually
     * in <tt>g2d</tt> it also takes care of some colorspace and alpha
     * issues.
     * @param g2d The Graphics2D to draw into.
     * @param cr  The image to be drawn.
     */
    public static void drawImage(Graphics2D g2d,
                                 CachableRed cr) {

        // System.out.println("DrawImage G: " + g2d);

        AffineTransform at = null;
        while (true) {
            if (cr instanceof AffineRed) {
                AffineRed ar = (AffineRed)cr;
                if (at == null)
                    at = ar.getTransform();
                else
                    at.concatenate(ar.getTransform());
                cr = ar.getSource();
                continue;
            } else if (cr instanceof TranslateRed) {
                TranslateRed tr = (TranslateRed)cr;
                // System.out.println("testing Translate");
                int dx = tr.getDeltaX();
                int dy = tr.getDeltaY();
                if (at == null)
                    at = AffineTransform.getTranslateInstance(dx, dy);
                else
                    at.translate(dx, dy);
                cr = tr.getSource();
                continue;
            }
            break;
        }
        AffineTransform g2dAt   = g2d.getTransform();
        if ((at == null) || (at.isIdentity()))
            at = g2dAt;
        else
            at.preConcatenate(g2dAt);

        ColorModel srcCM = cr.getColorModel();
        ColorModel g2dCM = getDestinationColorModel(g2d);
        ColorSpace g2dCS = null;
        if (g2dCM != null)
            g2dCS = g2dCM.getColorSpace();
        if (g2dCS == null)
            // Assume device is sRGB
            g2dCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);

        ColorModel drawCM = g2dCM;
        if ((g2dCM == null) || !g2dCM.hasAlpha()) {
            // If we can't find out about our device or the device
            // does not support alpha just use SRGB unpremultiplied
            // (Just because this seems to work for us).
            drawCM = sRGB_Unpre;
        }

        if (cr instanceof BufferedImageCachableRed) {
            // There is a huge win if we can use the BI directly here.
            // This results in something like a 10x performance gain
            // for images, the best thing is this is the common case.
            if (g2dCS.equals(srcCM.getColorSpace()) &&
                drawCM.equals(srcCM)) {
                // System.err.println("Fast Case");
                g2d.setTransform(at);
                BufferedImageCachableRed bicr;
                bicr = (BufferedImageCachableRed)cr;
                g2d.drawImage(bicr.getBufferedImage(),
                              bicr.getMinX(), bicr.getMinY(), null);
                g2d.setTransform(g2dAt);
                return;
            }
        }

        // Scaling down so do it before color conversion.
        double determinant = at.getDeterminant();
        if (!at.isIdentity() && (determinant <= 1.0)) {
            if (at.getType() != AffineTransform.TYPE_TRANSLATION)
                cr = new AffineRed(cr, at, g2d.getRenderingHints());
            else {
                int xloc = cr.getMinX() + (int)at.getTranslateX();
                int yloc = cr.getMinY() + (int)at.getTranslateY();
                cr = new TranslateRed(cr, xloc, yloc);
            }
        }

        if (g2dCS != srcCM.getColorSpace()) {
            // System.out.println("srcCS: " + srcCM.getColorSpace());
            // System.out.println("g2dCS: " + g2dCS);
            // System.out.println("sRGB: " +
            //                    ColorSpace.getInstance(ColorSpace.CS_sRGB));
            // System.out.println("LsRGB: " +
            //                    ColorSpace.getInstance
            //                    (ColorSpace.CS_LINEAR_RGB));
            if      (g2dCS == ColorSpace.getInstance(ColorSpace.CS_sRGB))
                cr = convertTosRGB(cr);
            else if (g2dCS == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB))
                cr = convertToLsRGB(cr);
        }
        srcCM = cr.getColorModel();
        if (!drawCM.equals(srcCM))
            cr = FormatRed.construct(cr, drawCM);

        // Scaling up so do it after color conversion.
        if (!at.isIdentity() && (determinant > 1.0))
            cr = new AffineRed(cr, at, g2d.getRenderingHints());

        // Now CR is in device space, so clear the g2d transform.
        g2d.setTransform(IDENTITY);

        // Ugly Hack alert.  This Makes it use our SrcOver implementation
        // Which doesn't seem to have as many bugs as the JDK one when
        // going between different src's and destinations (of course it's
        // also a lot slower).
        Composite g2dComposite = g2d.getComposite();
        if (g2d.getRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING) ==
            RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING) {
            if (SVGComposite.OVER.equals(g2dComposite)) {
                g2d.setComposite(SVGComposite.OVER);
            }
        }
        Rectangle crR  = cr.getBounds();
        Shape     clip = g2d.getClip();

        try {
            Rectangle clipR;
            if (clip == null) {
                clip  = crR;
                clipR = crR;
            } else {
                clipR   = clip.getBounds();

                if ( ! clipR.intersects(crR) )
                    return; // Nothing to draw...
                clipR = clipR.intersection(crR);
            }

            Rectangle gcR = getDestinationBounds(g2d);
            // System.out.println("ClipRects: " + clipR + " -> " + gcR);
            if (gcR != null) {
                if ( ! clipR.intersects(gcR) )
                    return; // Nothing to draw...
                clipR = clipR.intersection(gcR);
            }

            // System.out.println("Starting Draw: " + cr);
            // long startTime = System.currentTimeMillis();

            boolean useDrawRenderedImage = false;

            srcCM = cr.getColorModel();
            SampleModel srcSM = cr.getSampleModel();
            if ((srcSM.getWidth()*srcSM.getHeight()) >=
                (clipR.width*clipR.height))
                // if srcSM tiles are around the clip size
                // then just draw the renderedImage
                useDrawRenderedImage = true;

            Object atpHint = g2d.getRenderingHint
                (RenderingHintsKeyExt.KEY_AVOID_TILE_PAINTING);

            if (atpHint == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_ON)
                useDrawRenderedImage = true; //for PDF and PS transcoders

            if (atpHint == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_OFF)
                useDrawRenderedImage = false;


            WritableRaster wr;
            if (useDrawRenderedImage) {
                // This can be significantly faster but can also
                // require much more memory, so we only use it when
                // the clip size is smaller than the tile size.
                Raster r = cr.getData(clipR);
                wr = ((WritableRaster)r).createWritableChild
                    (clipR.x, clipR.y, clipR.width, clipR.height,
                     0, 0, null);

                BufferedImage bi = new BufferedImage
                    (srcCM, wr, srcCM.isAlphaPremultiplied(), null);

                // Any of the drawImage calls that take an
                // Affine are prone to the 'CGGStackRestore: gstack
                // underflow' bug on Mac OS X.  This should work
                // around that problem.
                g2d.drawImage(bi, clipR.x, clipR.y, null);
            } else {
                // Use tiles to draw image...
                wr = Raster.createWritableRaster(srcSM, new Point(0,0));
                BufferedImage bi = new BufferedImage
                    (srcCM, wr, srcCM.isAlphaPremultiplied(), null);

                int xt0 = cr.getMinTileX();
                int xt1 = xt0+cr.getNumXTiles();
                int yt0 = cr.getMinTileY();
                int yt1 = yt0+cr.getNumYTiles();
                int tw  = srcSM.getWidth();
                int th  = srcSM.getHeight();

                Rectangle tR  = new Rectangle(0,0,tw,th);
                Rectangle iR  = new Rectangle(0,0,0,0);

                if (false) {
                    System.err.println("SrcCM: " + srcCM);
                    System.err.println("CR: " + cr);
                    System.err.println("CRR: " + crR + " TG: [" +
                                       xt0 + ',' +
                                       yt0 + ',' +
                                       xt1 + ',' +
                                       yt1 +"] Off: " +
                                       cr.getTileGridXOffset() + ',' +
                                       cr.getTileGridYOffset());
                }

                int yloc = yt0*th+cr.getTileGridYOffset();
                int skip = (clipR.y-yloc)/th;
                if (skip <0) skip = 0;
                yt0+=skip;

                int xloc = xt0*tw+cr.getTileGridXOffset();
                skip = (clipR.x-xloc)/tw;
                if (skip <0) skip = 0;
                xt0+=skip;

                int endX = clipR.x+clipR.width-1;
                int endY = clipR.y+clipR.height-1;

                if (false) {
                    System.out.println("clipR: " + clipR + " TG: [" +
                                       xt0 + ',' +
                                       yt0 + ',' +
                                       xt1 + ',' +
                                       yt1 +"] Off: " +
                                       cr.getTileGridXOffset() + ',' +
                                       cr.getTileGridYOffset());
                }


                yloc = yt0*th+cr.getTileGridYOffset();
                int minX = xt0*tw+cr.getTileGridXOffset();
                int xStep = tw;
                xloc = minX;
                for (int y=yt0; y<yt1; y++, yloc += th) {
                    if (yloc > endY) break;
                    for (int x=xt0; x<xt1; x++, xloc+=xStep) {
                        if ((xloc<minX) || (xloc > endX)) break;
                        tR.x = xloc;
                        tR.y = yloc;
                        Rectangle2D.intersect(crR, tR, iR);

                        WritableRaster twr;
                        twr = wr.createWritableChild(0, 0,
                                                     iR.width, iR.height,
                                                     iR.x, iR.y, null);

                        // System.out.println("Generating tile: " + twr);
                        cr.copyData(twr);

                        // Make sure we only draw the region that was written.
                        BufferedImage subBI;
                        subBI = bi.getSubimage(0, 0, iR.width,  iR.height);

                        if (false) {
                            System.out.println("Drawing: " + tR);
                            System.out.println("IR: "      + iR);
                        }

                        // For some reason using the transform version
                        // causes a gStackUnderflow error but if I just
                        // use the drawImage with an x & y it works.
                        g2d.drawImage(subBI, iR.x, iR.y, null);
                        // AffineTransform trans
                        //  = AffineTransform.getTranslateInstance(iR.x, iR.y);
                        // g2d.drawImage(subBI, trans, null);

                        // String label = "sub [" + x + ", " + y + "]: ";
                        // org.ImageDisplay.showImage
                        //     (label, subBI);
                    }
                    xStep = -xStep; // Reverse directions.
                    xloc += xStep;   // Get back in bounds.
                }
            }
            // long endTime = System.currentTimeMillis();
            // System.out.println("Time: " + (endTime-startTime));


        } finally {
            g2d.setTransform(g2dAt);
            g2d.setComposite(g2dComposite);
        }

        // System.out.println("Finished Draw");
    }


    /**
     * Draws a <tt>Filter</tt> (<tt>RenderableImage</tt>) into a
     * Graphics 2D after taking into account a particular
     * <tt>RenderContext</tt>.<p>
     *
     * This method also attempts to unwind the rendering chain a bit.
     * So it knows about certain operations (like affine, pad,
     * composite), rather than applying each of these operations in
     * turn it accounts for their affects through modifications to the
     * Graphics2D. This avoids generating lots of intermediate images.
     *
     * @param g2d    The Graphics to draw into.
     * @param filter The filter to draw
     * @param rc The render context that controls the drawing operation.
     */
    public static void drawImage(Graphics2D      g2d,
                                 RenderableImage filter,
                                 RenderContext   rc) {

        AffineTransform origDev  = g2d.getTransform();
        Shape           origClip = g2d.getClip();
        RenderingHints  origRH   = g2d.getRenderingHints();

        Shape clip = rc.getAreaOfInterest();
        if (clip != null)
            g2d.clip(clip);
        g2d.transform(rc.getTransform());
        g2d.setRenderingHints(rc.getRenderingHints());

        drawImage(g2d, filter);

        g2d.setTransform(origDev);
        g2d.setClip(origClip);
        g2d.setRenderingHints(origRH);
    }

    /**
     * Draws a <tt>Filter</tt> (<tt>RenderableImage</tt>) into a
     * Graphics 2D.<p>
     *
     * This method also attempts to unwind the rendering chain a bit.
     * So it knows about certain operations (like affine, pad,
     * composite), rather than applying each of these operations in
     * turn it accounts for their affects through modifications to the
     * Graphics2D.  This avoids generating lots of intermediate images.
     *
     * @param g2d    The Graphics to draw into.
     * @param filter The filter to draw
     */
    public static void drawImage(Graphics2D g2d,
                                 RenderableImage filter) {
        if (filter instanceof PaintRable) {
            PaintRable pr = (PaintRable)filter;
            if (pr.paintRable(g2d))
                // paintRable succeeded so we are done...
                return;
        }

        // Get our sources image...
        // System.out.println("UnOpt: " + filter);
        AffineTransform at = g2d.getTransform();
        RenderedImage ri = filter.createRendering
            (new RenderContext(at, g2d.getClip(), g2d.getRenderingHints()));

        if (ri == null)
            return;

        g2d.setTransform(IDENTITY);
        drawImage(g2d, GraphicsUtil.wrap(ri));
        g2d.setTransform(at);
    }

    /**
     * This is a wrapper around the system's
     * BufferedImage.createGraphics that arranges for bi to be stored
     * in a Rendering hint in the returned Graphics2D.
     * This allows for accurate determination of the 'devices' size,
     * and colorspace.
     * @param bi The BufferedImage that the returned Graphics should
     *           draw into.
     * @return A Graphics2D that draws into BufferedImage with <tt>bi</tt>
     *         stored in a rendering hint.
     */
    public static Graphics2D createGraphics(BufferedImage bi,
                                            RenderingHints hints) {
        Graphics2D g2d = bi.createGraphics();
        if (hints != null)
            g2d.addRenderingHints(hints);
        g2d.setRenderingHint(RenderingHintsKeyExt.KEY_BUFFERED_IMAGE,
                             new WeakReference(bi));
        g2d.clip(new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
        return g2d;
    }


    public static Graphics2D createGraphics(BufferedImage bi) {
        Graphics2D g2d = bi.createGraphics();
        g2d.setRenderingHint(RenderingHintsKeyExt.KEY_BUFFERED_IMAGE,
                             new WeakReference(bi));
        g2d.clip(new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
        return g2d;
    }


    public static final boolean WARN_DESTINATION;

    static {
        boolean warn = true;
        try {
            String s = System.getProperty
                ("org.apache.batik.warn_destination", "true");
            warn = Boolean.valueOf(s).booleanValue();
        } catch (SecurityException se) {
        } catch (NumberFormatException nfe) {
        } finally {
            WARN_DESTINATION = warn;
        }
    }

    public static BufferedImage getDestination(Graphics2D g2d) {
        Object o = g2d.getRenderingHint
            (RenderingHintsKeyExt.KEY_BUFFERED_IMAGE);
        if (o != null)
            return (BufferedImage)(((Reference)o).get());

        // Check if this is a BufferedImage G2d if so throw an error...
        GraphicsConfiguration gc = g2d.getDeviceConfiguration();
        if (gc == null) {
            return null;
        }

        GraphicsDevice gd = gc.getDevice();
        if (WARN_DESTINATION &&
            (gd.getType() == GraphicsDevice.TYPE_IMAGE_BUFFER) &&
            (g2d.getRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING) !=
                RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING))
            // throw new IllegalArgumentException
            System.err.println
                ("Graphics2D from BufferedImage lacks BUFFERED_IMAGE hint");

        return null;
    }

    public static ColorModel getDestinationColorModel(Graphics2D g2d) {
        BufferedImage bi = getDestination(g2d);
        if (bi != null) {
            return bi.getColorModel();
        }

        GraphicsConfiguration gc = g2d.getDeviceConfiguration();
        if (gc == null) {
            return null; // Can't tell
        }

        // We are going to a BufferedImage but no hint was provided
        // so we can't determine the destination Color Model.
        if (gc.getDevice().getType() == GraphicsDevice.TYPE_IMAGE_BUFFER) {
            if (g2d.getRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING) ==
                RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING)
                return sRGB_Unpre;

            // System.out.println("CM: " + gc.getColorModel());
            // System.out.println("CS: " + gc.getColorModel().getColorSpace());
            return null;
        }

        return gc.getColorModel();
    }

    public static ColorSpace getDestinationColorSpace(Graphics2D g2d) {
        ColorModel cm = getDestinationColorModel(g2d);
        if (cm != null) return cm.getColorSpace();

        return null;
    }

    public static Rectangle getDestinationBounds(Graphics2D g2d) {
        BufferedImage bi = getDestination(g2d);
        if (bi != null) {
            return new Rectangle(0, 0, bi.getWidth(), bi.getHeight());
        }

        GraphicsConfiguration gc = g2d.getDeviceConfiguration();
        if (gc == null) {
            return null;
        }

        // We are going to a BufferedImage but no hint was provided
        // so we can't determine the destination bounds.
        if (gc.getDevice().getType() == GraphicsDevice.TYPE_IMAGE_BUFFER) {
            return null;
        }

        // This is a JDK 1.3ism, so we will just return null...
        // return gc.getBounds();
        return null;
    }


    /**
     * Standard prebuilt Linear_sRGB color model with no alpha */
    public static final ColorModel Linear_sRGB =
        new DirectColorModel(ColorSpace.getInstance
                             (ColorSpace.CS_LINEAR_RGB), 24,
                             0x00FF0000, 0x0000FF00,
                             0x000000FF, 0x0, false,
                             DataBuffer.TYPE_INT);
    /**
     * Standard prebuilt Linear_sRGB color model with premultiplied alpha.
     */
    public static final ColorModel Linear_sRGB_Pre =
        new DirectColorModel(ColorSpace.getInstance
                             (ColorSpace.CS_LINEAR_RGB), 32,
                             0x00FF0000, 0x0000FF00,
                             0x000000FF, 0xFF000000, true,
                             DataBuffer.TYPE_INT);
    /**
     * Standard prebuilt Linear_sRGB color model with unpremultiplied alpha.
     */
    public static final ColorModel Linear_sRGB_Unpre =
        new DirectColorModel(ColorSpace.getInstance
                             (ColorSpace.CS_LINEAR_RGB), 32,
                             0x00FF0000, 0x0000FF00,
                             0x000000FF, 0xFF000000, false,
                             DataBuffer.TYPE_INT);

    /**
     * Standard prebuilt sRGB color model with no alpha.
     */
    public static final ColorModel sRGB =
        new DirectColorModel(ColorSpace.getInstance
                             (ColorSpace.CS_sRGB), 24,
                             0x00FF0000, 0x0000FF00,
                             0x000000FF, 0x0, false,
                             DataBuffer.TYPE_INT);
    /**
     * Standard prebuilt sRGB color model with premultiplied alpha.
     */
    public static final ColorModel sRGB_Pre =
        new DirectColorModel(ColorSpace.getInstance
                             (ColorSpace.CS_sRGB), 32,
                             0x00FF0000, 0x0000FF00,
                             0x000000FF, 0xFF000000, true,
                             DataBuffer.TYPE_INT);
    /**
     * Standard prebuilt sRGB color model with unpremultiplied alpha.
     */
    public static final ColorModel sRGB_Unpre =
        new DirectColorModel(ColorSpace.getInstance
                             (ColorSpace.CS_sRGB), 32,
                             0x00FF0000, 0x0000FF00,
                             0x000000FF, 0xFF000000, false,
                             DataBuffer.TYPE_INT);

    /**
     * Method that returns either Linear_sRGB_Pre or Linear_sRGB_UnPre
     * based on premult flag.
     * @param premult True if the ColorModel should have premultiplied alpha.
     * @return        a ColorMdoel with Linear sRGB colorSpace and
     *                the alpha channel set in accordance with
     *                <tt>premult</tt>
     */
    public static ColorModel makeLinear_sRGBCM( boolean premult ) {

         return premult ? Linear_sRGB_Pre : Linear_sRGB_Unpre;
    }

    /**
     * Constructs a BufferedImage with a linear sRGB colorModel, and alpha.
     * @param width   The desired width of the BufferedImage
     * @param height  The desired height of the BufferedImage
     * @param premult The desired state of alpha premultiplied
     * @return        The requested BufferedImage.
     */
    public static BufferedImage makeLinearBufferedImage(int width,
                                                        int height,
                                                        boolean premult) {
        ColorModel cm = makeLinear_sRGBCM(premult);
        WritableRaster wr = cm.createCompatibleWritableRaster(width, height);
        return new BufferedImage(cm, wr, premult, null);
    }

    /**
     * This method will return a CacheableRed that has it's data in
     * the linear sRGB colorspace. If <tt>src</tt> is already in
     * linear sRGB then this method does nothing and returns <tt>src</tt>.
     * Otherwise it creates a transform that will convert
     * <tt>src</tt>'s output to linear sRGB and returns that CacheableRed.
     *
     * @param src The image to convert to linear sRGB.
     * @return    An equivilant image to <tt>src</tt> who's data is in
     *            linear sRGB.
     */
    public static CachableRed convertToLsRGB(CachableRed src) {
        ColorModel cm = src.getColorModel();
        ColorSpace cs = cm.getColorSpace();
        if (cs == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB))
            return src;

        return new Any2LsRGBRed(src);
    }

    /**
     * This method will return a CacheableRed that has it's data in
     * the sRGB colorspace. If <tt>src</tt> is already in
     * sRGB then this method does nothing and returns <tt>src</tt>.
     * Otherwise it creates a transform that will convert
     * <tt>src</tt>'s output to sRGB and returns that CacheableRed.
     *
     * @param src The image to convert to sRGB.
     * @return    An equivilant image to <tt>src</tt> who's data is in sRGB.
     */
    public static CachableRed convertTosRGB(CachableRed src) {
        ColorModel cm = src.getColorModel();
        ColorSpace cs = cm.getColorSpace();
        if (cs == ColorSpace.getInstance(ColorSpace.CS_sRGB))
            return src;

        return new Any2sRGBRed(src);
    }

    /**
     * Convertes any RenderedImage to a CacheableRed.  <p>
     * If <tt>ri</tt> is already a CacheableRed it casts it down and
     * returns it.<p>
     *
     * In cases where <tt>ri</tt> is not already a CacheableRed it
     * wraps <tt>ri</tt> with a helper class.  The wrapped
     * CacheableRed "Pretends" that it has no sources since it has no
     * way of inteligently handling the dependency/dirty region calls
     * if it exposed the source.
     * @param ri The RenderedImage to convert.
     * @return   a CacheableRed that contains the same data as ri.
     */
    public static CachableRed wrap(RenderedImage ri) {
        if (ri instanceof CachableRed)
            return (CachableRed) ri;
        if (ri instanceof BufferedImage)
            return new BufferedImageCachableRed((BufferedImage)ri);
        return new RenderedImageCachableRed(ri);
    }

    /**
     * An internal optimized version of copyData designed to work on
     * Integer packed data with a SinglePixelPackedSampleModel.  Only
     * the region of overlap between src and dst is copied.
     *
     * Calls to this should be preflighted with is_INT_PACK_Data
     * on both src and dest (requireAlpha can be false).
     *
     * @param src The source of the data
     * @param dst The destination for the data.
     */
    public static void copyData_INT_PACK(Raster src, WritableRaster dst) {
        // System.out.println("Fast copyData");
        int x0 = dst.getMinX();
        if (x0 < src.getMinX()) x0 = src.getMinX();

        int y0 = dst.getMinY();
        if (y0 < src.getMinY()) y0 = src.getMinY();

        int x1 = dst.getMinX()+dst.getWidth()-1;
        if (x1 > src.getMinX()+src.getWidth()-1)
            x1 = src.getMinX()+src.getWidth()-1;

        int y1 = dst.getMinY()+dst.getHeight()-1;
        if (y1 > src.getMinY()+src.getHeight()-1)
            y1 = src.getMinY()+src.getHeight()-1;

        int width  = x1-x0+1;
        int height = y1-y0+1;

        SinglePixelPackedSampleModel srcSPPSM;
        srcSPPSM = (SinglePixelPackedSampleModel)src.getSampleModel();

        final int     srcScanStride = srcSPPSM.getScanlineStride();
        DataBufferInt srcDB         = (DataBufferInt)src.getDataBuffer();
        final int []  srcPixels     = srcDB.getBankData()[0];
        final int     srcBase =
            (srcDB.getOffset() +
             srcSPPSM.getOffset(x0-src.getSampleModelTranslateX(),
                                y0-src.getSampleModelTranslateY()));


        SinglePixelPackedSampleModel dstSPPSM;
        dstSPPSM = (SinglePixelPackedSampleModel)dst.getSampleModel();

        final int     dstScanStride = dstSPPSM.getScanlineStride();
        DataBufferInt dstDB         = (DataBufferInt)dst.getDataBuffer();
        final int []  dstPixels     = dstDB.getBankData()[0];
        final int     dstBase =
            (dstDB.getOffset() +
             dstSPPSM.getOffset(x0-dst.getSampleModelTranslateX(),
                                y0-dst.getSampleModelTranslateY()));

        if ((srcScanStride == dstScanStride) &&
            (srcScanStride == width)) {
            // System.out.println("VERY Fast copyData");

            System.arraycopy(srcPixels, srcBase, dstPixels, dstBase,
                             width*height);
        } else if (width > 128) {
            int srcSP = srcBase;
            int dstSP = dstBase;
            for (int y=0; y<height; y++) {
                System.arraycopy(srcPixels, srcSP, dstPixels, dstSP, width);
                srcSP += srcScanStride;
                dstSP += dstScanStride;
            }
        } else {
            for (int y=0; y<height; y++) {
                int srcSP = srcBase+y*srcScanStride;
                int dstSP = dstBase+y*dstScanStride;
                for (int x=0; x<width; x++)
                    dstPixels[dstSP++] = srcPixels[srcSP++];
            }
        }
    }

    public static void copyData_FALLBACK(Raster src, WritableRaster dst) {
        // System.out.println("Fallback copyData");

        int x0 = dst.getMinX();
        if (x0 < src.getMinX()) x0 = src.getMinX();

        int y0 = dst.getMinY();
        if (y0 < src.getMinY()) y0 = src.getMinY();

        int x1 = dst.getMinX()+dst.getWidth()-1;
        if (x1 > src.getMinX()+src.getWidth()-1)
            x1 = src.getMinX()+src.getWidth()-1;

        int y1 = dst.getMinY()+dst.getHeight()-1;
        if (y1 > src.getMinY()+src.getHeight()-1)
            y1 = src.getMinY()+src.getHeight()-1;

        int width  = x1-x0+1;
        int [] data = null;

        for (int y = y0; y <= y1 ; y++)  {
            data = src.getPixels(x0,y,width,1,data);
            dst.setPixels       (x0,y,width,1,data);
        }
    }

    /**
     * Copies data from one raster to another. Only the region of
     * overlap between src and dst is copied.  <tt>Src</tt> and
     * <tt>Dst</tt> must have compatible SampleModels.
     *
     * @param src The source of the data
     * @param dst The destination for the data.
     */
    public static void copyData(Raster src, WritableRaster dst) {
        if (is_INT_PACK_Data(src.getSampleModel(), false) &&
            is_INT_PACK_Data(dst.getSampleModel(), false)) {
            copyData_INT_PACK(src, dst);
            return;
        }

        copyData_FALLBACK(src, dst);
    }

    /**
     * Creates a new raster that has a <b>copy</b> of the data in
     * <tt>ras</tt>.  This is highly optimized for speed.  There is
     * no provision for changing any aspect of the SampleModel.
     *
     * This method should be used when you need to change the contents
     * of a Raster that you do not "own" (ie the result of a
     * <tt>getData</tt> call).
     * @param ras The Raster to copy.
     * @return    A writable copy of <tt>ras</tt>
     */
    public static WritableRaster copyRaster(Raster ras) {
        return copyRaster(ras, ras.getMinX(), ras.getMinY());
    }


    /**
     * Creates a new raster that has a <b>copy</b> of the data in
     * <tt>ras</tt>.  This is highly optimized for speed.  There is
     * no provision for changing any aspect of the SampleModel.
     * However you can specify a new location for the returned raster.
     *
     * This method should be used when you need to change the contents
     * of a Raster that you do not "own" (ie the result of a
     * <tt>getData</tt> call).
     *
     * @param ras The Raster to copy.
     *
     * @param minX The x location for the upper left corner of the
     *             returned WritableRaster.
     *
     * @param minY The y location for the upper left corner of the
     *             returned WritableRaster.
     *
     * @return    A writable copy of <tt>ras</tt>
     */
    public static WritableRaster copyRaster(Raster ras, int minX, int minY) {
        WritableRaster ret = Raster.createWritableRaster
            (ras.getSampleModel(),
             new Point(0,0));
        ret = ret.createWritableChild
            (ras.getMinX()-ras.getSampleModelTranslateX(),
             ras.getMinY()-ras.getSampleModelTranslateY(),
             ras.getWidth(), ras.getHeight(),
             minX, minY, null);

        // Use System.arraycopy to copy the data between the two...
        DataBuffer srcDB = ras.getDataBuffer();
        DataBuffer retDB = ret.getDataBuffer();
        if (srcDB.getDataType() != retDB.getDataType()) {
            throw new IllegalArgumentException
                ("New DataBuffer doesn't match original");
        }
        int len   = srcDB.getSize();
        int banks = srcDB.getNumBanks();
        int [] offsets = srcDB.getOffsets();
        for (int b=0; b< banks; b++) {
            switch (srcDB.getDataType()) {
            case DataBuffer.TYPE_BYTE: {
                DataBufferByte srcDBT = (DataBufferByte)srcDB;
                DataBufferByte retDBT = (DataBufferByte)retDB;
                System.arraycopy(srcDBT.getData(b), offsets[b],
                                 retDBT.getData(b), offsets[b], len);
                break;
            }
            case DataBuffer.TYPE_INT: {
                DataBufferInt srcDBT = (DataBufferInt)srcDB;
                DataBufferInt retDBT = (DataBufferInt)retDB;
                System.arraycopy(srcDBT.getData(b), offsets[b],
                                 retDBT.getData(b), offsets[b], len);
                break;
            }
            case DataBuffer.TYPE_SHORT: {
                DataBufferShort srcDBT = (DataBufferShort)srcDB;
                DataBufferShort retDBT = (DataBufferShort)retDB;
                System.arraycopy(srcDBT.getData(b), offsets[b],
                                 retDBT.getData(b), offsets[b], len);
                break;
            }
            case DataBuffer.TYPE_USHORT: {
                DataBufferUShort srcDBT = (DataBufferUShort)srcDB;
                DataBufferUShort retDBT = (DataBufferUShort)retDB;
                System.arraycopy(srcDBT.getData(b), offsets[b],
                                 retDBT.getData(b), offsets[b], len);
                break;
            }
            }
        }

        return ret;
    }

    /**
     * Coerces <tt>ras</tt> to be writable.  The returned Raster continues to
     * reference the DataBuffer from ras, so modifications to the returned
     * WritableRaster will be seen in ras.<p>
     *
     * This method should only be used if you need a WritableRaster due to
     * an interface (such as to construct a BufferedImage), but have no
     * intention of modifying the contents of the returned Raster.  If
     * you have any doubt about other users of the data in <tt>ras</tt>,
     * use copyRaster (above).
     * @param ras The raster to make writable.
     * @return    A Writable version of ras (shares DataBuffer with
     *            <tt>ras</tt>).
     */
    public static WritableRaster makeRasterWritable(Raster ras) {
        return makeRasterWritable(ras, ras.getMinX(), ras.getMinY());
    }

    /**
     * Coerces <tt>ras</tt> to be writable.  The returned Raster continues to
     * reference the DataBuffer from ras, so modifications to the returned
     * WritableRaster will be seen in ras.<p>
     *
     * You can specify a new location for the returned WritableRaster, this
     * is especially useful for constructing BufferedImages which require
     * the Raster to be at (0,0).
     *
     * This method should only be used if you need a WritableRaster due to
     * an interface (such as to construct a BufferedImage), but have no
     * intention of modifying the contents of the returned Raster.  If
     * you have any doubt about other users of the data in <tt>ras</tt>,
     * use copyRaster (above).
     *
     * @param ras The raster to make writable.
     *
     * @param minX The x location for the upper left corner of the
     *             returned WritableRaster.
     *
     * @param minY The y location for the upper left corner of the
     *             returned WritableRaster.
     *
     * @return A Writable version of <tT>ras</tt> with it's upper left
     *         hand coordinate set to minX, minY (shares it's DataBuffer
     *         with <tt>ras</tt>).
     */
    public static WritableRaster makeRasterWritable(Raster ras,
                                                    int minX, int minY) {
        WritableRaster ret = Raster.createWritableRaster
            (ras.getSampleModel(),
             ras.getDataBuffer(),
             new Point(0,0));
        ret = ret.createWritableChild
            (ras.getMinX()-ras.getSampleModelTranslateX(),
             ras.getMinY()-ras.getSampleModelTranslateY(),
             ras.getWidth(), ras.getHeight(),
             minX, minY, null);
        return ret;
    }

    /**
     * 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() )
            // 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());

        if (newAlphaPreMult) {
            multiplyAlpha(wr);
        } else {
            divideAlpha(wr);
        }

        return coerceColorModel(cm, newAlphaPreMult);
    }

    public static void multiplyAlpha(WritableRaster wr) {
        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 {
            int [] pixel = null;
            int    bands = wr.getNumBands();
            float  norm = 1.0f/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<y1; y++)
                for (int x=x0; x<x1; x++) {
                    pixel = wr.getPixel(x,y,pixel);
                    a = pixel[bands-1];
                    if ((a >= 0) && (a < 255)) {
                        alpha = a*norm;
                        for (b=0; b<bands-1; b++)
                            pixel[b] = (int)(pixel[b]*alpha+0.5f);
                        wr.setPixel(x,y,pixel);
                    }
                }
        }
    }

    public static void divideAlpha(WritableRaster wr) {
        if (is_BYTE_COMP_Data(wr.getSampleModel()))
            divide_BYTE_COMP_Data(wr);
        else if (is_INT_PACK_Data(wr.getSampleModel(), true))
            divide_INT_PACK_Data(wr);
        else {
            int x0, x1, y0, y1, a, b;
            float ialpha;
            int    bands = wr.getNumBands();
            int [] pixel = null;

            x0 = wr.getMinX();
            x1 = x0+wr.getWidth();
            y0 = wr.getMinY();
            y1 = y0+wr.getHeight();
            for (int y=y0; y<y1; y++)
                for (int x=x0; x<x1; x++) {
                    pixel = wr.getPixel(x,y,pixel);
                    a = pixel[bands-1];
                    if ((a > 0) && (a < 255)) {
                        ialpha = 255/(float)a;
                        for (b=0; b<bands-1; b++)
                            pixel[b] = (int)(pixel[b]*ialpha+0.5f);
                        wr.setPixel(x,y,pixel);
                    }
                }
        }
    }

    /**
     * Copies data from one bufferedImage to another paying attention
     * to the state of AlphaPreMultiplied.
     *
     * @param src The source
     * @param dst The destination
     */
    public static void
        copyData(BufferedImage src, BufferedImage dst) {
        Rectangle srcRect = new Rectangle(0, 0,
                                          src.getWidth(), src.getHeight());
        copyData(src, srcRect, dst, new Point(0,0));
    }


    /**
     * Copies data from one bufferedImage to another paying attention
     * to the state of AlphaPreMultiplied.
     *
     * @param src The source
     * @param srcRect The Rectangle of source data to be copied
     * @param dst The destination
     * @param destP The Place for the upper left corner of srcRect in dst.
     */
    public static void
        copyData(BufferedImage src, Rectangle srcRect,
                 BufferedImage dst, Point destP) {

       /*
        if (srcCS != dstCS)
            throw new IllegalArgumentException
                ("Images must be in the same ColorSpace in order "+
                 "to copy Data between them");
        */
        boolean srcAlpha = src.getColorModel().hasAlpha();
        boolean dstAlpha = dst.getColorModel().hasAlpha();

        // System.out.println("Src has: " + srcAlpha +
        //                    " is: " + src.isAlphaPremultiplied());
        //
        // System.out.println("Dst has: " + dstAlpha +
        //                    " is: " + dst.isAlphaPremultiplied());

        if (srcAlpha == dstAlpha)
            if (( ! srcAlpha ) ||
                (src.isAlphaPremultiplied() == dst.isAlphaPremultiplied())) {
                // They match one another so just copy everything...
                copyData(src.getRaster(), dst.getRaster());
                return;
            }

        // System.out.println("Using Slow CopyData");

        int [] pixel = null;
        Raster         srcR  = src.getRaster();
        WritableRaster dstR  = dst.getRaster();
        int            bands = dstR.getNumBands();

        int dx = destP.x-srcRect.x;
        int dy = destP.y-srcRect.y;

        int w  = srcRect.width;
        int x0 = srcRect.x;
        int y0 = srcRect.y;
        int y1 = y0+srcRect.height-1;

        if (!srcAlpha) {
            // Src has no alpha dest does so set alpha to 1.0 everywhere.
            // System.out.println("Add Alpha");
            int [] oPix = new int[bands*w];
            int out = (w*bands)-1; // The 2 skips alpha channel
            while(out >= 0) {
                // Fill alpha channel with 255's
                oPix[out] = 255;
                out -= bands;
            }

            int b, in;
            for (int y=y0; y<=y1; y++) {
                pixel = srcR.getPixels(x0,y,w,1,pixel);
                in  = w*(bands-1)-1;
                out = (w*bands)-2; // The 2 skips alpha channel on last pix
                switch (bands) {
                case 4:
                    while(in >= 0) {
                        oPix[out--] = pixel[in--];
                        oPix[out--] = pixel[in--];
                        oPix[out--] = pixel[in--];
                        out--;
                    }
                    break;
                default:
                    while(in >= 0) {
                        for (b=0; b<bands-1; b++)
                            oPix[out--] = pixel[in--];
                        out--;
                    }
                }
                dstR.setPixels(x0+dx, y+dy, w, 1, oPix);
            }
        } else if (dstAlpha && dst.isAlphaPremultiplied()) {
            // Src and dest have Alpha but we need to multiply it for dst.
            // System.out.println("Mult Case");
            int a, b, alpha, in, fpNorm = (1<<24)/255, pt5 = 1<<23;
            for (int y=y0; y<=y1; y++) {
                pixel = srcR.getPixels(x0,y,w,1,pixel);
                in=bands*w-1;
                switch (bands) {
                case 4:
                    while(in >= 0) {
                        a = pixel[in];
                        if (a == 255)
                            in -= 4;
                        else {
                            in--;
                            alpha = fpNorm*a;
                            pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--;
                            pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--;
                            pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--;
                        }
                    }
                    break;
                default:
                    while(in >= 0) {
                        a = pixel[in];
                        if (a == 255)
                            in -= bands;
                        else {
                            in--;
                            alpha = fpNorm*a;
                            for (b=0; b<bands-1; b++) {
                                pixel[in] = (pixel[in]*alpha+pt5)>>>24;
                                in--;
                            }
                        }
                    }
                }
                dstR.setPixels(x0+dx, y+dy, w, 1, pixel);
            }
        } else if (dstAlpha && !dst.isAlphaPremultiplied()) {
            // Src and dest have Alpha but we need to divide it out for dst.
            // System.out.println("Div Case");
            int a, b, ialpha, in, fpNorm = 0x00FF0000, pt5 = 1<<15;
            for (int y=y0; y<=y1; y++) {
                pixel = srcR.getPixels(x0,y,w,1,pixel);
                in=(bands*w)-1;
                switch(bands) {
                case 4:
                    while(in >= 0) {
                        a = pixel[in];
                        if ((a <= 0) || (a >= 255))
                            in -= 4;
                        else {
                            in--;
                            ialpha = fpNorm/a;
                            pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--;
                            pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--;
                            pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--;
                        }
                    }
                    break;
                default:
                    while(in >= 0) {
                        a = pixel[in];
                        if ((a <= 0) || (a >= 255))
                            in -= bands;
                        else {
                            in--;
                            ialpha = fpNorm/a;
                            for (b=0; b<bands-1; b++) {
                                pixel[in] = (pixel[in]*ialpha+pt5)>>>16;
                                in--;
                            }
                        }
                    }
                }
                dstR.setPixels(x0+dx, y+dy, w, 1, pixel);
            }
        } else if (src.isAlphaPremultiplied()) {
            int [] oPix = new int[bands*w];
            // Src has alpha dest does not so unpremult and store...
            // System.out.println("Remove Alpha, Div Case");
            int a, b, ialpha, in, out, fpNorm = 0x00FF0000, pt5 = 1<<15;
            for (int y=y0; y<=y1; y++) {
                pixel = srcR.getPixels(x0,y,w,1,pixel);
                in  = (bands+1)*w -1;
                out = (bands*w)-1;
                while(in >= 0) {
                    a = pixel[in]; in--;
                    if (a > 0) {
                        if (a < 255) {
                            ialpha = fpNorm/a;
                            for (b=0; b<bands; b++)
                                oPix[out--] = (pixel[in--]*ialpha+pt5)>>>16;
                        } else
                            for (b=0; b<bands; b++)
                                oPix[out--] = pixel[in--];
                    } else {
                        in -= bands;
                        for (b=0; b<bands; b++)
                            oPix[out--] = 255;
                    }
                }
                dstR.setPixels(x0+dx, y+dy, w, 1, oPix);
            }
        } else {
            // Src has unpremult alpha, dest does not have alpha,
            // just copy the color channels over.
            Rectangle dstRect = new Rectangle(destP.x, destP.y,
                                              srcRect.width, srcRect.height);
            for (int b=0; b<bands; b++)
                copyBand(srcR, srcRect, b,
                         dstR, dstRect, b);
        }
    }

    public static void copyBand(Raster         src, int srcBand,
                                WritableRaster dst, int dstBand) {

        Rectangle sR   = src.getBounds();
        Rectangle dR   = dst.getBounds();
        Rectangle cpR  = sR.intersection(dR);

        copyBand(src, cpR, srcBand, dst, cpR, dstBand);
    }

    public static void copyBand(Raster         src, Rectangle sR, int sBand,
                                WritableRaster dst, Rectangle dR, int dBand) {
        int dy = dR.y -sR.y;
        int dx = dR.x -sR.x;
        sR = sR.intersection(src.getBounds());
        dR = dR.intersection(dst.getBounds());
        int width, height;
        if (dR.width  < sR.width)  width  = dR.width;
        else                       width  = sR.width;
        if (dR.height < sR.height) height = dR.height;
        else                       height = sR.height;

        int x = sR.x+dx;
        int [] samples = null;
        for (int y=sR.y; y< sR.y+height; y++) {
            samples = src.getSamples(sR.x, y, width, 1, sBand, samples);
            dst.setSamples(x, y+dy, width, 1, dBand, samples);
        }
    }

    public static boolean is_INT_PACK_Data(SampleModel sm,
                                           boolean requireAlpha) {
        // Check ColorModel is of type DirectColorModel
        if(!(sm instanceof SinglePixelPackedSampleModel)) return false;

        // Check transfer type
        if(sm.getDataType() != DataBuffer.TYPE_INT)       return false;

        SinglePixelPackedSampleModel sppsm;
        sppsm = (SinglePixelPackedSampleModel)sm;

        int [] masks = sppsm.getBitMasks();
        if (masks.length == 3) {
            if (requireAlpha) return false;
        } else if (masks.length != 4)
            return false;

        if(masks[0] != 0x00ff0000) return false;
        if(masks[1] != 0x0000ff00) return false;
        if(masks[2] != 0x000000ff) return false;
        if ((masks.length == 4) &&
            (masks[3] != 0xff000000)) return false;

        return true;
    }

        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 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()));

        // Access the pixel data array
        final int[] pixels = db.getBankData()[0];
        for (int y=0; y<wr.getHeight(); y++) {
            int sp = base + y*scanStride;
            final int end = sp + width;
            while (sp < end) {
                int pixel = pixels[sp];
                int a = pixel>>>24;
                if (a<=0) {
                    pixels[sp] = 0x00FFFFFF;
                } else if (a<255) {
                    int aFP = (0x00FF0000/a);
                    pixels[sp] =
                        ((a << 24) |
                         (((((pixel&0xFF0000)>>16)*aFP)&0xFF0000)    ) |
                         (((((pixel&0x00FF00)>>8) *aFP)&0xFF0000)>>8 ) |
                         (((((pixel&0x0000FF))    *aFP)&0xFF0000)>>16));
                }
                sp++;
            }
        }
    }

    protected static void mult_INT_PACK_Data(WritableRaster wr) {
        // System.out.println("Multiply Int: " + wr);

        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()));
        // Access the pixel data array
        final int[] pixels = db.getBankData()[0];
        for (int y=0; y<wr.getHeight(); y++) {
            int sp = base + y*scanStride;
            final int end = sp + width;
            while (sp < end) {
                int pixel = pixels[sp];
                int a = pixel>>>24;
                if ((a>=0) && (a<255)) {   // this does NOT include a == 255 (0xff) !
                    pixels[sp] = ((a << 24) |
                                  ((((pixel&0xFF0000)*a)>>8)&0xFF0000) |
                                  ((((pixel&0x00FF00)*a)>>8)&0x00FF00) |
                                  ((((pixel&0x0000FF)*a)>>8)&0x0000FF));
                }
                sp++;
            }
        }
    }


    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 aOff = bandOff[bandOff.length-1];
        int bands = bandOff.length-1;

        // Access the pixel data array
        final byte[] pixels = db.getBankData()[0];
        for (int y=0; y<wr.getHeight(); y++) {
            int sp = base + y*scanStride;
            final int end = sp + width*pixStride;
            while (sp < end) {
              int a = pixels[sp+aOff]&0xFF;
              if (a==0) {
                for ( int b=0; b<bands; b++)
                  pixels[sp+bandOff[b]] = (byte)0xFF;
              } else if (a<255) {         // this does NOT include a == 255 (0xff) !
                int aFP = (0x00FF0000/a);
                for ( int b=0; b<bands; b++) {
                  int i = sp+bandOff[b];
                  pixels[i] = (byte)(((pixels[i]&0xFF)*aFP)>>>16);
                }
              }
              sp+=pixStride;
            }
        }
    }

    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 aOff = bandOff[bandOff.length-1];
        int bands = bandOff.length-1;

        // Access the pixel data array
        final byte[] pixels = db.getBankData()[0];
        for (int y=0; y<wr.getHeight(); y++) {
            int sp = base + y*scanStride;
            final int end = sp + width*pixStride;
            while (sp < end) {
              int a = pixels[sp+aOff]&0xFF;
              if (a!=0xFF)
                for ( int b=0; b<bands; b++) {
                  int i = sp+bandOff[b];
                  pixels[i] = (byte)(((pixels[i]&0xFF)*a)>>8);
                }
              sp+=pixStride;
            }
        }
    }

/*
  This is skanky debugging code that might be useful in the future:

            if (count == 33) {
                String label = "sub [" + x + ", " + y + "]: ";
                org.ImageDisplay.showImage
                    (label, subBI);
                org.ImageDisplay.printImage
                    (label, subBI,
                     new Rectangle(75-iR.x, 90-iR.y, 32, 32));

            }


            // if ((count++ % 50) == 10)
            //     org.ImageDisplay.showImage("foo: ", subBI);


            Graphics2D realG2D = g2d;
            while (realG2D instanceof sun.java2d.ProxyGraphics2D) {
                realG2D = ((sun.java2d.ProxyGraphics2D)realG2D).getDelegate();
            }
            if (realG2D instanceof sun.awt.image.BufferedImageGraphics2D) {
                count++;
                if (count == 34) {
                    RenderedImage ri;
                    ri = ((sun.awt.image.BufferedImageGraphics2D)realG2D).bufImg;
                    // g2d.setComposite(SVGComposite.OVER);
                    // org.ImageDisplay.showImage("Bar: " + count, cr);
                    org.ImageDisplay.printImage("Bar: " + count, cr,
                                                new Rectangle(75, 90, 32, 32));

                    org.ImageDisplay.showImage ("Foo: " + count, ri);
                    org.ImageDisplay.printImage("Foo: " + count, ri,
                                                new Rectangle(75, 90, 32, 32));

                    System.out.println("BI: "   + ri);
                    System.out.println("BISM: " + ri.getSampleModel());
                    System.out.println("BICM: " + ri.getColorModel());
                    System.out.println("BICM class: " + ri.getColorModel().getClass());
                    System.out.println("BICS: " + ri.getColorModel().getColorSpace());
                    System.out.println
                        ("sRGB CS: " +
                         ColorSpace.getInstance(ColorSpace.CS_sRGB));
                    System.out.println("G2D info");
                    System.out.println("\tComposite: " + g2d.getComposite());
                    System.out.println("\tTransform" + g2d.getTransform());
                    java.awt.RenderingHints rh = g2d.getRenderingHints();
                    java.util.Set keys = rh.keySet();
                    java.util.Iterator iter = keys.iterator();
                    while (iter.hasNext()) {
                        Object o = iter.next();

                        System.out.println("\t" + o.toString() + " -> " +
                                           rh.get(o).toString());
                    }

                    ri = cr;
                    System.out.println("RI: "   + ri);
                    System.out.println("RISM: " + ri.getSampleModel());
                    System.out.println("RICM: " + ri.getColorModel());
                    System.out.println("RICM class: " + ri.getColorModel().getClass());
                    System.out.println("RICS: " + ri.getColorModel().getColorSpace());
                }
            }
*/

}
