/* ImageTypeSpecifier.java --
   Copyright (C) 2004  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.imageio;

import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.DataBuffer;
import java.awt.image.BandedSampleModel;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;

/**
 * ImageTypeSpecifier store the color and sample models associated
 * with an IIOImage.
 */
public class ImageTypeSpecifier
{
  /**
   * The image's color model.
   */
  protected ColorModel colorModel;

  /**
   * The image's sample model.
   */
  protected SampleModel sampleModel;

  /**
   * Construct an image type specifier with the given models.
   *
   * @param colorModel the color model
   * @param sampleModel the sample model
   *
   * @exception IllegalArgumentException if either model argument is
   * null
   * @exception IllegalArgumentException if the models are
   * incompatible with one another
   */
  public ImageTypeSpecifier(ColorModel colorModel, SampleModel sampleModel)
  {
    if (colorModel == null)
      throw new IllegalArgumentException("colorModel may not be null");

    if (sampleModel == null)
      throw new IllegalArgumentException("sampleModel may not be null");

    if (!colorModel.isCompatibleSampleModel(sampleModel))
      throw new IllegalArgumentException
        ("sample Model not compatible with colorModel");
    
    this.colorModel = colorModel;
    this.sampleModel = sampleModel;
  }

  /**
   * Construct an image type specifier that describes the given
   * rendered image.
   *
   * @param image a rendered image
   *
   * @exception IllegalArgumentException if image is null
   */
  public ImageTypeSpecifier(RenderedImage image)
  {
    if (image == null)
      throw new IllegalArgumentException("image may not be null");
    
    this.colorModel = image.getColorModel();
    this.sampleModel = image.getSampleModel();
  }

  /**
   * Create an image type specifier for a banded image using a
   * component color model and a banded sample model.
   *
   * @param colorSpace the color space
   * @param bankIndices the bank indices at which each band will be
   * stored
   * @param bankOffsets the starting band offset for each band within
   * its bank
   * @param dataType the data type, a DataBuffer constant
   * @param hasAlpha true if this image type specifier should have an
   * alpha component, false otherwise
   * @param isAlphaPremultiplied true if other color components should
   * be premultiplied by the alpha component, false otherwise
   *
   * @return a banded image type specifier
   *
   * @exception IllegalArgumentException if any of colorSpace,
   * bankIndices or bankOffsets is null
   * @exception IllegalArgumentException if bankIndices and
   * bankOffsets differ in length
   * @excpetion IllegalArgumentException if the number of color space
   * components, including the alpha component if requested, is
   * different from bandOffsets.length
   * @exception if dataType is not a valid DataBuffer constant
   */
  public static ImageTypeSpecifier createBanded (ColorSpace colorSpace,
                                                 int[] bankIndices,
                                                 int[] bankOffsets,
                                                 int dataType,
                                                 boolean hasAlpha,
                                                 boolean isAlphaPremultiplied)
  {
    if (colorSpace == null || bankIndices == null || bankOffsets == null)
      throw new IllegalArgumentException ("null argument");

    if (bankIndices.length != bankOffsets.length)
      throw new IllegalArgumentException ("array lengths differ");

    if (bankOffsets.length != (colorSpace.getNumComponents() + (hasAlpha ? 1 : 0)))
      throw new IllegalArgumentException ("invalid bankOffsets length");

    return new ImageTypeSpecifier (new ComponentColorModel (colorSpace,
                                                            hasAlpha,
                                                            isAlphaPremultiplied,
                                                            hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE,
                                                            dataType),
                                   new BandedSampleModel (dataType, 1, 1, 1,
                                                          bankIndices,
                                                          bankOffsets));
  }

  /**
   * Create a buffered image with the given dimensions using that has
   * the characteristics specified by this image type specifier.
   *
   * @param width  width of the buffered image, in pixels
   * @param height the height of the buffered image, in pixels
   *
   * @return a buffered image
   *
   * @exception IllegalArgumentException if either width or height is
   * less than or equal to zero
   * @exception IllegalArgumentException if width * height is greater
   * than Integer.MAX_VALUE or if the storage required is greater than
   * Integer.MAX_VALUE
   */
  public BufferedImage createBufferedImage (int width, int height)
  {
    if (width <= 0 || height <= 0)
      throw new IllegalArgumentException ("dimension <= 0");

    // test for overflow
    if (width * height < Math.min (width, height))
      throw new IllegalArgumentException ("width * height > Integer.MAX_VALUE");

    if (width * height * sampleModel.getNumBands() < Math.min (width, height))
      throw new IllegalArgumentException ("storage required >"
                                          + " Integer.MAX_VALUE");

    // FIXME: this is probably wrong:
    return new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB);
  }

  /**
   * Create an image type specifier that describes the given buffered
   * image type.
   *
   * @param bufferedImageType the buffered image type to represent
   * with the returned image type specifier
   *
   * @return a new image type specifier
   *
   * @exception IllegalArgumentException if bufferedImageType is not a
   * BufferedImage constant or is BufferedImage.TYPE_CUSTOM
   */
  public static ImageTypeSpecifier createFromBufferedImageType (int bufferedImageType)
  {
    if (bufferedImageType <= BufferedImage.TYPE_CUSTOM
        || bufferedImageType > BufferedImage.TYPE_BYTE_INDEXED)
      throw new IllegalArgumentException ("invalid buffered image type");

    return new ImageTypeSpecifier (new BufferedImage (1, 1, bufferedImageType));
  }

  /**
   * Create an image type specifier that describes the given rendered
   * image's type.
   *
   * @param image the rendered image
   *
   * @return a new image type specifier
   *
   * @exception IllegalArgumentException if image is null
   */
  public static ImageTypeSpecifier createFromRenderedImage (RenderedImage image)
  {
    if (image == null)
      throw new IllegalArgumentException ("image null");

    return new ImageTypeSpecifier (image);
  }

  /**
   * Create a grayscale image type specifier, given the number of
   * bits, data type and whether or not the data is signed.
   *
   * @param bits the number of bits used to specify a greyscale value
   * @param dataType a DataBuffer type constant
   * @param isSigned true if this type specifier should support
   * negative values, false otherwise
   *
   * @return a greyscal image type specifier
   *
   * @exception IllegalArgumentException if bits is not 1, 2, 4, 8 or 16
   * @exception IllegalArgumentException if dataType is not
   * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT or
   * DataBuffer.TYPE_USHORT
   * @exception if bits is larger than the number of bits in the given
   * data type
   */
  public static ImageTypeSpecifier createGrayscale (int bits, int dataType, boolean isSigned)
  {
    return createGrayscale (bits, dataType, isSigned, false);
  }

  /**
   * Create a grayscale image type specifier, given the number of
   * bits, data type and whether or not the data is signed.
   *
   * @param bits the number of bits used to specify a greyscale value
   * @param dataType a DataBuffer type constant
   * @param isSigned true if this type specifier should support
   * negative values, false otherwise
   *
   * @return a greyscal image type specifier
   *
   * @exception IllegalArgumentException if bits is not 1, 2, 4, 8 or
   * 16
   * @exception IllegalArgumentException if dataType is not
   * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT or
   * DataBuffer.TYPE_USHORT
   * @exception if bits is larger than the number of bits in the given
   * data type
   */
  public static ImageTypeSpecifier createGrayscale (int bits, int dataType,
                                                    boolean isSigned,
                                                    boolean isAlphaPremultiplied)
  {
    if (bits != 1 && bits != 2 && bits != 4 && bits != 8 && bits != 16)
      throw new IllegalArgumentException ("invalid bit size");

    if (dataType != DataBuffer.TYPE_BYTE && dataType != DataBuffer.TYPE_SHORT
        && dataType != DataBuffer.TYPE_USHORT)
      throw new IllegalArgumentException ("invalid data type");

    if (dataType == DataBuffer.TYPE_BYTE && bits > 8)
      throw new IllegalArgumentException ("number of bits too large for data type");

    // FIXME: this is probably wrong:
    return new ImageTypeSpecifier (new DirectColorModel (bits, 0xff, 0x0,
                                                         0x0, 0xff),
                                   new MultiPixelPackedSampleModel (dataType,
                                                                    1, 1,
                                                                    bits));
  }

  /**
   * Return an image type specifier for an image that uses an indexed
   * colour model where each colour value has the specified number of
   * bits and type and where the colour tables are those given.
   *
   * @param redLUT the red index values
   * @param greenLUT the green index values
   * @param blueLUT the blue index values
   * @param alphaLUT the alpha index values
   * @param bits the number of bits per index value
   * @param dataType the type of each index value
   *
   * @return an indexed image type specifier
   *
   * @exception IllegalArgumentException if any of the colour arrays,
   * not including alphaLUT, is null
   * @exception IllegalArgumentException if bits is not 1, 2, 4, 8 or
   * 16
   * @exception IllegalArgumentException if dataType is not
   * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT or
   * DataBuffer.TYPE_USHORT
   * @exception if bits is larger than the number of bits in the given
   * data type
   */
  public static ImageTypeSpecifier createIndexed (byte[] redLUT,
						  byte[] greenLUT,
						  byte[] blueLUT,
						  byte[] alphaLUT,
						  int bits,
						  int dataType)
  {
    if (redLUT == null || greenLUT == null || blueLUT == null)
      throw new IllegalArgumentException ("null colour table");

    if (bits != 1 && bits != 2 && bits != 4 && bits != 8 && bits != 16)
      throw new IllegalArgumentException ("invalid bit size");

    if (dataType != DataBuffer.TYPE_BYTE && dataType != DataBuffer.TYPE_SHORT
        && dataType != DataBuffer.TYPE_USHORT)
      throw new IllegalArgumentException ("invalid data type");

    if (dataType == DataBuffer.TYPE_BYTE && bits > 8)
      throw new IllegalArgumentException ("number of bits too large for data type");

    // FIXME: this is probably wrong:
    return new ImageTypeSpecifier (new IndexColorModel (bits, redLUT.length,
                                                        redLUT, greenLUT, blueLUT,
                                                        alphaLUT),
                                   new MultiPixelPackedSampleModel (dataType,
                                                                    1, 1,
                                                                    bits));
  }

  /**
   * Create an image type specifier that uses a component colour model
   * and a pixel interleaved sample model.  Each pixel component will
   * be stored in a separate value of the given data type.
   *
   * @param colorSpace the colour space used by the colour model
   * @param bandOffsets the starting band offset for each band within
   * its bank
   * @param dataType the type of each pixel value
   * @param hasAlpha true if an alpha channel should be specified,
   * false otherwise
   * @param isAlphaPremultiplied true if other colour channels should
   * be premultiplied by the alpha value, false otherwise
   *
   * @return an interleaved image type specifier
   *
   * @exception IllegalArgumentException if either colorSpace or
   * bandOffsets is null
   * @excpetion IllegalArgumentException if the number of color space
   * components, including the alpha component if requested, is
   * different from bandOffsets.length
   * @exception if dataType is not a valid DataBuffer constant
   */
  public static ImageTypeSpecifier createInterleaved (ColorSpace colorSpace,
                                                      int[] bandOffsets,
                                                      int dataType,
                                                      boolean hasAlpha,
                                                      boolean isAlphaPremultiplied)
  {
    if (colorSpace == null || bandOffsets == null)
      throw new IllegalArgumentException ("null argument");

    if (bandOffsets.length != (colorSpace.getNumComponents() + (hasAlpha ? 1 : 0)))
      throw new IllegalArgumentException ("invalid bankOffsets length");

    return new ImageTypeSpecifier (new ComponentColorModel (colorSpace,
                                                            hasAlpha,
                                                            isAlphaPremultiplied,
                                                            hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE,
                                                            dataType),
                                   new PixelInterleavedSampleModel (dataType, 1, 1, 1, 1,
                                                                    bandOffsets));
  }

  /**
   * Create an image type specifier using a direct color model and a
   * packed sample model.  All pixel components will be packed into
   * one value of the given data type.
   *
   * @param colorSpace the color space to use in the color model
   * @param redMask the bitmask for the red bits 
   * @param greenMask the bitmask for the green bits 
   * @param blueMask the bitmask for the blue bits 
   * @param alphaMask the bitmask for the alpha bits 
   * @param transferType the data type used to store pixel values
   * @param isAlphaPremultiplied true if other colour channels should
   * be premultiplied by the alpha value, false otherwise
   *
   * @return a packed image type specifier
   *
   * @exception IllegalArgumentException if colorSpace is null
   * @exception IllegalArgumentException if colorSpace does not have
   * type ColorSpace.TYPE_RGB
   * @exception IllegalArgumentException if all masks are 0
   * @exception IllegalArgumentException if dataType is not
   * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT or
   * DataBuffer.TYPE_INT
   */
  public static ImageTypeSpecifier createPacked (ColorSpace colorSpace,
                                                 int redMask,
                                                 int greenMask,
                                                 int blueMask,
                                                 int alphaMask,
                                                 int transferType,
                                                 boolean isAlphaPremultiplied)
  {
    if (colorSpace == null)
      throw new IllegalArgumentException ("null color space");

    if (colorSpace.getType() != ColorSpace.TYPE_RGB)
      throw new IllegalArgumentException ("invalid color space type");

    if (redMask == 0 && greenMask == 0 && blueMask == 0 && alphaMask == 0)
      throw new IllegalArgumentException ("no non-zero mask");

    if (transferType != DataBuffer.TYPE_BYTE && transferType != DataBuffer.TYPE_USHORT
        && transferType != DataBuffer.TYPE_INT)
      throw new IllegalArgumentException ("invalid data type");

    // Assume DataBuffer.TYPE_BYTE.
    int numBits = 8;

    if (transferType == DataBuffer.TYPE_SHORT)
      numBits = 16;
    else if (transferType == DataBuffer.TYPE_INT)
      numBits = 32;

    return new ImageTypeSpecifier (new DirectColorModel (colorSpace,
                                                         numBits,
                                                         redMask,
                                                         greenMask,
                                                         blueMask,
                                                         alphaMask,
                                                         isAlphaPremultiplied,
                                                         transferType),
                                   new MultiPixelPackedSampleModel (transferType,
                                                                    1, 1, numBits));
  }

  /**
   * Get the number of bits per sample in the given band.
   *
   * @param band the band from which to get the number of bits
   *
   * @return the number of bits in the given band
   *
   * @exception IllegalArgumentException if band is out-of-bounds
   */
  public int getBitsPerBand (int band)
  {
    if (band < 0 || band > sampleModel.getNumBands())
      throw new IllegalArgumentException ("band out-of-bounds");

    return sampleModel.getSampleSize (band);
  }

  /**
   * Get the buffered image constant specified by this image type
   * specifier.
   *
   * @return a buffered image constant
   */
  public int getBufferedImageType ()
  {
    // FIXME:
    return BufferedImage.TYPE_INT_RGB;
  }

  /**
   * Create a sample model that is compatible with the one specified
   * by this image type specifier, with the given dimensions.
   *
   * @param width the width of the returned sample model
   * @param height the height of the returned sample model
   *
   * @return a sample model compatible with the one in this image type
   * specifier, with the given dimensions
   *
   * @exception IllegalArgumentException if either width or height is
   * less than or equal to 0
   * @exception IllegalArgumentException if width * height is greater
   * than Intere.MAX_VALUE
   */
  public SampleModel getSampleModel (int width, int height)
  {
    if (width <= 0 || height <= 0)
      throw new IllegalArgumentException ("invalid dimension");

    // test for overflow
    if (width * height < Math.min (width, height))
      throw new IllegalArgumentException ("width * height > Integer.MAX_VALUE");

    return sampleModel.createCompatibleSampleModel (width, height);
  }

  /**
   * Get the color model specified by this image type specifier.
   *
   * @return the color model
   */
  public ColorModel getColorModel()
  {
    return colorModel;
  }

  /**
   * Get the number of bands specified by this image type specifier's
   * sample model.
   *
   * @return the number of bands in the sample model
   */
  public int getNumBands()
  {
    return sampleModel.getNumBands();
  }

  /**
   * Get the number of components specified by this image type
   * specifier's color model.
   *
   * @return the number of color components per pixel
   */
  public int getNumComponents()
  {
    return colorModel.getNumComponents();
  }

  /**
   * Get the sample model specified by this image type specifier.
   *
   * @return the sample model
   */
  public SampleModel getSampleModel()
  {
    return sampleModel;
  }
}
