/*
 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* ****************************************************************
 ******************************************************************
 ******************************************************************
 *** COPYRIGHT (c) Eastman Kodak Company, 1997
 *** As  an unpublished  work pursuant to Title 17 of the United
 *** States Code.  All rights reserved.
 ******************************************************************
 ******************************************************************
 ******************************************************************/

package java.awt.image;

import java.util.Arrays;

/**
 *  This class represents image data which is stored such that each sample
 *  of a pixel occupies one data element of the DataBuffer.  It stores the
 *  N samples which make up a pixel in N separate data array elements.
 *  Different bands may be in different banks of the DataBuffer.
 *  Accessor methods are provided so that image data can be manipulated
 *  directly. This class can support different kinds of interleaving, e.g.
 *  band interleaving, scanline interleaving, and pixel interleaving.
 *  Pixel stride is the number of data array elements between two samples
 *  for the same band on the same scanline. Scanline stride is the number
 *  of data array elements between a given sample and the corresponding sample
 *  in the same column of the next scanline.  Band offsets denote the number
 *  of data array elements from the first data array element of the bank
 *  of the DataBuffer holding each band to the first sample of the band.
 *  The bands are numbered from 0 to N-1.  This class can represent image
 *  data for which each sample is an unsigned integral number which can be
 *  stored in 8, 16, or 32 bits (using <code>DataBuffer.TYPE_BYTE</code>,
 *  <code>DataBuffer.TYPE_USHORT</code>, or <code>DataBuffer.TYPE_INT</code>,
 *  respectively), data for which each sample is a signed integral number
 *  which can be stored in 16 bits (using <code>DataBuffer.TYPE_SHORT</code>),
 *  or data for which each sample is a signed float or double quantity
 *  (using <code>DataBuffer.TYPE_FLOAT</code> or
 *  <code>DataBuffer.TYPE_DOUBLE</code>, respectively).
 *  All samples of a given ComponentSampleModel
 *  are stored with the same precision.  All strides and offsets must be
 *  non-negative.  This class supports
 *  {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
 *  {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
 *  {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
 *  {@link DataBuffer#TYPE_INT TYPE_INT},
 *  {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT},
 *  {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE},
 *  @see java.awt.image.PixelInterleavedSampleModel
 *  @see java.awt.image.BandedSampleModel
 */

public class ComponentSampleModel extends SampleModel
{
    /** Offsets for all bands in data array elements. */
    protected int bandOffsets[];

    /** Index for each bank storing a band of image data. */
    protected int[] bankIndices;

    /**
     * The number of bands in this
     * <code>ComponentSampleModel</code>.
     */
    protected int numBands = 1;

    /**
     * The number of banks in this
     * <code>ComponentSampleModel</code>.
     */
    protected int numBanks = 1;

    /**
     *  Line stride (in data array elements) of the region of image
     *  data described by this ComponentSampleModel.
     */
    protected int scanlineStride;

    /** Pixel stride (in data array elements) of the region of image
     *  data described by this ComponentSampleModel.
     */
    protected int pixelStride;

    static private native void initIDs();
    static {
        ColorModel.loadLibraries();
        initIDs();
    }

    /**
     * Constructs a ComponentSampleModel with the specified parameters.
     * The number of bands will be given by the length of the bandOffsets array.
     * All bands will be stored in the first bank of the DataBuffer.
     * @param dataType  the data type for storing samples
     * @param w         the width (in pixels) of the region of
     *     image data described
     * @param h         the height (in pixels) of the region of
     *     image data described
     * @param pixelStride the pixel stride of the region of image
     *     data described
     * @param scanlineStride the line stride of the region of image
     *     data described
     * @param bandOffsets the offsets of all bands
     * @throws IllegalArgumentException if <code>w</code> or
     *         <code>h</code> is not greater than 0
     * @throws IllegalArgumentException if <code>pixelStride</code>
     *         is less than 0
     * @throws IllegalArgumentException if <code>scanlineStride</code>
     *         is less than 0
     * @throws IllegalArgumentException if <code>numBands</code>
     *         is less than 1
     * @throws IllegalArgumentException if the product of <code>w</code>
     *         and <code>h</code> is greater than
     *         <code>Integer.MAX_VALUE</code>
     * @throws IllegalArgumentException if <code>dataType</code> is not
     *         one of the supported data types
     */
    public ComponentSampleModel(int dataType,
                                int w, int h,
                                int pixelStride,
                                int scanlineStride,
                                int bandOffsets[]) {
        super(dataType, w, h, bandOffsets.length);
        this.dataType = dataType;
        this.pixelStride = pixelStride;
        this.scanlineStride  = scanlineStride;
        this.bandOffsets = (int[])bandOffsets.clone();
        numBands = bandOffsets.length;
        if (pixelStride < 0) {
            throw new IllegalArgumentException("Pixel stride must be >= 0");
        }
        // TODO - bug 4296691 - remove this check
        if (scanlineStride < 0) {
            throw new IllegalArgumentException("Scanline stride must be >= 0");
        }
        if (numBands < 1) {
            throw new IllegalArgumentException("Must have at least one band.");
        }
        if ((dataType < DataBuffer.TYPE_BYTE) ||
            (dataType > DataBuffer.TYPE_DOUBLE)) {
            throw new IllegalArgumentException("Unsupported dataType.");
        }
        bankIndices = new int[numBands];
        for (int i=0; i<numBands; i++) {
            bankIndices[i] = 0;
        }
    }


    /**
     * Constructs a ComponentSampleModel with the specified parameters.
     * The number of bands will be given by the length of the bandOffsets array.
     * Different bands may be stored in different banks of the DataBuffer.
     *
     * @param dataType  the data type for storing samples
     * @param w         the width (in pixels) of the region of
     *     image data described
     * @param h         the height (in pixels) of the region of
     *     image data described
     * @param pixelStride the pixel stride of the region of image
     *     data described
     * @param scanlineStride The line stride of the region of image
     *     data described
     * @param bankIndices the bank indices of all bands
     * @param bandOffsets the band offsets of all bands
     * @throws IllegalArgumentException if <code>w</code> or
     *         <code>h</code> is not greater than 0
     * @throws IllegalArgumentException if <code>pixelStride</code>
     *         is less than 0
     * @throws IllegalArgumentException if <code>scanlineStride</code>
     *         is less than 0
     * @throws IllegalArgumentException if the length of
     *         <code>bankIndices</code> does not equal the length of
     *         <code>bankOffsets</code>
     * @throws IllegalArgumentException if any of the bank indices
     *         of <code>bandIndices</code> is less than 0
     * @throws IllegalArgumentException if <code>dataType</code> is not
     *         one of the supported data types
     */
    public ComponentSampleModel(int dataType,
                                int w, int h,
                                int pixelStride,
                                int scanlineStride,
                                int bankIndices[],
                                int bandOffsets[]) {
        super(dataType, w, h, bandOffsets.length);
        this.dataType = dataType;
        this.pixelStride = pixelStride;
        this.scanlineStride  = scanlineStride;
        this.bandOffsets = (int[])bandOffsets.clone();
        this.bankIndices = (int[]) bankIndices.clone();
        if (pixelStride < 0) {
            throw new IllegalArgumentException("Pixel stride must be >= 0");
        }
        // TODO - bug 4296691 - remove this check
        if (scanlineStride < 0) {
            throw new IllegalArgumentException("Scanline stride must be >= 0");
        }
        if ((dataType < DataBuffer.TYPE_BYTE) ||
            (dataType > DataBuffer.TYPE_DOUBLE)) {
            throw new IllegalArgumentException("Unsupported dataType.");
        }
        int maxBank = bankIndices[0];
        if (maxBank < 0) {
            throw new IllegalArgumentException("Index of bank 0 is less than "+
                                               "0 ("+maxBank+")");
        }
        for (int i=1; i < bankIndices.length; i++) {
            if (bankIndices[i] > maxBank) {
                maxBank = bankIndices[i];
            }
            else if (bankIndices[i] < 0) {
                throw new IllegalArgumentException("Index of bank "+i+
                                                   " is less than 0 ("+
                                                   maxBank+")");
            }
        }
        numBanks         = maxBank+1;
        numBands         = bandOffsets.length;
        if (bandOffsets.length != bankIndices.length) {
            throw new IllegalArgumentException("Length of bandOffsets must "+
                                               "equal length of bankIndices.");
        }
    }

    /**
     * Returns the size of the data buffer (in data elements) needed
     * for a data buffer that matches this ComponentSampleModel.
     */
     private long getBufferSize() {
         int maxBandOff=bandOffsets[0];
         for (int i=1; i<bandOffsets.length; i++)
             maxBandOff = Math.max(maxBandOff,bandOffsets[i]);

         long size = 0;
         if (maxBandOff >= 0)
             size += maxBandOff+1;
         if (pixelStride > 0)
             size += pixelStride * (width-1);
         if (scanlineStride > 0)
             size += scanlineStride*(height-1);
         return size;
     }

     /**
      * Preserves band ordering with new step factor...
      */
    int []orderBands(int orig[], int step) {
        int map[] = new int[orig.length];
        int ret[] = new int[orig.length];

        for (int i=0; i<map.length; i++) map[i] = i;

        for (int i = 0; i < ret.length; i++) {
            int index = i;
            for (int j = i+1; j < ret.length; j++) {
                if (orig[map[index]] > orig[map[j]]) {
                    index = j;
                }
            }
            ret[map[index]] = i*step;
            map[index]  = map[i];
        }
        return ret;
    }

    /**
     * Creates a new <code>ComponentSampleModel</code> with the specified
     * width and height.  The new <code>SampleModel</code> will have the same
     * number of bands, storage data type, interleaving scheme, and
     * pixel stride as this <code>SampleModel</code>.
     * @param w the width of the resulting <code>SampleModel</code>
     * @param h the height of the resulting <code>SampleModel</code>
     * @return a new <code>ComponentSampleModel</code> with the specified size
     * @throws IllegalArgumentException if <code>w</code> or
     *         <code>h</code> is not greater than 0
     */
    public SampleModel createCompatibleSampleModel(int w, int h) {
        SampleModel ret=null;
        long size;
        int minBandOff=bandOffsets[0];
        int maxBandOff=bandOffsets[0];
        for (int i=1; i<bandOffsets.length; i++) {
            minBandOff = Math.min(minBandOff,bandOffsets[i]);
            maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
        }
        maxBandOff -= minBandOff;

        int bands   = bandOffsets.length;
        int bandOff[];
        int pStride = Math.abs(pixelStride);
        int lStride = Math.abs(scanlineStride);
        int bStride = Math.abs(maxBandOff);

        if (pStride > lStride) {
            if (pStride > bStride) {
                if (lStride > bStride) { // pix > line > band
                    bandOff = new int[bandOffsets.length];
                    for (int i=0; i<bands; i++)
                        bandOff[i] = bandOffsets[i]-minBandOff;
                    lStride = bStride+1;
                    pStride = lStride*h;
                } else { // pix > band > line
                    bandOff = orderBands(bandOffsets,lStride*h);
                    pStride = bands*lStride*h;
                }
            } else { // band > pix > line
                pStride = lStride*h;
                bandOff = orderBands(bandOffsets,pStride*w);
            }
        } else {
            if (pStride > bStride) { // line > pix > band
                bandOff = new int[bandOffsets.length];
                for (int i=0; i<bands; i++)
                    bandOff[i] = bandOffsets[i]-minBandOff;
                pStride = bStride+1;
                lStride = pStride*w;
            } else {
                if (lStride > bStride) { // line > band > pix
                    bandOff = orderBands(bandOffsets,pStride*w);
                    lStride = bands*pStride*w;
                } else { // band > line > pix
                    lStride = pStride*w;
                    bandOff = orderBands(bandOffsets,lStride*h);
                }
            }
        }

        // make sure we make room for negative offsets...
        int base = 0;
        if (scanlineStride < 0) {
            base += lStride*h;
            lStride *= -1;
        }
        if (pixelStride    < 0) {
            base += pStride*w;
            pStride *= -1;
        }

        for (int i=0; i<bands; i++)
            bandOff[i] += base;
        return new ComponentSampleModel(dataType, w, h, pStride,
                                        lStride, bankIndices, bandOff);
    }

    /**
     * Creates a new ComponentSampleModel with a subset of the bands
     * of this ComponentSampleModel.  The new ComponentSampleModel can be
     * used with any DataBuffer that the existing ComponentSampleModel
     * can be used with.  The new ComponentSampleModel/DataBuffer
     * combination will represent an image with a subset of the bands
     * of the original ComponentSampleModel/DataBuffer combination.
     * @param bands a subset of bands from this
     *              <code>ComponentSampleModel</code>
     * @return a <code>ComponentSampleModel</code> created with a subset
     *          of bands from this <code>ComponentSampleModel</code>.
     */
    public SampleModel createSubsetSampleModel(int bands[]) {
       if (bands.length > bankIndices.length)
            throw new RasterFormatException("There are only " +
                                            bankIndices.length +
                                            " bands");
        int newBankIndices[] = new int[bands.length];
        int newBandOffsets[] = new int[bands.length];

        for (int i=0; i<bands.length; i++) {
            newBankIndices[i] = bankIndices[bands[i]];
            newBandOffsets[i] = bandOffsets[bands[i]];
        }

        return new ComponentSampleModel(this.dataType, width, height,
                                        this.pixelStride,
                                        this.scanlineStride,
                                        newBankIndices, newBandOffsets);
    }

    /**
     * Creates a <code>DataBuffer</code> that corresponds to this
     * <code>ComponentSampleModel</code>.
     * The <code>DataBuffer</code> object's data type, number of banks,
     * and size are be consistent with this <code>ComponentSampleModel</code>.
     * @return a <code>DataBuffer</code> whose data type, number of banks
     *         and size are consistent with this
     *         <code>ComponentSampleModel</code>.
     */
    public DataBuffer createDataBuffer() {
        DataBuffer dataBuffer = null;

        int size = (int)getBufferSize();
        switch (dataType) {
        case DataBuffer.TYPE_BYTE:
            dataBuffer = new DataBufferByte(size, numBanks);
            break;
        case DataBuffer.TYPE_USHORT:
            dataBuffer = new DataBufferUShort(size, numBanks);
            break;
        case DataBuffer.TYPE_SHORT:
            dataBuffer = new DataBufferShort(size, numBanks);
            break;
        case DataBuffer.TYPE_INT:
            dataBuffer = new DataBufferInt(size, numBanks);
            break;
        case DataBuffer.TYPE_FLOAT:
            dataBuffer = new DataBufferFloat(size, numBanks);
            break;
        case DataBuffer.TYPE_DOUBLE:
            dataBuffer = new DataBufferDouble(size, numBanks);
            break;
        }

        return dataBuffer;
    }


    /** Gets the offset for the first band of pixel (x,y).
     *  A sample of the first band can be retrieved from a
     * <code>DataBuffer</code>
     *  <code>data</code> with a <code>ComponentSampleModel</code>
     * <code>csm</code> as
     * <pre>
     *        data.getElem(csm.getOffset(x, y));
     * </pre>
     * @param x the X location of the pixel
     * @param y the Y location of the pixel
     * @return the offset for the first band of the specified pixel.
     */
    public int getOffset(int x, int y) {
        int offset = y*scanlineStride + x*pixelStride + bandOffsets[0];
        return offset;
    }

    /** Gets the offset for band b of pixel (x,y).
     *  A sample of band <code>b</code> can be retrieved from a
     *  <code>DataBuffer</code> <code>data</code>
     *  with a <code>ComponentSampleModel</code> <code>csm</code> as
     * <pre>
     *       data.getElem(csm.getOffset(x, y, b));
     * </pre>
     * @param x the X location of the specified pixel
     * @param y the Y location of the specified pixel
     * @param b the specified band
     * @return the offset for the specified band of the specified pixel.
     */
    public int getOffset(int x, int y, int b) {
        int offset = y*scanlineStride + x*pixelStride + bandOffsets[b];
        return offset;
    }

    /** Returns the number of bits per sample for all bands.
     *  @return an array containing the number of bits per sample
     *          for all bands, where each element in the array
     *          represents a band.
     */
    public final int[] getSampleSize() {
        int sampleSize[] = new int [numBands];
        int sizeInBits = getSampleSize(0);

        for (int i=0; i<numBands; i++)
            sampleSize[i] = sizeInBits;

        return sampleSize;
    }

    /** Returns the number of bits per sample for the specified band.
     *  @param band the specified band
     *  @return the number of bits per sample for the specified band.
     */
    public final int getSampleSize(int band) {
        return DataBuffer.getDataTypeSize(dataType);
    }

    /** Returns the bank indices for all bands.
     *  @return the bank indices for all bands.
     */
    public final int [] getBankIndices() {
        return (int[]) bankIndices.clone();
    }

    /** Returns the band offset for all bands.
     *  @return the band offsets for all bands.
     */
    public final int [] getBandOffsets() {
        return (int[])bandOffsets.clone();
    }

    /** Returns the scanline stride of this ComponentSampleModel.
     *  @return the scanline stride of this <code>ComponentSampleModel</code>.
     */
    public final int getScanlineStride() {
        return scanlineStride;
    }

    /** Returns the pixel stride of this ComponentSampleModel.
     *  @return the pixel stride of this <code>ComponentSampleModel</code>.
     */
    public final int getPixelStride() {
        return pixelStride;
    }

    /**
     * Returns the number of data elements needed to transfer a pixel
     * with the
     * {@link #getDataElements(int, int, Object, DataBuffer) } and
     * {@link #setDataElements(int, int, Object, DataBuffer) }
     * methods.
     * For a <code>ComponentSampleModel</code>, this is identical to the
     * number of bands.
     * @return the number of data elements needed to transfer a pixel with
     *         the <code>getDataElements</code> and
     *         <code>setDataElements</code> methods.
     * @see java.awt.image.SampleModel#getNumDataElements
     * @see #getNumBands
     */
    public final int getNumDataElements() {
        return getNumBands();
    }

    /**
     * Returns data for a single pixel in a primitive array of type
     * <code>TransferType</code>.  For a <code>ComponentSampleModel</code>,
     * this is the same as the data type, and samples are returned
     * one per array element.  Generally, <code>obj</code> should
     * be passed in as <code>null</code>, so that the <code>Object</code>
     * is created automatically and is the right primitive data type.
     * <p>
     * The following code illustrates transferring data for one pixel from
     * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
     * described by <code>ComponentSampleModel</code> <code>csm1</code>,
     * to <code>DataBuffer</code> <code>db2</code>, whose storage layout
     * is described by <code>ComponentSampleModel</code> <code>csm2</code>.
     * The transfer is usually more efficient than using
     * <code>getPixel</code> and <code>setPixel</code>.
     * <pre>
     *       ComponentSampleModel csm1, csm2;
     *       DataBufferInt db1, db2;
     *       csm2.setDataElements(x, y,
     *                            csm1.getDataElements(x, y, null, db1), db2);
     * </pre>
     *
     * Using <code>getDataElements</code> and <code>setDataElements</code>
     * to transfer between two <code>DataBuffer/SampleModel</code>
     * pairs is legitimate if the <code>SampleModel</code> objects have
     * the same number of bands, corresponding bands have the same number of
     * bits per sample, and the <code>TransferType</code>s are the same.
     * <p>
     * If <code>obj</code> is not <code>null</code>, it should be a
     * primitive array of type <code>TransferType</code>.
     * Otherwise, a <code>ClassCastException</code> is thrown.  An
     * <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
     * coordinates are not in bounds, or if <code>obj</code> is not
     * <code>null</code> and is not large enough to hold
     * the pixel data.
     *
     * @param x         the X coordinate of the pixel location
     * @param y         the Y coordinate of the pixel location
     * @param obj       if non-<code>null</code>, a primitive array
     *                  in which to return the pixel data
     * @param data      the <code>DataBuffer</code> containing the image data
     * @return the data of the specified pixel
     * @see #setDataElements(int, int, Object, DataBuffer)
     *
     * @throws NullPointerException if data is null.
     * @throws ArrayIndexOutOfBoundsException if the coordinates are
     * not in bounds, or if obj is too small to hold the ouput.
     */
    public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }

        int type = getTransferType();
        int numDataElems = getNumDataElements();
        int pixelOffset = y*scanlineStride + x*pixelStride;

        switch(type) {

        case DataBuffer.TYPE_BYTE:

            byte[] bdata;

            if (obj == null)
                bdata = new byte[numDataElems];
            else
                bdata = (byte[])obj;

            for (int i=0; i<numDataElems; i++) {
                bdata[i] = (byte)data.getElem(bankIndices[i],
                                              pixelOffset + bandOffsets[i]);
            }

            obj = (Object)bdata;
            break;

        case DataBuffer.TYPE_USHORT:
        case DataBuffer.TYPE_SHORT:

            short[] sdata;

            if (obj == null)
                sdata = new short[numDataElems];
            else
                sdata = (short[])obj;

            for (int i=0; i<numDataElems; i++) {
                sdata[i] = (short)data.getElem(bankIndices[i],
                                               pixelOffset + bandOffsets[i]);
            }

            obj = (Object)sdata;
            break;

        case DataBuffer.TYPE_INT:

            int[] idata;

            if (obj == null)
                idata = new int[numDataElems];
            else
                idata = (int[])obj;

            for (int i=0; i<numDataElems; i++) {
                idata[i] = data.getElem(bankIndices[i],
                                        pixelOffset + bandOffsets[i]);
            }

            obj = (Object)idata;
            break;

        case DataBuffer.TYPE_FLOAT:

            float[] fdata;

            if (obj == null)
                fdata = new float[numDataElems];
            else
                fdata = (float[])obj;

            for (int i=0; i<numDataElems; i++) {
                fdata[i] = data.getElemFloat(bankIndices[i],
                                             pixelOffset + bandOffsets[i]);
            }

            obj = (Object)fdata;
            break;

        case DataBuffer.TYPE_DOUBLE:

            double[] ddata;

            if (obj == null)
                ddata = new double[numDataElems];
            else
                ddata = (double[])obj;

            for (int i=0; i<numDataElems; i++) {
                ddata[i] = data.getElemDouble(bankIndices[i],
                                              pixelOffset + bandOffsets[i]);
            }

            obj = (Object)ddata;
            break;
        }

        return obj;
    }

    /**
     * Returns all samples for the specified pixel in an int array,
     * one sample per array element.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
     * the coordinates are not in bounds.
     * @param x         the X coordinate of the pixel location
     * @param y         the Y coordinate of the pixel location
     * @param iArray    If non-null, returns the samples in this array
     * @param data      The DataBuffer containing the image data
     * @return the samples of the specified pixel.
     * @see #setPixel(int, int, int[], DataBuffer)
     *
     * @throws NullPointerException if data is null.
     * @throws ArrayIndexOutOfBoundsException if the coordinates are
     * not in bounds, or if iArray is too small to hold the output.
     */
    public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
        int pixels[];
        if (iArray != null) {
           pixels = iArray;
        } else {
           pixels = new int [numBands];
        }
        int pixelOffset = y*scanlineStride + x*pixelStride;
        for (int i=0; i<numBands; i++) {
            pixels[i] = data.getElem(bankIndices[i],
                                     pixelOffset + bandOffsets[i]);
        }
        return pixels;
    }

    /**
     * Returns all samples for the specified rectangle of pixels in
     * an int array, one sample per array element.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
     * the coordinates are not in bounds.
     * @param x         The X coordinate of the upper left pixel location
     * @param y         The Y coordinate of the upper left pixel location
     * @param w         The width of the pixel rectangle
     * @param h         The height of the pixel rectangle
     * @param iArray    If non-null, returns the samples in this array
     * @param data      The DataBuffer containing the image data
     * @return the samples of the pixels within the specified region.
     * @see #setPixels(int, int, int, int, int[], DataBuffer)
     */
    public int[] getPixels(int x, int y, int w, int h,
                           int iArray[], DataBuffer data) {
        if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
        int pixels[];
        if (iArray != null) {
           pixels = iArray;
        } else {
           pixels = new int [w*h*numBands];
        }
        int lineOffset = y*scanlineStride + x*pixelStride;
        int srcOffset = 0;

        for (int i = 0; i < h; i++) {
           int pixelOffset = lineOffset;
           for (int j = 0; j < w; j++) {
              for (int k=0; k < numBands; k++) {
                 pixels[srcOffset++] =
                    data.getElem(bankIndices[k], pixelOffset + bandOffsets[k]);
              }
              pixelOffset += pixelStride;
           }
           lineOffset += scanlineStride;
        }
        return pixels;
    }

    /**
     * Returns as int the sample in a specified band for the pixel
     * located at (x,y).
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
     * the coordinates are not in bounds.
     * @param x         the X coordinate of the pixel location
     * @param y         the Y coordinate of the pixel location
     * @param b         the band to return
     * @param data      the <code>DataBuffer</code> containing the image data
     * @return the sample in a specified band for the specified pixel
     * @see #setSample(int, int, int, int, DataBuffer)
     */
    public int getSample(int x, int y, int b, DataBuffer data) {
        // Bounds check for 'b' will be performed automatically
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
        int sample = data.getElem(bankIndices[b],
                                  y*scanlineStride + x*pixelStride +
                                  bandOffsets[b]);
        return sample;
    }

    /**
     * Returns the sample in a specified band
     * for the pixel located at (x,y) as a float.
     * An <code>ArrayIndexOutOfBoundsException</code> might be
     * thrown if the coordinates are not in bounds.
     * @param x         The X coordinate of the pixel location
     * @param y         The Y coordinate of the pixel location
     * @param b         The band to return
     * @param data      The DataBuffer containing the image data
     * @return a float value representing the sample in the specified
     * band for the specified pixel.
     */
    public float getSampleFloat(int x, int y, int b, DataBuffer data) {
        // Bounds check for 'b' will be performed automatically
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }

        float sample = data.getElemFloat(bankIndices[b],
                                         y*scanlineStride + x*pixelStride +
                                         bandOffsets[b]);
        return sample;
    }

    /**
     * Returns the sample in a specified band
     * for a pixel located at (x,y) as a double.
     * An <code>ArrayIndexOutOfBoundsException</code> might be
     * thrown if the coordinates are not in bounds.
     * @param x         The X coordinate of the pixel location
     * @param y         The Y coordinate of the pixel location
     * @param b         The band to return
     * @param data      The DataBuffer containing the image data
     * @return a double value representing the sample in the specified
     * band for the specified pixel.
     */
    public double getSampleDouble(int x, int y, int b, DataBuffer data) {
        // Bounds check for 'b' will be performed automatically
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }

        double sample = data.getElemDouble(bankIndices[b],
                                           y*scanlineStride + x*pixelStride +
                                           bandOffsets[b]);
        return sample;
    }

    /**
     * Returns the samples in a specified band for the specified rectangle
     * of pixels in an int array, one sample per data array element.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
     * the coordinates are not in bounds.
     * @param x         The X coordinate of the upper left pixel location
     * @param y         The Y coordinate of the upper left pixel location
     * @param w         the width of the pixel rectangle
     * @param h         the height of the pixel rectangle
     * @param b         the band to return
     * @param iArray    if non-<code>null</code>, returns the samples
     *                  in this array
     * @param data      the <code>DataBuffer</code> containing the image data
     * @return the samples in the specified band of the specified pixel
     * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
     */
    public int[] getSamples(int x, int y, int w, int h, int b,
                            int iArray[], DataBuffer data) {
        // Bounds check for 'b' will be performed automatically
        if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
        int samples[];
        if (iArray != null) {
           samples = iArray;
        } else {
           samples = new int [w*h];
        }
        int lineOffset = y*scanlineStride + x*pixelStride +  bandOffsets[b];
        int srcOffset = 0;

        for (int i = 0; i < h; i++) {
           int sampleOffset = lineOffset;
           for (int j = 0; j < w; j++) {
              samples[srcOffset++] = data.getElem(bankIndices[b],
                                                  sampleOffset);
              sampleOffset += pixelStride;
           }
           lineOffset += scanlineStride;
        }
        return samples;
    }

    /**
     * Sets the data for a single pixel in the specified
     * <code>DataBuffer</code> from a primitive array of type
     * <code>TransferType</code>.  For a <code>ComponentSampleModel</code>,
     * this is the same as the data type, and samples are transferred
     * one per array element.
     * <p>
     * The following code illustrates transferring data for one pixel from
     * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
     * described by <code>ComponentSampleModel</code> <code>csm1</code>,
     * to <code>DataBuffer</code> <code>db2</code>, whose storage layout
     * is described by <code>ComponentSampleModel</code> <code>csm2</code>.
     * The transfer is usually more efficient than using
     * <code>getPixel</code> and <code>setPixel</code>.
     * <pre>
     *       ComponentSampleModel csm1, csm2;
     *       DataBufferInt db1, db2;
     *       csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
     *                            db2);
     * </pre>
     * Using <code>getDataElements</code> and <code>setDataElements</code>
     * to transfer between two <code>DataBuffer/SampleModel</code> pairs
     * is legitimate if the <code>SampleModel</code> objects have
     * the same number of bands, corresponding bands have the same number of
     * bits per sample, and the <code>TransferType</code>s are the same.
     * <p>
     * A <code>ClassCastException</code> is thrown if <code>obj</code> is not
     * a primitive array of type <code>TransferType</code>.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
     * the coordinates are not in bounds, or if <code>obj</code> is not large
     * enough to hold the pixel data.
     * @param x         the X coordinate of the pixel location
     * @param y         the Y coordinate of the pixel location
     * @param obj       a primitive array containing pixel data
     * @param data      the DataBuffer containing the image data
     * @see #getDataElements(int, int, Object, DataBuffer)
     */
    public void setDataElements(int x, int y, Object obj, DataBuffer data) {
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }

        int type = getTransferType();
        int numDataElems = getNumDataElements();
        int pixelOffset = y*scanlineStride + x*pixelStride;

        switch(type) {

        case DataBuffer.TYPE_BYTE:

            byte[] barray = (byte[])obj;

            for (int i=0; i<numDataElems; i++) {
                data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
                           ((int)barray[i])&0xff);
            }
            break;

        case DataBuffer.TYPE_USHORT:
        case DataBuffer.TYPE_SHORT:

            short[] sarray = (short[])obj;

            for (int i=0; i<numDataElems; i++) {
                data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
                           ((int)sarray[i])&0xffff);
            }
            break;

        case DataBuffer.TYPE_INT:

            int[] iarray = (int[])obj;

            for (int i=0; i<numDataElems; i++) {
                data.setElem(bankIndices[i],
                             pixelOffset + bandOffsets[i], iarray[i]);
            }
            break;

        case DataBuffer.TYPE_FLOAT:

            float[] farray = (float[])obj;

            for (int i=0; i<numDataElems; i++) {
                data.setElemFloat(bankIndices[i],
                             pixelOffset + bandOffsets[i], farray[i]);
            }
            break;

        case DataBuffer.TYPE_DOUBLE:

            double[] darray = (double[])obj;

            for (int i=0; i<numDataElems; i++) {
                data.setElemDouble(bankIndices[i],
                             pixelOffset + bandOffsets[i], darray[i]);
            }
            break;

        }
    }

    /**
     * Sets a pixel in the <code>DataBuffer</code> using an int array of
     * samples for input.  An <code>ArrayIndexOutOfBoundsException</code>
     * might be thrown if the coordinates are
     * not in bounds.
     * @param x         The X coordinate of the pixel location
     * @param y         The Y coordinate of the pixel location
     * @param iArray    The input samples in an int array
     * @param data      The DataBuffer containing the image data
     * @see #getPixel(int, int, int[], DataBuffer)
     */
    public void setPixel(int x, int y, int iArray[], DataBuffer data) {
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
       int pixelOffset = y*scanlineStride + x*pixelStride;
       for (int i=0; i<numBands; i++) {
           data.setElem(bankIndices[i],
                        pixelOffset + bandOffsets[i],iArray[i]);
       }
    }

    /**
     * Sets all samples for a rectangle of pixels from an int array containing
     * one sample per array element.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
     * coordinates are not in bounds.
     * @param x         The X coordinate of the upper left pixel location
     * @param y         The Y coordinate of the upper left pixel location
     * @param w         The width of the pixel rectangle
     * @param h         The height of the pixel rectangle
     * @param iArray    The input samples in an int array
     * @param data      The DataBuffer containing the image data
     * @see #getPixels(int, int, int, int, int[], DataBuffer)
     */
    public void setPixels(int x, int y, int w, int h,
                          int iArray[], DataBuffer data) {
        if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }

        int lineOffset = y*scanlineStride + x*pixelStride;
        int srcOffset = 0;

        for (int i = 0; i < h; i++) {
           int pixelOffset = lineOffset;
           for (int j = 0; j < w; j++) {
              for (int k=0; k < numBands; k++) {
                 data.setElem(bankIndices[k], pixelOffset + bandOffsets[k],
                              iArray[srcOffset++]);
              }
              pixelOffset += pixelStride;
           }
           lineOffset += scanlineStride;
        }
    }

    /**
     * Sets a sample in the specified band for the pixel located at (x,y)
     * in the <code>DataBuffer</code> using an int for input.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
     * coordinates are not in bounds.
     * @param x         The X coordinate of the pixel location
     * @param y         The Y coordinate of the pixel location
     * @param b         the band to set
     * @param s         the input sample as an int
     * @param data      the DataBuffer containing the image data
     * @see #getSample(int, int, int, DataBuffer)
     */
    public void setSample(int x, int y, int b, int s,
                          DataBuffer data) {
        // Bounds check for 'b' will be performed automatically
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
        data.setElem(bankIndices[b],
                     y*scanlineStride + x*pixelStride + bandOffsets[b], s);
    }

    /**
     * Sets a sample in the specified band for the pixel located at (x,y)
     * in the <code>DataBuffer</code> using a float for input.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
     * the coordinates are not in bounds.
     * @param x         The X coordinate of the pixel location
     * @param y         The Y coordinate of the pixel location
     * @param b         The band to set
     * @param s         The input sample as a float
     * @param data      The DataBuffer containing the image data
     * @see #getSample(int, int, int, DataBuffer)
     */
    public void setSample(int x, int y, int b,
                          float s ,
                          DataBuffer data) {
        // Bounds check for 'b' will be performed automatically
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
        data.setElemFloat(bankIndices[b],
                          y*scanlineStride + x*pixelStride + bandOffsets[b],
                          s);
    }

    /**
     * Sets a sample in the specified band for the pixel located at (x,y)
     * in the <code>DataBuffer</code> using a double for input.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
     * the coordinates are not in bounds.
     * @param x         The X coordinate of the pixel location
     * @param y         The Y coordinate of the pixel location
     * @param b         The band to set
     * @param s         The input sample as a double
     * @param data      The DataBuffer containing the image data
     * @see #getSample(int, int, int, DataBuffer)
     */
    public void setSample(int x, int y, int b,
                          double s,
                          DataBuffer data) {
        // Bounds check for 'b' will be performed automatically
        if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
        data.setElemDouble(bankIndices[b],
                          y*scanlineStride + x*pixelStride + bandOffsets[b],
                          s);
    }

    /**
     * Sets the samples in the specified band for the specified rectangle
     * of pixels from an int array containing one sample per data array element.
     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
     * coordinates are not in bounds.
     * @param x         The X coordinate of the upper left pixel location
     * @param y         The Y coordinate of the upper left pixel location
     * @param w         The width of the pixel rectangle
     * @param h         The height of the pixel rectangle
     * @param b         The band to set
     * @param iArray    The input samples in an int array
     * @param data      The DataBuffer containing the image data
     * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
     */
    public void setSamples(int x, int y, int w, int h, int b,
                           int iArray[], DataBuffer data) {
        // Bounds check for 'b' will be performed automatically
        if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
            throw new ArrayIndexOutOfBoundsException
                ("Coordinate out of bounds!");
        }
        int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
        int srcOffset = 0;

        for (int i = 0; i < h; i++) {
           int sampleOffset = lineOffset;
           for (int j = 0; j < w; j++) {
              data.setElem(bankIndices[b], sampleOffset, iArray[srcOffset++]);
              sampleOffset += pixelStride;
           }
           lineOffset += scanlineStride;
        }
    }

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

        ComponentSampleModel that = (ComponentSampleModel)o;
        return this.width == that.width &&
            this.height == that.height &&
            this.numBands == that.numBands &&
            this.dataType == that.dataType &&
            Arrays.equals(this.bandOffsets, that.bandOffsets) &&
            Arrays.equals(this.bankIndices, that.bankIndices) &&
            this.numBands == that.numBands &&
            this.numBanks == that.numBanks &&
            this.scanlineStride == that.scanlineStride &&
            this.pixelStride == that.pixelStride;
    }

    // If we implement equals() we must also implement hashCode
    public int hashCode() {
        int hash = 0;
        hash = width;
        hash <<= 8;
        hash ^= height;
        hash <<= 8;
        hash ^= numBands;
        hash <<= 8;
        hash ^= dataType;
        hash <<= 8;
        for (int i = 0; i < bandOffsets.length; i++) {
            hash ^= bandOffsets[i];
            hash <<= 8;
        }
        for (int i = 0; i < bankIndices.length; i++) {
            hash ^= bankIndices[i];
            hash <<= 8;
        }
        hash ^= numBands;
        hash <<= 8;
        hash ^= numBanks;
        hash <<= 8;
        hash ^= scanlineStride;
        hash <<= 8;
        hash ^= pixelStride;
        return hash;
    }
}
