/* ColorModel.java --
   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2006  Free Software Foundation

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 java.awt.image;

import gnu.java.awt.Buffers;

import java.awt.Point;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.util.Arrays;

/**
 * A color model operates with colors in several formats:
 *
 * <ul>
 * <li>normalized: component samples are in range [0.0, 1.0].</li>
 *
 * <li>color model pixel value: all the color component samples for a
 * sigle pixel packed/encoded in a way natural for the color
 * model.</li>
 *
 * <li>color model pixel int value: only makes sense if the natural
 * encoding of a single pixel can fit in a single int value.</li>
 *
 * <li>array of transferType containing a single pixel: the pixel is
 * encoded in the natural way of the color model, taking up as many
 * array elements as needed.</li>
 *
 * <li>sRGB pixel int value: a pixel in sRGB color space, encoded in
 * default 0xAARRGGBB format, assumed not alpha premultiplied.</li>
 * 
 * <li>single [0, 255] scaled int samples from default sRGB color
 * space. These are always assumed to be alpha non-premultiplied.</li>
 *
 * <li>arrays of unnormalized component samples of single pixel: these
 * samples are scaled and multiplied according to the color model, but
 * is otherwise not packed or encoded. Each element of the array is one
 * separate component sample. The color model only operate on the
 * components from one pixel at a time, but using offsets, allows
 * manipulation of arrays that contain the components of more than one
 * pixel.</li>
 *
 * </ul>
 *
 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
 * @author C. Brian Jones (cbj@gnu.org)
 */
public abstract class ColorModel implements Transparency
{
  protected int pixel_bits;
  protected int transferType;

  int[] bits;
  ColorSpace cspace;
  int transparency;
  boolean hasAlpha;
  boolean isAlphaPremultiplied;

  /**
   * The standard color model for the common sRGB.
   */
  private static final ColorModel S_RGB_MODEL = new SRGBColorModel();

  static int[] nArray(int value, int times)
  {
    int[] array = new int[times];
    java.util.Arrays.fill(array, value);
    return array;
  }

  static byte[] nArray(byte value, int times)
  {
    byte[] array = new byte[times];
    java.util.Arrays.fill(array, value);
    return array;
  } 

  /**
   * Constructs the default color model.  The default color model 
   * can be obtained by calling <code>getRGBdefault</code> of this
   * class.
   * @param bits the number of bits wide used for bit size of pixel values
   */
  public ColorModel(int bits)
  {
    this(bits * 4, // total bits, sRGB, four channels
	 nArray(bits, 4), // bits for each channel
	 ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
	 true, // has alpha
	 false, // not premultiplied
	 TRANSLUCENT,
	 Buffers.smallestAppropriateTransferType(bits * 4));
  }

  /**
   * Constructs a ColorModel that translates pixel values to
   * color/alpha components.
   *
   * @exception IllegalArgumentException If the length of the bit array is less
   * than the number of color or alpha components in this ColorModel, or if the
   * transparency is not a valid value, or if the sum of the number of bits in
   * bits is less than 1 or if any of the elements in bits is less than 0.
   */
  protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
		       boolean hasAlpha, boolean isAlphaPremultiplied,
		       int transparency, int transferType)
  {
    int bits_sum = 0;
    for (int i = 0; i < bits.length; i++)
      {
        if (bits [i] < 0)
          throw new IllegalArgumentException ();

        bits_sum |= bits [i];
      }
    
    if ((bits.length < cspace.getNumComponents())
        || (bits_sum < 1))
      throw new IllegalArgumentException ();

    this.pixel_bits = pixel_bits;
    this.bits = bits;
    this.cspace = cspace;
    this.hasAlpha = hasAlpha;
    this.isAlphaPremultiplied = isAlphaPremultiplied;
    this.transparency = transparency;
    this.transferType = transferType;
  }
  
  public void finalize()
  {
    // Do nothing here.
  }

  /**
   * Returns the default color model which in Sun's case is an instance
   * of <code>DirectColorModel</code>.
   */
  public static ColorModel getRGBdefault()
  {
    return S_RGB_MODEL;
  }

  public final boolean hasAlpha()
  {
    return hasAlpha;
  }

  public final boolean isAlphaPremultiplied()
  {
    return isAlphaPremultiplied;
  }

  /**
   * Get get number of bits wide used for the bit size of pixel values
   */
  public int getPixelSize()
  {
    return pixel_bits;
  }
    
  public int getComponentSize(int componentIdx)
  {
    return bits[componentIdx];
  }
    
  public int[] getComponentSize()
  {
    return bits;
  }

  public int getTransparency()
  {
    return transparency;
  }

  public int getNumComponents()
  {
    return getNumColorComponents() + (hasAlpha ? 1 : 0);
  }

  public int getNumColorComponents()
  {
    return cspace.getNumComponents();
  }

  /**
   * Converts pixel value to sRGB and extract red int sample scaled
   * to range [0, 255].
   *
   * @param pixel pixel value that will be interpreted according to
   * the color model, (assumed alpha premultiplied if color model says
   * so.)
   *
   * @return red sample scaled to range [0, 255], from default color
   * space sRGB, alpha non-premultiplied.
   */
  public abstract int getRed(int pixel);

  /**
   * Converts pixel value to sRGB and extract green int sample
   * scaled to range [0, 255].
   *
   * @see #getRed(int)
   */
  public abstract int getGreen(int pixel);
    
  /**
   * Converts pixel value to sRGB and extract blue int sample
   * scaled to range [0, 255].
   *
   * @see #getRed(int)
   */
  public abstract int getBlue(int pixel);

  /**
   * Extract alpha int sample from pixel value, scaled to [0, 255].
   *
   * @param pixel pixel value that will be interpreted according to
   * the color model.
   *
   * @return alpha sample, scaled to range [0, 255].
   */
  public abstract int getAlpha(int pixel);

  /**
   * Converts a pixel int value of the color space of the color
   * model to a sRGB pixel int value.
   *
   * This method is typically overriden in subclasses to provide a
   * more efficient implementation.
   * 
   * @param pixel pixel value that will be interpreted according to
   * the color model.
   *
   * @return a pixel in sRGB color space, encoded in default
   * 0xAARRGGBB format.  */
  public int getRGB(int pixel)
  {
    return 
      ((getAlpha(pixel) & 0xff) << 24) |
      ((  getRed(pixel) & 0xff) << 16) |
      ((getGreen(pixel) & 0xff) <<  8) |
      (( getBlue(pixel) & 0xff) <<  0);
  }
  

  /**
   * In this color model we know that the whole pixel value will
   * always be contained within the first element of the pixel
   * array.
   */
  final int getPixelFromArray(Object inData) {
    DataBuffer data =
      Buffers.createBufferFromData(transferType, inData, 1);
    Object da = Buffers.getData(data);

    return data.getElem(0);
  }

  /** 
   * Converts pixel in the given array to sRGB and extract blue int
   * sample scaled to range [0-255].
   *
   * This method is typically overriden in subclasses to provide a
   * more efficient implementation.
   * 
   * @param inData array of transferType containing a single pixel.  The
   * pixel should be encoded in the natural way of the color model.
   */
  public int getRed(Object inData)
  {
    return getRed(getPixelFromArray(inData));
  }

  /**
   * @see #getRed(Object)
   */
  public int getGreen(Object inData)
  {
    return getGreen(getPixelFromArray(inData));
  }

  /**
   * @see #getRed(Object)
   */
  public int getBlue(Object inData) {
    return getBlue(getPixelFromArray(inData));
  }

  /**
   * @see #getRed(Object)
   */
  public int getAlpha(Object inData) {
    return getAlpha(getPixelFromArray(inData));
  }

  /**
   * Converts a pixel in the given array of the color space of the
   * color model to an sRGB pixel int value.
   *
   * <p>This method performs the inverse function of
   * <code>getDataElements(int rgb, Object pixel)</code>.
   * I.e. <code>(rgb == cm.getRGB(cm.getDataElements(rgb,
   * null)))</code>.
   *
   * @param inData array of transferType containing a single pixel. The
   * pixel should be encoded in the natural way of the color model.
   *
   * @return a pixel in sRGB color space, encoded in default
   * 0xAARRGGBB format.
   *
   * @see #getDataElements(int, Object)
   */
  public int getRGB(Object inData)
  {
    return 
      ((getAlpha(inData) & 0xff) << 24) |
      ((  getRed(inData) & 0xff) << 16) |
      ((getGreen(inData) & 0xff) <<  8) |
      (( getBlue(inData) & 0xff) <<  0);
  }

  /**
   * Converts an sRGB pixel int value to an array containing a
   * single pixel of the color space of the color model.
   * 
   * <p>This method performs the inverse function of
   * <code>getRGB(Object inData)</code>.
   *
   * Outline of conversion process:
   *
   * <ol>
   *
   * <li>Convert rgb to normalized [0.0, 1.0] sRGB values.</li>
   *
   * <li>Convert to color space components using fromRGB in
   * ColorSpace.</li>
   *
   * <li>If color model has alpha and should be premultiplied,
   * multiply color space components with alpha value</li>
   *
   * <li>Scale the components to the correct number of bits.</li>
   *
   * <li>Arrange the components in the output array</li>
   * 
   * </ol>
   *
   * @param rgb The color to be converted to dataElements.  A pixel
   * in sRGB color space, encoded in default 0xAARRGGBB format,
   * assumed not alpha premultiplied.
   *
   * @param pixel to avoid needless creation of arrays, an array to
   * use to return the pixel can be given. If null, a suitable array
   * will be created.
   *
   * @return An array of transferType values representing the color,
   * in the color model format. The color model defines whether the
   *  
   * @see #getRGB(Object)
   */
  public Object getDataElements(int rgb, Object pixel)
  {
    // subclasses has to implement this method.
    throw new UnsupportedOperationException();
  }

  /**
   * Fills an array with the unnormalized component samples from a
   * pixel value. I.e. decompose the pixel, but not perform any
   * color conversion. 
   *
   * This method is typically overriden in subclasses to provide a
   * more efficient implementation.
   * 
   * @param pixel pixel value encoded according to the color model.
   *
   * @return arrays of unnormalized component samples of single
   * pixel.  The scale and multiplication state of the samples are
   * according to the color model. Each component sample is stored
   * as a separate element in the array.
   */
  public int[] getComponents(int pixel, int[] components, int offset)
  {
    // subclasses has to implement this method.
    throw new UnsupportedOperationException();
  }
  
  /**
   * Fills an array with the unnormalized component samples from an
   * array of transferType containing a single pixel. I.e. decompose
   * the pixel, but not perform any color conversion.
   *
   * This method is typically overriden in subclasses to provide a
   * more efficient implementation.
   *
   * @param pixel an array of transferType containing a single pixel.  The
   * pixel should be encoded in the natural way of the color model.  If
   * this argument is not an array, as expected, a {@link ClassCastException}
   * will be thrown.
   * @param components an array that will be filled with the color component
   * of the pixel.  If this is null, a new array will be allocated
   * @param offset index into the components array at which the result
   * will be stored
   * 
   * @return arrays of unnormalized component samples of single
   * pixel.  The scale and multiplication state of the samples are
   * according to the color model. Each component sample is stored
   * as a separate element in the array.
   */
  public int[] getComponents(Object pixel, int[] components, int offset)
  {
    // subclasses has to implement this method.
    throw new UnsupportedOperationException();
  }

  /**
   * Convert normalized components to unnormalized components.
   */
  public int[] getUnnormalizedComponents(float[] normComponents,
					 int normOffset,
					 int[] components,
					 int offset)
  {
    int numComponents = getNumComponents();
    if (components == null)
    {
      components = new int[offset + numComponents];
    }
    
    for (int i=0; i<numComponents; i++)
    {
      float in = normComponents[normOffset++];
      int out = (int) (in * ((1<<getComponentSize(i)) - 1));
      components[offset++] = out;
    }
    return components;
  }

  /**
   * Convert unnormalized components to normalized components.
   */
  public float[] getNormalizedComponents(int[] components,
					 int offset,
					 float[] normComponents,
					 int normOffset)
  {
    int numComponents = getNumComponents();
    if (normComponents == null)
    {
      normComponents = new float[normOffset + numComponents];
    }

    for (int i=0; i<numComponents; i++)
    {
      float in = components[offset++];
      float out = in / ((1<<getComponentSize(i)) - 1);
      normComponents[normOffset++] = out;
    }
    return normComponents;
  }

  /**
   * Convert unnormalized components to normalized components.
   *
   * @since 1.4
   */
  public float[] getNormalizedComponents (Object pixel,
                                          float[] normComponents,
                                          int normOffset)
  {
    int[] components = getComponents(pixel, null, 0);
    return getNormalizedComponents(components, 0, normComponents, normOffset);
  }

  /**
   * Converts the unnormalized component samples from an array to a
   * pixel value. I.e. composes the pixel from component samples, but
   * does not perform any color conversion or scaling of the samples.
   * 
   * This method performs the inverse function of
   * <code>getComponents(int pixel, int[] components,
   *			       int offset)</code>. I.e.
   *
   * <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null,
   * 0), 0))</code>.
   *
   * This method is overriden in subclasses since this abstract class throws
   * UnsupportedOperationException().
   *
   * @param components Array of unnormalized component samples of single
   * pixel.  The scale and multiplication state of the samples are according
   * to the color model. Each component sample is stored as a separate element
   * in the array.
   * @param offset Position of the first value of the pixel in components.
   *
   * @return pixel value encoded according to the color model.
   */
  public int getDataElement(int[] components, int offset)
  {
    // subclasses have to implement this method.
    throw new UnsupportedOperationException();
  }

  /**
   * Converts the normalized component samples from an array to a pixel
   * value. I.e. composes the pixel from component samples, but does not
   * perform any color conversion or scaling of the samples.
   * 
   * This method is typically overriden in subclasses to provide a
   * more efficient implementation.  The method provided by this abstract
   * class converts the components to unnormalized form and returns
   * getDataElement(int[], int).
   *
   * @param components Array of normalized component samples of single pixel.
   * The scale and multiplication state of the samples are according to the
   * color model. Each component sample is stored as a separate element in the
   * array.
   * @param offset Position of the first value of the pixel in components.
   *
   * @return pixel value encoded according to the color model.
   * @since 1.4
   */
  public int getDataElement (float[] components, int offset)
  {
    return
      getDataElement(getUnnormalizedComponents(components, offset, null, 0),
		     0);
  }
  
  public Object getDataElements(int[] components, int offset, Object obj)
  {
    // subclasses have to implement this method.
    throw new UnsupportedOperationException();
  }

  /**
   * Converts the normalized component samples from an array to an array of
   * TransferType values. I.e. composes the pixel from component samples, but
   * does not perform any color conversion or scaling of the samples.
   *
   * If obj is null, a new array of TransferType is allocated and returned.
   * Otherwise the results are stored in obj and obj is returned.  If obj is
   * not long enough, ArrayIndexOutOfBounds is thrown.  If obj is not an array
   * of primitives, ClassCastException is thrown.
   * 
   * This method is typically overriden in subclasses to provide a
   * more efficient implementation.  The method provided by this abstract
   * class converts the components to unnormalized form and returns
   * getDataElement(int[], int, Object).
   *
   * @param components Array of normalized component samples of single pixel.
   * The scale and multiplication state of the samples are according to the
   * color model. Each component sample is stored as a separate element in the
   * array.
   * @param offset Position of the first value of the pixel in components.
   * @param obj Array of TransferType or null.
   *
   * @return pixel value encoded according to the color model.
   * @throws ArrayIndexOutOfBoundsException
   * @throws ClassCastException
   * @since 1.4
   */
  public Object getDataElements(float[] components, int offset, Object obj)
  {
    return
      getDataElements(getUnnormalizedComponents(components, offset, null, 0),
		      0, obj);
  }

  public boolean equals(Object obj)
  {
    if (!(obj instanceof ColorModel)) return false;

    ColorModel o = (ColorModel) obj;
    return 
      (pixel_bits == o.pixel_bits) &&
      (transferType == o.transferType) &&
      (transparency == o.transparency) &&
      (hasAlpha == o.hasAlpha) &&
      (isAlphaPremultiplied == o.isAlphaPremultiplied) &&
      Arrays.equals(bits, o.bits) &&
      (cspace.equals(o.cspace));
  }

  public final ColorSpace getColorSpace()
  {
    return cspace;
  }

  // Typically overridden
  public ColorModel coerceData(WritableRaster raster,
			       boolean isAlphaPremultiplied)
  {
    if (this.isAlphaPremultiplied == isAlphaPremultiplied)
      return this;

    int w = raster.getWidth();
    int h = raster.getHeight();
    int x = raster.getMinX();
    int y = raster.getMinY();
    int size = w*h;
    int numColors = getNumColorComponents();
    int numComponents = getNumComponents();
    int alphaScale = (1<<getComponentSize(numColors)) - 1;
    double[] pixels = raster.getPixels(x, y, w, h, (double[]) null);

    for (int i=0; i<size; i++)
      {
	double alpha = pixels[i*numComponents+numColors]*alphaScale;
	for (int c=0; c<numColors; c++)
	  {
	    int offset = i*numComponents+c;
	    if (isAlphaPremultiplied)
		pixels[offset] = pixels[offset]/alpha;
	    else
	      pixels[offset] = pixels[offset]*alpha;
	  }
      }
    
    raster.setPixels(0, 0, w, h, pixels);

    // FIXME: what can we return?
    return null;
  }
    
  /**
   * Checks if the given raster has a compatible data-layout (SampleModel).
   * @param raster The Raster to test.
   * @return true if raster is compatible.
   */ 
  public boolean isCompatibleRaster(Raster raster)
  {
    SampleModel sampleModel = raster.getSampleModel();
    return isCompatibleSampleModel(sampleModel);
  }

  // Typically overridden
  public WritableRaster createCompatibleWritableRaster(int w, int h)
  {
    return new WritableRaster(createCompatibleSampleModel(w, h),
			      new Point(0, 0));
  }

  // Typically overridden
  public SampleModel createCompatibleSampleModel(int w, int h)
  {
    throw new UnsupportedOperationException();
  }

  // Typically overridden
  public boolean isCompatibleSampleModel(SampleModel sm)
  {
    return sm.getTransferType() == transferType;
  }

  public final int getTransferType ()
  {
    return transferType;
  }

  /**
   * Subclasses must override this method if it is possible for the
   * color model to have an alpha channel.
   *
   * @return null, as per JDK 1.3 doc. Subclasses will only return
   * null if no alpha raster exists.
   */
  public WritableRaster getAlphaRaster(WritableRaster raster)
  {
    return null;
    
    /* It is a mystery to me why we couldn't use the following code...
       
       
       if (!hasAlpha()) return null;
       
       SampleModel sm = raster.getSampleModel();
       int[] alphaBand = { sm.getNumBands() - 1 };
       SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
       DataBuffer buffer = raster.getDataBuffer();
       Point origin = new Point(0, 0);
       return Raster.createWritableRaster(alphaModel, buffer, origin);
       

       ...here, and avoided overriding the method in subclasses,
       but the Sun docs state that this method always will return
       null, and that overriding is required. Oh, well.
    */
  }

  String stringParam()
  {
    return "pixel_bits=" + pixel_bits +
      ", cspace=" + cspace +
      ", transferType=" + transferType +
      ", transparency=" + transparency +
      ", hasAlpha=" + hasAlpha +
      ", isAlphaPremultiplied=" + isAlphaPremultiplied;
  }

  public String toString()
  {
    return getClass().getName() + "[" + stringParam() + "]";
  }

  /**
   * A color model optimized for standard sRGB.
   */
  private static class SRGBColorModel
    extends DirectColorModel
  {
    
    SRGBColorModel()
    {
      super(32,0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
    }

    public int getAlpha(Object inData)
    {
      return ((((int[]) inData)[0]) >> 24) & 0xFF;
    }

    public int getBlue(Object inData)
    {
      return ((((int[]) inData)[0])) & 0xFF;
    }

    public int getGreen(Object inData)
    {
      return ((((int[]) inData)[0]) >>  8) & 0xFF;
    }

    public int getRed(Object inData)
    {
      return ((((int[]) inData)[0]) >> 16) & 0xFF;
    }

    public int getRGB(Object inData)
    {
      return ((int[]) inData)[0];
    }

    public Object getDataElements(int rgb, Object pixel)
    {
      if(pixel == null)
        {
          pixel = new int[]{rgb};  
        }
      else
        {
          ((int[]) pixel)[0] = rgb;  
        }
      
      return pixel;
    }
  }
}
