/* 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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);
  }
}
