/*
 * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.imageio;

import java.awt.Point;
import java.awt.Transparency;
import java.awt.image.BandedSampleModel;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.color.ColorSpace;
import java.awt.image.IndexColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DirectColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.util.Hashtable;

/**
 * A class that allows the format of an image (in particular, its
 * <code>SampleModel</code> and <code>ColorModel</code>) to be
 * specified in a convenient manner.
 *
 */
public class ImageTypeSpecifier {

    /**
     * The <code>ColorModel</code> to be used as a prototype.
     */
    protected ColorModel colorModel;

    /**
     * A <code>SampleModel</code> to be used as a prototype.
     */
    protected SampleModel sampleModel;

    /**
     * Cached specifiers for all of the standard
     * <code>BufferedImage</code> types.
     */
    private static ImageTypeSpecifier[] BISpecifier;

    // Initialize the standard specifiers
    static {
        ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);

        BISpecifier =
            new ImageTypeSpecifier[BufferedImage.TYPE_BYTE_INDEXED + 1];

        BISpecifier[BufferedImage.TYPE_CUSTOM] = null;

        BISpecifier[BufferedImage.TYPE_INT_RGB] =
            createPacked(sRGB,
                         0x00ff0000,
                         0x0000ff00,
                         0x000000ff,
                         0x0,
                         DataBuffer.TYPE_INT,
                         false);

        BISpecifier[BufferedImage.TYPE_INT_ARGB] =
            createPacked(sRGB,
                         0x00ff0000,
                         0x0000ff00,
                         0x000000ff,
                         0xff000000,
                         DataBuffer.TYPE_INT,
                         false);

        BISpecifier[BufferedImage.TYPE_INT_ARGB_PRE] =
            createPacked(sRGB,
                         0x00ff0000,
                         0x0000ff00,
                         0x000000ff,
                         0xff000000,
                         DataBuffer.TYPE_INT,
                         true);

        BISpecifier[BufferedImage.TYPE_INT_BGR] =
            createPacked(sRGB,
                         0x000000ff,
                         0x0000ff00,
                         0x00ff0000,
                         0x0,
                         DataBuffer.TYPE_INT,
                         false);

        int[] bOffsRGB = { 2, 1, 0 };
        BISpecifier[BufferedImage.TYPE_3BYTE_BGR] =
            createInterleaved(sRGB,
                              bOffsRGB,
                              DataBuffer.TYPE_BYTE,
                              false,
                              false);

        int[] bOffsABGR = { 3, 2, 1, 0 };
        BISpecifier[BufferedImage.TYPE_4BYTE_ABGR] =
            createInterleaved(sRGB,
                              bOffsABGR,
                              DataBuffer.TYPE_BYTE,
                              true,
                              false);

        BISpecifier[BufferedImage.TYPE_4BYTE_ABGR_PRE] =
            createInterleaved(sRGB,
                              bOffsABGR,
                              DataBuffer.TYPE_BYTE,
                              true,
                              true);

        BISpecifier[BufferedImage.TYPE_USHORT_565_RGB] =
            createPacked(sRGB,
                         0xF800,
                         0x07E0,
                         0x001F,
                         0x0,
                         DataBuffer.TYPE_USHORT,
                         false);

        BISpecifier[BufferedImage.TYPE_USHORT_555_RGB] =
            createPacked(sRGB,
                         0x7C00,
                         0x03E0,
                         0x001F,
                         0x0,
                         DataBuffer.TYPE_USHORT,
                         false);

        BISpecifier[BufferedImage.TYPE_BYTE_GRAY] =
            createGrayscale(8,
                            DataBuffer.TYPE_BYTE,
                            false);

        BISpecifier[BufferedImage.TYPE_USHORT_GRAY] =
            createGrayscale(16,
                            DataBuffer.TYPE_USHORT,
                            false);

        BISpecifier[BufferedImage.TYPE_BYTE_BINARY] =
            createGrayscale(1,
                            DataBuffer.TYPE_BYTE,
                            false);

        BufferedImage bi =
            new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
        IndexColorModel icm = (IndexColorModel)bi.getColorModel();
        int mapSize = icm.getMapSize();
        byte[] redLUT = new byte[mapSize];
        byte[] greenLUT = new byte[mapSize];
        byte[] blueLUT = new byte[mapSize];
        byte[] alphaLUT = new byte[mapSize];

        icm.getReds(redLUT);
        icm.getGreens(greenLUT);
        icm.getBlues(blueLUT);
        icm.getAlphas(alphaLUT);

        BISpecifier[BufferedImage.TYPE_BYTE_INDEXED] =
            createIndexed(redLUT, greenLUT, blueLUT, alphaLUT,
                          8,
                          DataBuffer.TYPE_BYTE);
    }

    /**
     * A constructor to be used by inner subclasses only.
     */
    private ImageTypeSpecifier() {}

    /**
     * Constructs an <code>ImageTypeSpecifier</code> directly
     * from a <code>ColorModel</code> and a <code>SampleModel</code>.
     * It is the caller's responsibility to supply compatible
     * parameters.
     *
     * @param colorModel a <code>ColorModel</code>.
     * @param sampleModel a <code>SampleModel</code>.
     *
     * @exception IllegalArgumentException if either parameter is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>sampleModel</code>
     * is not compatible with <code>colorModel</code>.
     */
    public ImageTypeSpecifier(ColorModel colorModel, SampleModel sampleModel) {
        if (colorModel == null) {
            throw new IllegalArgumentException("colorModel == null!");
        }
        if (sampleModel == null) {
            throw new IllegalArgumentException("sampleModel == null!");
        }
        if (!colorModel.isCompatibleSampleModel(sampleModel)) {
            throw new IllegalArgumentException
                ("sampleModel is incompatible with colorModel!");
        }
        this.colorModel = colorModel;
        this.sampleModel = sampleModel;
    }

    /**
     * Constructs an <code>ImageTypeSpecifier</code> from a
     * <code>RenderedImage</code>.  If a <code>BufferedImage</code> is
     * being used, one of the factory methods
     * <code>createFromRenderedImage</code> or
     * <code>createFromBufferedImageType</code> should be used instead in
     * order to get a more accurate result.
     *
     * @param image a <code>RenderedImage</code>.
     *
     * @exception IllegalArgumentException if the argument is
     * <code>null</code>.
     */
    public ImageTypeSpecifier(RenderedImage image) {
        if (image == null) {
            throw new IllegalArgumentException("image == null!");
        }
        colorModel = image.getColorModel();
        sampleModel = image.getSampleModel();
    }

    // Packed

    static class Packed extends ImageTypeSpecifier {
        ColorSpace colorSpace;
        int redMask;
        int greenMask;
        int blueMask;
        int alphaMask;
        int transferType;
        boolean isAlphaPremultiplied;

        public Packed(ColorSpace colorSpace,
                      int redMask,
                      int greenMask,
                      int blueMask,
                      int alphaMask, // 0 if no alpha
                      int transferType,
                      boolean isAlphaPremultiplied) {
            if (colorSpace == null) {
                throw new IllegalArgumentException("colorSpace == null!");
            }
            if (colorSpace.getType() != ColorSpace.TYPE_RGB) {
                throw new IllegalArgumentException
                    ("colorSpace is not of type TYPE_RGB!");
            }
            if (transferType != DataBuffer.TYPE_BYTE &&
                transferType != DataBuffer.TYPE_USHORT &&
                transferType != DataBuffer.TYPE_INT) {
                throw new IllegalArgumentException
                    ("Bad value for transferType!");
            }
            if (redMask == 0 && greenMask == 0 &&
                blueMask == 0 && alphaMask == 0) {
                throw new IllegalArgumentException
                    ("No mask has at least 1 bit set!");
            }
            this.colorSpace = colorSpace;
            this.redMask = redMask;
            this.greenMask = greenMask;
            this.blueMask = blueMask;
            this.alphaMask = alphaMask;
            this.transferType = transferType;
            this.isAlphaPremultiplied = isAlphaPremultiplied;

            int bits = 32;
            this.colorModel =
                new DirectColorModel(colorSpace,
                                     bits,
                                     redMask, greenMask, blueMask,
                                     alphaMask, isAlphaPremultiplied,
                                     transferType);
            this.sampleModel = colorModel.createCompatibleSampleModel(1, 1);
        }
    }

    /**
     * Returns a specifier for a packed image format that will use a
     * <code>DirectColorModel</code> and a packed
     * <code>SampleModel</code> to store each pixel packed into in a
     * single byte, short, or int.
     *
     * @param colorSpace the desired <code>ColorSpace</code>.
     * @param redMask a contiguous mask indicated the position of the
     * red channel.
     * @param greenMask a contiguous mask indicated the position of the
     * green channel.
     * @param blueMask a contiguous mask indicated the position of the
     * blue channel.
     * @param alphaMask a contiguous mask indicated the position of the
     * alpha channel.
     * @param transferType the desired <code>SampleModel</code> transfer type.
     * @param isAlphaPremultiplied <code>true</code> if the color channels
     * will be premultipled by the alpha channel.
     *
     * @return an <code>ImageTypeSpecifier</code> with the desired
     * characteristics.
     *
     * @exception IllegalArgumentException if <code>colorSpace</code>
     * is <code>null</code>.
     * @exception IllegalArgumentException if <code>colorSpace</code>
     * is not of type <code>TYPE_RGB</code>.
     * @exception IllegalArgumentException if no mask has at least 1
     * bit set.
     * @exception IllegalArgumentException if
     * <code>transferType</code> if not one of
     * <code>DataBuffer.TYPE_BYTE</code>,
     * <code>DataBuffer.TYPE_USHORT</code>, or
     * <code>DataBuffer.TYPE_INT</code>.
     */
    public static ImageTypeSpecifier
        createPacked(ColorSpace colorSpace,
                     int redMask,
                     int greenMask,
                     int blueMask,
                     int alphaMask, // 0 if no alpha
                     int transferType,
                     boolean isAlphaPremultiplied) {
        return new ImageTypeSpecifier.Packed(colorSpace,
                                             redMask,
                                             greenMask,
                                             blueMask,
                                             alphaMask, // 0 if no alpha
                                             transferType,
                                             isAlphaPremultiplied);
    }

    static ColorModel createComponentCM(ColorSpace colorSpace,
                                        int numBands,
                                        int dataType,
                                        boolean hasAlpha,
                                        boolean isAlphaPremultiplied) {
        int transparency =
            hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;

        int[] numBits = new int[numBands];
        int bits = DataBuffer.getDataTypeSize(dataType);

        for (int i = 0; i < numBands; i++) {
            numBits[i] = bits;
        }

        return new ComponentColorModel(colorSpace,
                                       numBits,
                                       hasAlpha,
                                       isAlphaPremultiplied,
                                       transparency,
                                       dataType);
    }

    // Interleaved

    static class Interleaved extends ImageTypeSpecifier {
        ColorSpace colorSpace;
        int[] bandOffsets;
        int dataType;
        boolean hasAlpha;
        boolean isAlphaPremultiplied;

        public Interleaved(ColorSpace colorSpace,
                           int[] bandOffsets,
                           int dataType,
                           boolean hasAlpha,
                           boolean isAlphaPremultiplied) {
            if (colorSpace == null) {
                throw new IllegalArgumentException("colorSpace == null!");
            }
            if (bandOffsets == null) {
                throw new IllegalArgumentException("bandOffsets == null!");
            }
            int numBands = colorSpace.getNumComponents() +
                (hasAlpha ? 1 : 0);
            if (bandOffsets.length != numBands) {
                throw new IllegalArgumentException
                    ("bandOffsets.length is wrong!");
            }
            if (dataType != DataBuffer.TYPE_BYTE &&
                dataType != DataBuffer.TYPE_SHORT &&
                dataType != DataBuffer.TYPE_USHORT &&
                dataType != DataBuffer.TYPE_INT &&
                dataType != DataBuffer.TYPE_FLOAT &&
                dataType != DataBuffer.TYPE_DOUBLE) {
                throw new IllegalArgumentException
                    ("Bad value for dataType!");
            }
            this.colorSpace = colorSpace;
            this.bandOffsets = (int[])bandOffsets.clone();
            this.dataType = dataType;
            this.hasAlpha = hasAlpha;
            this.isAlphaPremultiplied = isAlphaPremultiplied;

            this.colorModel =
                ImageTypeSpecifier.createComponentCM(colorSpace,
                                                     bandOffsets.length,
                                                     dataType,
                                                     hasAlpha,
                                                     isAlphaPremultiplied);

            int minBandOffset = bandOffsets[0];
            int maxBandOffset = minBandOffset;
            for (int i = 0; i < bandOffsets.length; i++) {
                int offset = bandOffsets[i];
                minBandOffset = Math.min(offset, minBandOffset);
                maxBandOffset = Math.max(offset, maxBandOffset);
            }
            int pixelStride = maxBandOffset - minBandOffset + 1;

            int w = 1;
            int h = 1;
            this.sampleModel =
                new PixelInterleavedSampleModel(dataType,
                                                w, h,
                                                pixelStride,
                                                w*pixelStride,
                                                bandOffsets);
        }

        public boolean equals(Object o) {
            if ((o == null) ||
                !(o instanceof ImageTypeSpecifier.Interleaved)) {
                return false;
            }

            ImageTypeSpecifier.Interleaved that =
                (ImageTypeSpecifier.Interleaved)o;

            if ((!(this.colorSpace.equals(that.colorSpace))) ||
                (this.dataType != that.dataType) ||
                (this.hasAlpha != that.hasAlpha) ||
                (this.isAlphaPremultiplied != that.isAlphaPremultiplied) ||
                (this.bandOffsets.length != that.bandOffsets.length)) {
                return false;
            }

            for (int i = 0; i < bandOffsets.length; i++) {
                if (this.bandOffsets[i] != that.bandOffsets[i]) {
                    return false;
                }
            }

            return true;
        }

        public int hashCode() {
            return (super.hashCode() +
                    (4 * bandOffsets.length) +
                    (25 * dataType) +
                    (hasAlpha ? 17 : 18));
        }
    }

    /**
     * Returns a specifier for an interleaved image format that will
     * use a <code>ComponentColorModel</code> and a
     * <code>PixelInterleavedSampleModel</code> to store each pixel
     * component in a separate byte, short, or int.
     *
     * @param colorSpace the desired <code>ColorSpace</code>.
     * @param bandOffsets an array of <code>int</code>s indicating the
     * offsets for each band.
     * @param dataType the desired data type, as one of the enumerations
     * from the <code>DataBuffer</code> class.
     * @param hasAlpha <code>true</code> if an alpha channel is desired.
     * @param isAlphaPremultiplied <code>true</code> if the color channels
     * will be premultipled by the alpha channel.
     *
     * @return an <code>ImageTypeSpecifier</code> with the desired
     * characteristics.
     *
     * @exception IllegalArgumentException if <code>colorSpace</code>
     * is <code>null</code>.
     * @exception IllegalArgumentException if <code>bandOffsets</code>
     * is <code>null</code>.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of the legal <code>DataBuffer.TYPE_*</code> constants.
     * @exception IllegalArgumentException if
     * <code>bandOffsets.length</code> does not equal the number of
     * color space components, plus 1 if <code>hasAlpha</code> is
     * <code>true</code>.
     */
    public static ImageTypeSpecifier
        createInterleaved(ColorSpace colorSpace,
                          int[] bandOffsets,
                          int dataType,
                          boolean hasAlpha,
                          boolean isAlphaPremultiplied) {
        return new ImageTypeSpecifier.Interleaved(colorSpace,
                                                  bandOffsets,
                                                  dataType,
                                                  hasAlpha,
                                                  isAlphaPremultiplied);
    }

    // Banded

    static class Banded extends ImageTypeSpecifier {
        ColorSpace colorSpace;
        int[] bankIndices;
        int[] bandOffsets;
        int dataType;
        boolean hasAlpha;
        boolean isAlphaPremultiplied;

        public Banded(ColorSpace colorSpace,
                      int[] bankIndices,
                      int[] bandOffsets,
                      int dataType,
                      boolean hasAlpha,
                      boolean isAlphaPremultiplied) {
            if (colorSpace == null) {
                throw new IllegalArgumentException("colorSpace == null!");
            }
            if (bankIndices == null) {
                throw new IllegalArgumentException("bankIndices == null!");
            }
            if (bandOffsets == null) {
                throw new IllegalArgumentException("bandOffsets == null!");
            }
            if (bankIndices.length != bandOffsets.length) {
                throw new IllegalArgumentException
                    ("bankIndices.length != bandOffsets.length!");
            }
            if (dataType != DataBuffer.TYPE_BYTE &&
                dataType != DataBuffer.TYPE_SHORT &&
                dataType != DataBuffer.TYPE_USHORT &&
                dataType != DataBuffer.TYPE_INT &&
                dataType != DataBuffer.TYPE_FLOAT &&
                dataType != DataBuffer.TYPE_DOUBLE) {
                throw new IllegalArgumentException
                    ("Bad value for dataType!");
            }
            int numBands = colorSpace.getNumComponents() +
                (hasAlpha ? 1 : 0);
            if (bandOffsets.length != numBands) {
                throw new IllegalArgumentException
                    ("bandOffsets.length is wrong!");
            }

            this.colorSpace = colorSpace;
            this.bankIndices = (int[])bankIndices.clone();
            this.bandOffsets = (int[])bandOffsets.clone();
            this.dataType = dataType;
            this.hasAlpha = hasAlpha;
            this.isAlphaPremultiplied = isAlphaPremultiplied;

            this.colorModel =
                ImageTypeSpecifier.createComponentCM(colorSpace,
                                                     bankIndices.length,
                                                     dataType,
                                                     hasAlpha,
                                                     isAlphaPremultiplied);

            int w = 1;
            int h = 1;
            this.sampleModel = new BandedSampleModel(dataType,
                                                     w, h,
                                                     w,
                                                     bankIndices,
                                                     bandOffsets);
        }

        public boolean equals(Object o) {
            if ((o == null) ||
                !(o instanceof ImageTypeSpecifier.Banded)) {
                return false;
            }

            ImageTypeSpecifier.Banded that =
                (ImageTypeSpecifier.Banded)o;

            if ((!(this.colorSpace.equals(that.colorSpace))) ||
                (this.dataType != that.dataType) ||
                (this.hasAlpha != that.hasAlpha) ||
                (this.isAlphaPremultiplied != that.isAlphaPremultiplied) ||
                (this.bankIndices.length != that.bankIndices.length) ||
                (this.bandOffsets.length != that.bandOffsets.length)) {
                return false;
            }

            for (int i = 0; i < bankIndices.length; i++) {
                if (this.bankIndices[i] != that.bankIndices[i]) {
                    return false;
                }
            }

            for (int i = 0; i < bandOffsets.length; i++) {
                if (this.bandOffsets[i] != that.bandOffsets[i]) {
                    return false;
                }
            }

            return true;
        }

        public int hashCode() {
            return (super.hashCode() +
                    (3 * bandOffsets.length) +
                    (7 * bankIndices.length) +
                    (21 * dataType) +
                    (hasAlpha ? 19 : 29));
        }
    }

    /**
     * Returns a specifier for a banded image format that will use a
     * <code>ComponentColorModel</code> and a
     * <code>BandedSampleModel</code> to store each channel in a
     * separate array.
     *
     * @param colorSpace the desired <code>ColorSpace</code>.
     * @param bankIndices an array of <code>int</code>s indicating the
     * bank in which each band will be stored.
     * @param bandOffsets an array of <code>int</code>s indicating the
     * starting offset of each band within its bank.
     * @param dataType the desired data type, as one of the enumerations
     * from the <code>DataBuffer</code> class.
     * @param hasAlpha <code>true</code> if an alpha channel is desired.
     * @param isAlphaPremultiplied <code>true</code> if the color channels
     * will be premultipled by the alpha channel.
     *
     * @return an <code>ImageTypeSpecifier</code> with the desired
     * characteristics.
     *
     * @exception IllegalArgumentException if <code>colorSpace</code>
     * is <code>null</code>.
     * @exception IllegalArgumentException if <code>bankIndices</code>
     * is <code>null</code>.
     * @exception IllegalArgumentException if <code>bandOffsets</code>
     * is <code>null</code>.
     * @exception IllegalArgumentException if the lengths of
     * <code>bankIndices</code> and <code>bandOffsets</code> differ.
     * @exception IllegalArgumentException if
     * <code>bandOffsets.length</code> does not equal the number of
     * color space components, plus 1 if <code>hasAlpha</code> is
     * <code>true</code>.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of the legal <code>DataBuffer.TYPE_*</code> constants.
     */
    public static ImageTypeSpecifier
        createBanded(ColorSpace colorSpace,
                     int[] bankIndices,
                     int[] bandOffsets,
                     int dataType,
                     boolean hasAlpha,
                     boolean isAlphaPremultiplied) {
        return new ImageTypeSpecifier.Banded(colorSpace,
                                             bankIndices,
                                             bandOffsets,
                                             dataType,
                                             hasAlpha,
                                             isAlphaPremultiplied);
    }

    // Grayscale

    static class Grayscale extends ImageTypeSpecifier {
        int bits;
        int dataType;
        boolean isSigned;
        boolean hasAlpha;
        boolean isAlphaPremultiplied;

        public Grayscale(int bits,
                         int dataType,
                         boolean isSigned,
                         boolean hasAlpha,
                         boolean isAlphaPremultiplied)
        {
            if (bits != 1 && bits != 2 && bits != 4 &&
                bits != 8 && bits != 16)
            {
                throw new IllegalArgumentException("Bad value for bits!");
            }
            if (dataType != DataBuffer.TYPE_BYTE &&
                dataType != DataBuffer.TYPE_SHORT &&
                dataType != DataBuffer.TYPE_USHORT)
            {
                throw new IllegalArgumentException
                    ("Bad value for dataType!");
            }
            if (bits > 8 && dataType == DataBuffer.TYPE_BYTE) {
                throw new IllegalArgumentException
                    ("Too many bits for dataType!");
            }

            this.bits = bits;
            this.dataType = dataType;
            this.isSigned = isSigned;
            this.hasAlpha = hasAlpha;
            this.isAlphaPremultiplied = isAlphaPremultiplied;

            ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);

            if ((bits == 8 && dataType == DataBuffer.TYPE_BYTE) ||
                (bits == 16 &&
                 (dataType == DataBuffer.TYPE_SHORT ||
                  dataType == DataBuffer.TYPE_USHORT))) {
                // Use component color model & sample model

                int numBands = hasAlpha ? 2 : 1;
                int transparency =
                    hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;


                int[] nBits = new int[numBands];
                nBits[0] = bits;
                if (numBands == 2) {
                    nBits[1] = bits;
                }
                this.colorModel =
                    new ComponentColorModel(colorSpace,
                                            nBits,
                                            hasAlpha,
                                            isAlphaPremultiplied,
                                            transparency,
                                            dataType);

                int[] bandOffsets = new int[numBands];
                bandOffsets[0] = 0;
                if (numBands == 2) {
                    bandOffsets[1] = 1;
                }

                int w = 1;
                int h = 1;
                this.sampleModel =
                    new PixelInterleavedSampleModel(dataType,
                                                    w, h,
                                                    numBands, w*numBands,
                                                    bandOffsets);
            } else {
                int numEntries = 1 << bits;
                byte[] arr = new byte[numEntries];
                for (int i = 0; i < numEntries; i++) {
                    arr[i] = (byte)(i*255/(numEntries - 1));
                }
                this.colorModel =
                    new IndexColorModel(bits, numEntries, arr, arr, arr);

                this.sampleModel =
                    new MultiPixelPackedSampleModel(dataType, 1, 1, bits);
            }
        }
    }

    /**
     * Returns a specifier for a grayscale image format that will pack
     * pixels of the given bit depth into array elements of
     * the specified data type.
     *
     * @param bits the number of bits per gray value (1, 2, 4, 8, or 16).
     * @param dataType the desired data type, as one of the enumerations
     * from the <code>DataBuffer</code> class.
     * @param isSigned <code>true</code> if negative values are to
     * be represented.
     *
     * @return an <code>ImageTypeSpecifier</code> with the desired
     * characteristics.
     *
     * @exception IllegalArgumentException if <code>bits</code> is
     * not one of 1, 2, 4, 8, or 16.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of <code>DataBuffer.TYPE_BYTE</code>,
     * <code>DataBuffer.TYPE_SHORT</code>, or
     * <code>DataBuffer.TYPE_USHORT</code>.
     * @exception IllegalArgumentException if <code>bits</code> is
     * larger than the bit size of the given <code>dataType</code>.
     */
    public static ImageTypeSpecifier
        createGrayscale(int bits,
                        int dataType,
                        boolean isSigned) {
        return new ImageTypeSpecifier.Grayscale(bits,
                                                dataType,
                                                isSigned,
                                                false,
                                                false);
    }

    /**
     * Returns a specifier for a grayscale plus alpha image format
     * that will pack pixels of the given bit depth into array
     * elements of the specified data type.
     *
     * @param bits the number of bits per gray value (1, 2, 4, 8, or 16).
     * @param dataType the desired data type, as one of the enumerations
     * from the <code>DataBuffer</code> class.
     * @param isSigned <code>true</code> if negative values are to
     * be represented.
     * @param isAlphaPremultiplied <code>true</code> if the luminance channel
     * will be premultipled by the alpha channel.
     *
     * @return an <code>ImageTypeSpecifier</code> with the desired
     * characteristics.
     *
     * @exception IllegalArgumentException if <code>bits</code> is
     * not one of 1, 2, 4, 8, or 16.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of <code>DataBuffer.TYPE_BYTE</code>,
     * <code>DataBuffer.TYPE_SHORT</code>, or
     * <code>DataBuffer.TYPE_USHORT</code>.
     * @exception IllegalArgumentException if <code>bits</code> is
     * larger than the bit size of the given <code>dataType</code>.
     */
    public static ImageTypeSpecifier
        createGrayscale(int bits,
                        int dataType,
                        boolean isSigned,
                        boolean isAlphaPremultiplied) {
        return new ImageTypeSpecifier.Grayscale(bits,
                                                dataType,
                                                isSigned,
                                                true,
                                                isAlphaPremultiplied);
    }

    // Indexed

    static class Indexed extends ImageTypeSpecifier {
        byte[] redLUT;
        byte[] greenLUT;
        byte[] blueLUT;
        byte[] alphaLUT = null;
        int bits;
        int dataType;

        public Indexed(byte[] redLUT,
                       byte[] greenLUT,
                       byte[] blueLUT,
                       byte[] alphaLUT,
                       int bits,
                       int dataType) {
            if (redLUT == null || greenLUT == null || blueLUT == null) {
                throw new IllegalArgumentException("LUT is null!");
            }
            if (bits != 1 && bits != 2 && bits != 4 &&
                bits != 8 && bits != 16) {
                throw new IllegalArgumentException("Bad value for bits!");
            }
            if (dataType != DataBuffer.TYPE_BYTE &&
                dataType != DataBuffer.TYPE_SHORT &&
                dataType != DataBuffer.TYPE_USHORT &&
                dataType != DataBuffer.TYPE_INT) {
                throw new IllegalArgumentException
                    ("Bad value for dataType!");
            }
            if ((bits > 8 && dataType == DataBuffer.TYPE_BYTE) ||
                (bits > 16 && dataType != DataBuffer.TYPE_INT)) {
                throw new IllegalArgumentException
                    ("Too many bits for dataType!");
            }

            int len = 1 << bits;
            if (redLUT.length != len ||
                greenLUT.length != len ||
                blueLUT.length != len ||
                (alphaLUT != null && alphaLUT.length != len)) {
                throw new IllegalArgumentException("LUT has improper length!");
            }
            this.redLUT = (byte[])redLUT.clone();
            this.greenLUT = (byte[])greenLUT.clone();
            this.blueLUT = (byte[])blueLUT.clone();
            if (alphaLUT != null) {
                this.alphaLUT = (byte[])alphaLUT.clone();
            }
            this.bits = bits;
            this.dataType = dataType;

            if (alphaLUT == null) {
                this.colorModel = new IndexColorModel(bits,
                                                      redLUT.length,
                                                      redLUT,
                                                      greenLUT,
                                                      blueLUT);
            } else {
                this.colorModel = new IndexColorModel(bits,
                                                      redLUT.length,
                                                      redLUT,
                                                      greenLUT,
                                                      blueLUT,
                                                      alphaLUT);
            }

            if ((bits == 8 && dataType == DataBuffer.TYPE_BYTE) ||
                (bits == 16 &&
                 (dataType == DataBuffer.TYPE_SHORT ||
                  dataType == DataBuffer.TYPE_USHORT))) {
                int[] bandOffsets = { 0 };
                this.sampleModel =
                    new PixelInterleavedSampleModel(dataType,
                                                    1, 1, 1, 1,
                                                    bandOffsets);
            } else {
                this.sampleModel =
                    new MultiPixelPackedSampleModel(dataType, 1, 1, bits);
            }
        }
    }

    /**
     * Returns a specifier for an indexed-color image format that will pack
     * index values of the given bit depth into array elements of
     * the specified data type.
     *
     * @param redLUT an array of <code>byte</code>s containing
     * the red values for each index.
     * @param greenLUT an array of <code>byte</code>s containing * the
     *  green values for each index.
     * @param blueLUT an array of <code>byte</code>s containing the
     * blue values for each index.
     * @param alphaLUT an array of <code>byte</code>s containing the
     * alpha values for each index, or <code>null</code> to create a
     * fully opaque LUT.
     * @param bits the number of bits in each index.
     * @param dataType the desired output type, as one of the enumerations
     * from the <code>DataBuffer</code> class.
     *
     * @return an <code>ImageTypeSpecifier</code> with the desired
     * characteristics.
     *
     * @exception IllegalArgumentException if <code>redLUT</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>greenLUT</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>blueLUT</code> is
     * <code>null</code>.
     * @exception IllegalArgumentException if <code>bits</code> is
     * not one of 1, 2, 4, 8, or 16.
     * @exception IllegalArgumentException if the
     * non-<code>null</code> LUT parameters do not have lengths of
     * exactly <code>1 << bits</code>.
     * @exception IllegalArgumentException if <code>dataType</code> is
     * not one of <code>DataBuffer.TYPE_BYTE</code>,
     * <code>DataBuffer.TYPE_SHORT</code>,
     * <code>DataBuffer.TYPE_USHORT</code>,
     * or <code>DataBuffer.TYPE_INT</code>.
     * @exception IllegalArgumentException if <code>bits</code> is
     * larger than the bit size of the given <code>dataType</code>.
     */
    public static ImageTypeSpecifier
        createIndexed(byte[] redLUT,
                      byte[] greenLUT,
                      byte[] blueLUT,
                      byte[] alphaLUT,
                      int bits,
                      int dataType) {
        return new ImageTypeSpecifier.Indexed(redLUT,
                                              greenLUT,
                                              blueLUT,
                                              alphaLUT,
                                              bits,
                                              dataType);
    }

    /**
     * Returns an <code>ImageTypeSpecifier</code> that encodes
     * one of the standard <code>BufferedImage</code> types
     * (other than <code>TYPE_CUSTOM</code>).
     *
     * @param bufferedImageType an int representing one of the standard
     * <code>BufferedImage</code> types.
     *
     * @return an <code>ImageTypeSpecifier</code> with the desired
     * characteristics.
     *
     * @exception IllegalArgumentException if
     * <code>bufferedImageType</code> is not one of the standard
     * types, or is equal to <code>TYPE_CUSTOM</code>.
     *
     * @see java.awt.image.BufferedImage
     * @see java.awt.image.BufferedImage#TYPE_INT_RGB
     * @see java.awt.image.BufferedImage#TYPE_INT_ARGB
     * @see java.awt.image.BufferedImage#TYPE_INT_ARGB_PRE
     * @see java.awt.image.BufferedImage#TYPE_INT_BGR
     * @see java.awt.image.BufferedImage#TYPE_3BYTE_BGR
     * @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR
     * @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR_PRE
     * @see java.awt.image.BufferedImage#TYPE_USHORT_565_RGB
     * @see java.awt.image.BufferedImage#TYPE_USHORT_555_RGB
     * @see java.awt.image.BufferedImage#TYPE_BYTE_GRAY
     * @see java.awt.image.BufferedImage#TYPE_USHORT_GRAY
     * @see java.awt.image.BufferedImage#TYPE_BYTE_BINARY
     * @see java.awt.image.BufferedImage#TYPE_BYTE_INDEXED
     */
    public static
        ImageTypeSpecifier createFromBufferedImageType(int bufferedImageType) {
        if (bufferedImageType >= BufferedImage.TYPE_INT_RGB &&
            bufferedImageType <= BufferedImage.TYPE_BYTE_INDEXED) {
            return BISpecifier[bufferedImageType];
        } else if (bufferedImageType == BufferedImage.TYPE_CUSTOM) {
            throw new IllegalArgumentException("Cannot create from TYPE_CUSTOM!");
        } else {
            throw new IllegalArgumentException("Invalid BufferedImage type!");
        }
    }

    /**
     * Returns an <code>ImageTypeSpecifier</code> that encodes the
     * layout of a <code>RenderedImage</code> (which may be a
     * <code>BufferedImage</code>).
     *
     * @param image a <code>RenderedImage</code>.
     *
     * @return an <code>ImageTypeSpecifier</code> with the desired
     * characteristics.
     *
     * @exception IllegalArgumentException if <code>image</code> is
     * <code>null</code>.
     */
    public static
        ImageTypeSpecifier createFromRenderedImage(RenderedImage image) {
        if (image == null) {
            throw new IllegalArgumentException("image == null!");
        }

        if (image instanceof BufferedImage) {
            int bufferedImageType = ((BufferedImage)image).getType();
            if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
                return BISpecifier[bufferedImageType];
            }
        }

        return new ImageTypeSpecifier(image);
    }

    /**
     * Returns an int containing one of the enumerated constant values
     * describing image formats from <code>BufferedImage</code>.
     *
     * @return an <code>int</code> representing a
     * <code>BufferedImage</code> type.
     *
     * @see java.awt.image.BufferedImage
     * @see java.awt.image.BufferedImage#TYPE_CUSTOM
     * @see java.awt.image.BufferedImage#TYPE_INT_RGB
     * @see java.awt.image.BufferedImage#TYPE_INT_ARGB
     * @see java.awt.image.BufferedImage#TYPE_INT_ARGB_PRE
     * @see java.awt.image.BufferedImage#TYPE_INT_BGR
     * @see java.awt.image.BufferedImage#TYPE_3BYTE_BGR
     * @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR
     * @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR_PRE
     * @see java.awt.image.BufferedImage#TYPE_USHORT_565_RGB
     * @see java.awt.image.BufferedImage#TYPE_USHORT_555_RGB
     * @see java.awt.image.BufferedImage#TYPE_BYTE_GRAY
     * @see java.awt.image.BufferedImage#TYPE_USHORT_GRAY
     * @see java.awt.image.BufferedImage#TYPE_BYTE_BINARY
     * @see java.awt.image.BufferedImage#TYPE_BYTE_INDEXED
     */
    public int getBufferedImageType() {
        BufferedImage bi = createBufferedImage(1, 1);
        return bi.getType();
    }

    /**
     * Return the number of color components
     * specified by this object.  This is the same value as returned by
     * <code>ColorModel.getNumComponents</code>
     *
     * @return the number of components in the image.
     */
    public int getNumComponents() {
        return colorModel.getNumComponents();
    }

    /**
     * Return the number of bands
     * specified by this object.  This is the same value as returned by
     * <code>SampleModel.getNumBands</code>
     *
     * @return the number of bands in the image.
     */
    public int getNumBands() {
        return sampleModel.getNumBands();
    }

    /**
     * Return the number of bits used to represent samples of the given band.
     *
     * @param band the index of the band to be queried, as an
     * int.
     *
     * @return an int specifying a number of bits.
     *
     * @exception IllegalArgumentException if <code>band</code> is
     * negative or greater than the largest band index.
     */
    public int getBitsPerBand(int band) {
        if (band < 0 | band >= getNumBands()) {
            throw new IllegalArgumentException("band out of range!");
        }
        return sampleModel.getSampleSize(band);
    }

    /**
     * Returns a <code>SampleModel</code> based on the settings
     * encapsulated within this object.  The width and height of the
     * <code>SampleModel</code> will be set to arbitrary values.
     *
     * @return a <code>SampleModel</code> with arbitrary dimensions.
     */
    public SampleModel getSampleModel() {
        return sampleModel;
    }

    /**
     * Returns a <code>SampleModel</code> based on the settings
     * encapsulated within this object.  The width and height of the
     * <code>SampleModel</code> will be set to the supplied values.
     *
     * @param width the desired width of the returned <code>SampleModel</code>.
     * @param height the desired height of the returned
     * <code>SampleModel</code>.
     *
     * @return a <code>SampleModel</code> with the given dimensions.
     *
     * @exception IllegalArgumentException if either <code>width</code> or
     * <code>height</code> are negative or zero.
     * @exception IllegalArgumentException if the product of
     * <code>width</code> and <code>height</code> is greater than
     * <code>Integer.MAX_VALUE</code>
     */
    public SampleModel getSampleModel(int width, int height) {
        if ((long)width*height > Integer.MAX_VALUE) {
            throw new IllegalArgumentException
                ("width*height > Integer.MAX_VALUE!");
        }
        return sampleModel.createCompatibleSampleModel(width, height);
    }

    /**
     * Returns the <code>ColorModel</code> specified by this object.
     *
     * @return a <code>ColorModel</code>.
     */
    public ColorModel getColorModel() {
        return colorModel;
    }

    /**
     * Creates a <code>BufferedImage</code> with a given width and
     * height according to the specification embodied in this object.
     *
     * @param width the desired width of the returned
     * <code>BufferedImage</code>.
     * @param height the desired height of the returned
     * <code>BufferedImage</code>.
     *
     * @return a new <code>BufferedImage</code>
     *
     * @exception IllegalArgumentException if either <code>width</code> or
     * <code>height</code> are negative or zero.
     * @exception IllegalArgumentException if the product of
     * <code>width</code> and <code>height</code> is greater than
     * <code>Integer.MAX_VALUE</code>, or if the number of array
     * elements needed to store the image is greater than
     * <code>Integer.MAX_VALUE</code>.
     */
    public BufferedImage createBufferedImage(int width, int height) {
        try {
            SampleModel sampleModel = getSampleModel(width, height);
            WritableRaster raster =
                Raster.createWritableRaster(sampleModel,
                                            new Point(0, 0));
            return new BufferedImage(colorModel, raster,
                                     colorModel.isAlphaPremultiplied(),
                                     new Hashtable());
        } catch (NegativeArraySizeException e) {
            // Exception most likely thrown from a DataBuffer constructor
            throw new IllegalArgumentException
                ("Array size > Integer.MAX_VALUE!");
        }
    }

    /**
     * Returns <code>true</code> if the given <code>Object</code> is
     * an <code>ImageTypeSpecifier</code> and has a
     * <code>SampleModel</code> and <code>ColorModel</code> that are
     * equal to those of this object.
     *
     * @param o the <code>Object</code> to be compared for equality.
     *
     * @return <code>true</code> if the given object is an equivalent
     * <code>ImageTypeSpecifier</code>.
     */
    public boolean equals(Object o) {
        if ((o == null) || !(o instanceof ImageTypeSpecifier)) {
            return false;
        }

        ImageTypeSpecifier that = (ImageTypeSpecifier)o;
        return (colorModel.equals(that.colorModel)) &&
            (sampleModel.equals(that.sampleModel));
    }

    /**
     * Returns the hash code for this ImageTypeSpecifier.
     *
     * @return a hash code for this ImageTypeSpecifier
     */
    public int hashCode() {
        return (9 * colorModel.hashCode()) + (14 * sampleModel.hashCode());
    }
}
