/* ComponentColorModel.java --
   Copyright (C) 2000, 2002, 2004  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.color.ColorSpace;

public class ComponentColorModel extends ColorModel
{
  private static int sum(int[] values)
  {
    int sum = 0;
    for (int i=0; i<values.length; i++)
      sum += values[i];
    return sum;
  }

  public ComponentColorModel(ColorSpace colorSpace, int[] bits,
			     boolean hasAlpha,
			     boolean isAlphaPremultiplied,
			     int transparency, int transferType)
  {
    super(sum(bits), bits, colorSpace, hasAlpha, isAlphaPremultiplied,
	  transparency, transferType);
  }

  /**
   * Construct a new ComponentColorModel.
   * 
   * This constructor makes all bits of each sample significant, so for a
   * transferType of DataBuffer.BYTE, the bits per sample is 8, etc.  If
   * both hasAlpha and isAlphaPremultiplied are true, color samples are
   * assumed to be premultiplied by the alpha component.  Transparency may be
   * one of OPAQUE, BITMASK, or TRANSLUCENT. 
   * 
   * @param colorSpace The colorspace for this color model.
   * @param hasAlpha True if there is an alpha component.
   * @param isAlphaPremultiplied True if colors are already multiplied by
   * alpha.
   * @param transparency The type of alpha values.
   * @param transferType Data type of pixel sample values.
   * @since 1.4
   */
  public ComponentColorModel(ColorSpace colorSpace,
			     boolean hasAlpha,
			     boolean isAlphaPremultiplied,
			     int transparency, int transferType)
  {	
    this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
         transparency, transferType);
  }

  public int getRed(int pixel)
  {
    if (getNumComponents()>1) throw new IllegalArgumentException();
    return (int) getRGBFloat(pixel)[0];
  }

  public int getGreen(int pixel)
  {
    if (getNumComponents()>1) throw new IllegalArgumentException();
    return (int) getRGBFloat(pixel)[0];
  }
  
  public int getBlue(int pixel)
  {
    if (getNumComponents()>1) throw new IllegalArgumentException();
    return (int) getRGBFloat(pixel)[0];
  }

  public int getAlpha(int pixel)
  {
    if (getNumComponents()>1) throw new IllegalArgumentException();
    int shift = 8 - getComponentSize(getNumColorComponents());
    if (shift >= 0) return pixel << shift;
    return pixel >> (-shift);
  }
   
  public int getRGB(int pixel)
  {
    float[] rgb = getRGBFloat(pixel);
    int ret = getRGB(rgb);
    if (hasAlpha()) ret |= getAlpha(pixel) << 24;
    return ret;
  }


  /* Note, it's OK to pass a to large array to toRGB(). Extra
     elements are ignored. */
  
  private float[] getRGBFloat(int pixel)
  {
    float[] data = { pixel };
    return cspace.toRGB(data);
  }

  private float[] getRGBFloat(Object inData)
  {
    DataBuffer buffer =
    Buffers.createBufferFromData(transferType, inData,
				 getNumComponents());
    int colors = getNumColorComponents();
    float[] data = new float[colors];
    
    // FIXME: unpremultiply data that is premultiplied
    for (int i=0; i<colors; i++)
      {
	float maxValue = (1<<getComponentSize(i))-1;
	data[i] = buffer.getElemFloat(i)/maxValue; 
      }
    float[] rgb = cspace.toRGB(data);
    return rgb;
  }
  
  public int getRed(Object inData)
  {
    return (int) getRGBFloat(inData)[0]*255;
  }

  public int getGreen(Object inData)
  {
    return (int) getRGBFloat(inData)[1]*255;
  }

  public int getBlue(Object inData)
  {
    return (int) getRGBFloat(inData)[2]*255;
  }

  public int getAlpha(Object inData)
  {
    DataBuffer buffer =
      Buffers.createBufferFromData(transferType, inData,
				   getNumComponents());
    int shift = 8 - getComponentSize(getNumColorComponents());
    int alpha = buffer.getElem(getNumColorComponents());
    if (shift >= 0) return alpha << shift;
    return alpha >> (-shift);
  }

  private int getRGB(float[] rgb)
  {
    /* NOTE: We could cast to byte instead of int here. This would
       avoid bits spilling over from one bit field to
       another. But, if we assume that floats are in the [0.0,
       1.0] range, this will never happen anyway. */
    
    /* Remember to multiply BEFORE casting to int, otherwise, decimal
       point data will be lost. */
    int ret =
      (((int) (rgb[0]*255F)) << 16) |
      (((int) (rgb[1]*255F)) <<  8) |
      (((int) (rgb[2]*255F)) <<  0);
    return ret;
  }

  /**
   * @param inData pixel data of transferType, as returned by the
   * getDataElements method in SampleModel.
   */
  public int getRGB(Object inData)
  {
    float[] rgb = getRGBFloat(inData);
    int ret = getRGB(rgb);
    if (hasAlpha()) ret |= getAlpha(inData) << 24;
    return ret;
  }

  public Object getDataElements(int rgb, Object pixel)
  {
    // Convert rgb to [0.0, 1.0] sRGB values.
    float[] rgbFloats = {
      ((rgb >> 16)&0xff)/255.0F,
      ((rgb >>  8)&0xff)/255.0F,
      ((rgb >>  0)&0xff)/255.0F
    };

    // Convert from rgb to color space components.
    float[] data = cspace.fromRGB(rgbFloats);
    DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
					     getNumComponents());
    int numColors = getNumColorComponents();
    
    if (hasAlpha())
      {
	float alpha = ((rgb >> 24)&0xff)/255.0F;
	
	/* If color model has alpha and should be premultiplied, multiply
	   color space components with alpha value. */
	if (isAlphaPremultiplied()) {
	  for (int i=0; i<numColors; i++)
	    data[i] *= alpha;
	}
	// Scale the alpha sample to the correct number of bits.
	alpha *= (1<<(bits[numColors]-1));
	// Arrange the alpha sample in the output array.
	buffer.setElemFloat(numColors, alpha);
      }
    for (int i=0; i<numColors; i++)
      {
	// Scale the color samples to the correct number of bits.
	float value = data[i]*(1<<(bits[i]-1));
	// Arrange the color samples in the output array.
	buffer.setElemFloat(i, value);
      }
    return Buffers.getData(buffer);
  }

  public int[] getComponents(int pixel, int[] components, int offset)
  {
    if (getNumComponents()>1) throw new IllegalArgumentException();
    if (components == null)
    components = new int[getNumComponents() + offset];
    components[offset] = pixel;
    return components;
  }

  public int[] getComponents(Object pixel, int[] components, int offset)
  {
    DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
					     getNumComponents());
    int numComponents = getNumComponents();

    if (components == null)
      components = new int[numComponents + offset];

    for (int i=0; i<numComponents; i++)
      components[offset++] = buffer.getElem(i);

    return components;
  }

  public int getDataElement(int[] components, int offset)
  {
    if (getNumComponents()>1) throw new IllegalArgumentException();
    return components[offset];
  }

  public Object getDataElements(int[] components, int offset, Object obj)
  {
    DataBuffer buffer = Buffers.createBuffer(transferType, obj,
					     getNumComponents());
    int numComponents = getNumComponents();

    for (int i=0; i<numComponents; i++)
      buffer.setElem(i, components[offset++]);

    return Buffers.getData(buffer);
  }

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

    /* TODO: provide better implementation based on the
       assumptions we can make due to the specific type of the
       color model. */
    super.coerceData(raster, isAlphaPremultiplied);
    
    return new ComponentColorModel(cspace, bits, hasAlpha(),
				   isAlphaPremultiplied, // argument
				   transparency, transferType);
  }

  public boolean isCompatibleRaster(Raster raster)
  {
    return super.isCompatibleRaster(raster);
    // FIXME: Should we test something more here? (Why override?)
  }

  public WritableRaster createCompatibleWritableRaster(int w, int h)
  {
    SampleModel sm = createCompatibleSampleModel(w, h);
    Point origin = new Point(0, 0);
    return Raster.createWritableRaster(sm, origin);
  }


  /**
   * Creates a <code>SampleModel</code> whose arrangement of pixel
   * data is compatible to this <code>ColorModel</code>.
   *
   * @param w the number of pixels in the horizontal direction.
   * @param h the number of pixels in the vertical direction.
   */
  public SampleModel createCompatibleSampleModel(int w, int h)
  {
    int pixelStride, scanlineStride;
    int[] bandOffsets;

    pixelStride = getNumComponents();
    scanlineStride = pixelStride * w;

    /* We might be able to re-use the same bandOffsets array among
     * multiple calls to this method. However, this optimization does
     * not seem worthwile because setting up descriptive data
     * structures (such as SampleModels) is neglectible in comparision
     * to shuffling around masses of pixel data.
     */
    bandOffsets = new int[pixelStride];
    for (int i = 0; i < pixelStride; i++)
      bandOffsets[i] = i;

    /* FIXME: Think about whether it would make sense to return the
     * possibly more efficient PixelInterleavedSampleModel for other
     * transferTypes as well. It seems unlikely that this would break
     * any user applications, so the Mauve tests on this method
     * might be too restrictive.
     */
    switch (transferType)
      {
      case DataBuffer.TYPE_BYTE:
      case DataBuffer.TYPE_USHORT:
        return new PixelInterleavedSampleModel(transferType, w, h,
                                               pixelStride,
                                               scanlineStride,
                                               bandOffsets);

      default:
        return new ComponentSampleModel(transferType, w, h,
                                        pixelStride,
                                        scanlineStride,
                                        bandOffsets);
      }
  }


  public boolean isCompatibleSampleModel(SampleModel sm)
  {
    return 
      (sm instanceof ComponentSampleModel) &&
      super.isCompatibleSampleModel(sm);
  }

  public WritableRaster getAlphaRaster(WritableRaster raster)
  {
    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);
  }
    
  public boolean equals(Object obj)
  {
    if (!(obj instanceof ComponentColorModel)) return false;
    return super.equals(obj);
  }
}
