/* BufferedImage.java --
   Copyright (C) 2000, 2002, 2003, 2004, 2005, 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.ComponentDataBlitOp;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.util.Hashtable;
import java.util.Vector;

/**
 * A buffered image always starts at coordinates (0, 0).
 *
 * The buffered image is not subdivided into multiple tiles. Instead,
 * the image consists of one large tile (0,0) with the width and
 * height of the image. This tile is always considered to be checked
 * out.
 * 
 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
 */
public class BufferedImage extends Image
  implements WritableRenderedImage, Transparency
{
  public static final int TYPE_CUSTOM         =  0,
                          TYPE_INT_RGB        =  1,
                          TYPE_INT_ARGB       =  2,
                          TYPE_INT_ARGB_PRE   =  3,
                          TYPE_INT_BGR        =  4,
                          TYPE_3BYTE_BGR      =  5,
                          TYPE_4BYTE_ABGR     =  6,
                          TYPE_4BYTE_ABGR_PRE =  7,
                          TYPE_USHORT_565_RGB =  8,
                          TYPE_USHORT_555_RGB =  9,
                          TYPE_BYTE_GRAY      = 10,
                          TYPE_USHORT_GRAY    = 11,
                          TYPE_BYTE_BINARY    = 12,
                          TYPE_BYTE_INDEXED   = 13;
  
  static final int[] bits3 = { 8, 8, 8 };
  static final int[] bits4 = { 8, 8, 8, 8 };
  static final int[] bits1byte = { 8 };
  static final int[] bits1ushort = { 16 };
  
  static final int[] masks_int = { 0x00ff0000,
				   0x0000ff00,
				   0x000000ff,
				   DataBuffer.TYPE_INT };
  static final int[] masks_565 = { 0xf800,
				   0x07e0,
				   0x001f,
				   DataBuffer.TYPE_USHORT};
  static final int[] masks_555 = { 0x7c00,
				   0x03e0,
				   0x001f,
				   DataBuffer.TYPE_USHORT};

  Vector observers;
  
  /**
   * Creates a new <code>BufferedImage</code> with the specified width, height
   * and type.  Valid <code>type</code> values are:
   * 
   * <ul>
   *   <li>{@link #TYPE_INT_RGB}</li>
   *   <li>{@link #TYPE_INT_ARGB}</li>
   *   <li>{@link #TYPE_INT_ARGB_PRE}</li>
   *   <li>{@link #TYPE_INT_BGR}</li>
   *   <li>{@link #TYPE_3BYTE_BGR}</li>
   *   <li>{@link #TYPE_4BYTE_ABGR}</li>
   *   <li>{@link #TYPE_4BYTE_ABGR_PRE}</li>
   *   <li>{@link #TYPE_USHORT_565_RGB}</li>
   *   <li>{@link #TYPE_USHORT_555_RGB}</li>
   *   <li>{@link #TYPE_BYTE_GRAY}</li>
   *   <li>{@link #TYPE_USHORT_GRAY}</li>
   *   <li>{@link #TYPE_BYTE_BINARY}</li>
   *   <li>{@link #TYPE_BYTE_INDEXED}</li>
   * </ul>
   * 
   * @param w  the width (must be > 0).
   * @param h  the height (must be > 0).
   * @param type  the image type (see the list of valid types above).
   * 
   * @throws IllegalArgumentException if <code>w</code> or <code>h</code> is
   *     less than or equal to zero.
   * @throws IllegalArgumentException if <code>type</code> is not one of the
   *     specified values.
   */
  public BufferedImage(int w, int h, int type)
  {
    ColorModel cm = null;
    
    boolean alpha = false;
    boolean premultiplied = false;
    switch (type)
      {
      case TYPE_4BYTE_ABGR_PRE:
      case TYPE_INT_ARGB_PRE:
	premultiplied = true;
	// fall through
      case TYPE_INT_ARGB:
      case TYPE_4BYTE_ABGR:
	alpha = true;
      }
	
    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
    switch (type)
      {
      case TYPE_INT_RGB:
      case TYPE_INT_ARGB:
      case TYPE_INT_ARGB_PRE:
      case TYPE_USHORT_565_RGB:
      case TYPE_USHORT_555_RGB:
	int[] masks = null;
	switch (type)
	  {
	  case TYPE_INT_RGB:
	  case TYPE_INT_ARGB:
	  case TYPE_INT_ARGB_PRE:
	    masks = masks_int;
	    break;
	  case TYPE_USHORT_565_RGB:
	    masks = masks_565;
	    break;
	  case TYPE_USHORT_555_RGB:
	    masks = masks_555;
	    break;
	  }
	
	cm = new DirectColorModel(cs,
				  32, // 32 bits in an int
				  masks[0], // r
				  masks[1], // g
				  masks[2], // b
				  alpha ? 0xff000000 : 0,
				  premultiplied,
				  masks[3] // data type
				  );
	break;
	
      case TYPE_INT_BGR:
	String msg =
	  "FIXME: Programmer is confused. Why (and how) does a " +
	  "TYPE_INT_BGR image use ComponentColorModel to store " +
	  "8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " +
	  "is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?";
	throw new UnsupportedOperationException(msg);
	
      case TYPE_3BYTE_BGR:
      case TYPE_4BYTE_ABGR:
      case TYPE_4BYTE_ABGR_PRE:
      case TYPE_BYTE_GRAY:
      case TYPE_USHORT_GRAY:
	int[] bits = null;
	int dataType = DataBuffer.TYPE_BYTE;
	switch (type) {
	case TYPE_3BYTE_BGR:
	  bits = bits3;
	  break;
	case TYPE_4BYTE_ABGR:
	case TYPE_4BYTE_ABGR_PRE:
	  bits = bits4;
	  break;
        case TYPE_BYTE_GRAY:
          bits = bits1byte;
          cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
          break;
        case TYPE_USHORT_GRAY:
          bits = bits1ushort;
          cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
          dataType = DataBuffer.TYPE_USHORT;
          break;
	}
	cm = new ComponentColorModel(cs, bits, alpha, premultiplied,
				     alpha ?
				     Transparency.TRANSLUCENT:
				     Transparency.OPAQUE,
				     dataType);
	break;
      case TYPE_BYTE_BINARY:
	byte[] vals = { 0, (byte) 0xff };
	cm = new IndexColorModel(8, 2, vals, vals, vals);
	break;
      case TYPE_BYTE_INDEXED:
	String msg2 = "type not implemented yet";
	throw new UnsupportedOperationException(msg2);
	// FIXME: build color-cube and create color model
      default:
        throw new IllegalArgumentException("Unknown image type " + type);
      }
    
    init(cm,
	 cm.createCompatibleWritableRaster(w, h),
	 premultiplied,
	 null, // no properties
	 type
	 );
  }

  public BufferedImage(int w, int h, int type,
		       IndexColorModel indexcolormodel)
  {
    if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
      throw new IllegalArgumentException("type must be binary or indexed");

    init(indexcolormodel,
	 indexcolormodel.createCompatibleWritableRaster(w, h),
	 false, // not premultiplied (guess)
	 null, // no properties
	 type);
  }

  public BufferedImage(ColorModel colormodel, 
		       WritableRaster writableraster,
		       boolean premultiplied,
		       Hashtable properties)
  {
    init(colormodel, writableraster, premultiplied, properties,
	 TYPE_CUSTOM);
    // TODO: perhaps try to identify type?
  }
 
  WritableRaster raster;
  ColorModel colorModel;
  Hashtable properties;
  boolean isPremultiplied;
  int type;
  
  private void init(ColorModel cm,
		    WritableRaster writableraster,
		    boolean premultiplied,
		    Hashtable properties,
		    int type)
  {
    raster = writableraster;
    colorModel = cm;
    this.properties = properties;
    isPremultiplied = premultiplied;
    this.type = type;
  }
    
  //public void addTileObserver(TileObserver tileobserver) {}
  
  public void coerceData(boolean premultiplied)
  {
    colorModel = colorModel.coerceData(raster, premultiplied);
  }

  public WritableRaster copyData(WritableRaster dest)
  {
    if (dest == null)
      dest = raster.createCompatibleWritableRaster(getMinX(), getMinY(),
                                                   getWidth(),getHeight());

    int x = dest.getMinX();
    int y = dest.getMinY();
    int w = dest.getWidth();
    int h = dest.getHeight();
    
    // create a src child that has the right bounds...
    WritableRaster src =
      raster.createWritableChild(x, y, w, h, x, y,
				 null  // same bands
				 );
    if (src.getSampleModel () instanceof ComponentSampleModel
        && dest.getSampleModel () instanceof ComponentSampleModel)
      // Refer to ComponentDataBlitOp for optimized data blitting:
      ComponentDataBlitOp.INSTANCE.filter(src, dest);
    else
      {
        // slower path
        int samples[] = src.getPixels (x, y, w, h, (int [])null);
        dest.setPixels (x, y, w, h, samples);
      }
    return dest;
  }

  public Graphics2D createGraphics()
  {
    GraphicsEnvironment env;
    env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
    return env.createGraphics (this);
  }

  public void flush() {
  }
  
  public WritableRaster getAlphaRaster()
  {
    return colorModel.getAlphaRaster(raster);
  }
  
  public ColorModel getColorModel()
  {
    return colorModel;
  }
  
  public Raster getData()
  {
    return copyData(null);
    /* TODO: this might be optimized by returning the same
       raster (not writable) as long as image data doesn't change. */
  }

  public Raster getData(Rectangle rectangle)
  {
    WritableRaster dest =
      raster.createCompatibleWritableRaster(rectangle);
    return copyData(dest);
  }
  
  public Graphics getGraphics()
  {
    return createGraphics();
  }

  public int getHeight()
  {
    return raster.getHeight();
  }
  
  public int getHeight(ImageObserver imageobserver)
  {
    return getHeight();
  }
    
  public int getMinTileX()
  {
    return 0;
  }
  
  public int getMinTileY()
  {
    return 0;
  }

  public int getMinX()
  {
    return 0; 
  }

  public int getMinY() 
  {
    return 0;
  }
  
  public int getNumXTiles()
  {
    return 1;
  }

  public int getNumYTiles()
  {
	return 1;
  }

  /**
   * Returns the value of the specified property, or 
   * {@link Image#UndefinedProperty} if the property is not defined.
   * 
   * @param string  the property key (<code>null</code> not permitted).
   * 
   * @return The property value.
   * 
   * @throws NullPointerException if <code>string</code> is <code>null</code>.
   */
  public Object getProperty(String string)
  {
    if (string == null)
      throw new NullPointerException("The property name cannot be null.");
    Object result = Image.UndefinedProperty;
    if (properties != null)
      {
        Object v = properties.get(string);
        if (v != null)
          result = v;
      }
    return result;
  }

  public Object getProperty(String string, ImageObserver imageobserver)
  {
    return getProperty(string);
  }

  /**
   * Returns <code>null</code> always.
   * 
   * @return <code>null</code> always.
   */
  public String[] getPropertyNames()
  {
    // This method should always return null, see:
    // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4640609
    return null;
  }

  public int getRGB(int x, int y)
  {
    Object rgbElem = raster.getDataElements(x, y,
					    null // create as needed
					    );
    return colorModel.getRGB(rgbElem);
  }
    
  public int[] getRGB(int startX, int startY, int w, int h,
		      int[] rgbArray,
		      int offset, int scanlineStride)
  {
    if (rgbArray == null)
    {
      /*
	000000000000000000
	00000[#######-----   [ = start
	-----########-----   ] = end
	-----#######]00000
	000000000000000000  */
      int size = (h-1)*scanlineStride + w;
      rgbArray = new int[size];
    }
	
    int endX = startX + w;
    int endY = startY + h;
    
    /* *TODO*:
       Opportunity for optimization by examining color models...
       
       Perhaps wrap the rgbArray up in a WritableRaster with packed
       sRGB color model and perform optimized rendering into the
       array. */

    Object rgbElem = null;
    for (int y=startY; y<endY; y++)
      {
	int xoffset = offset;
	for (int x=startX; x<endX; x++)
	  {
	    int rgb;
	    rgbElem = raster.getDataElements(x, y, rgbElem);
	    rgb = colorModel.getRGB(rgbElem);
	    rgbArray[xoffset++] = rgb;
	  }
	offset += scanlineStride;
      }
    return rgbArray;
  }

  public WritableRaster getRaster()
  {
    return raster;
  }
  
  public SampleModel getSampleModel()
  {
    return raster.getSampleModel();
  }
    
  public ImageProducer getSource()
  {
    return new ImageProducer() {
        
	Vector consumers = new Vector();

        public void addConsumer(ImageConsumer ic)
        {
	  if(!consumers.contains(ic))
	    consumers.add(ic);
        }

        public boolean isConsumer(ImageConsumer ic)
        {
          return consumers.contains(ic);
        }

        public void removeConsumer(ImageConsumer ic)
        {
	  consumers.remove(ic);
        }

        public void startProduction(ImageConsumer ic)
        {
          int x = 0;
          int y = 0;
          int width = getWidth();
          int height = getHeight();
          int stride = width;
          int offset = 0;
          int[] pixels = getRGB(x, y, 
                                width, height, 
                                (int[])null, offset, stride);
          // We already convert the color to RGB in the getRGB call, so
          // we pass a simple RGB color model to the consumers.
          ColorModel model = new DirectColorModel(32, 0xff0000, 0xff00, 0xff,
                                                  0xff000000);

          consumers.add(ic);

	  for(int i=0;i<consumers.size();i++)
            {
              ImageConsumer c = (ImageConsumer) consumers.elementAt(i);
              c.setHints(ImageConsumer.SINGLEPASS);
              c.setDimensions(getWidth(), getHeight());
              c.setPixels(x, y, width, height, model, pixels, offset, stride);
              c.imageComplete(ImageConsumer.STATICIMAGEDONE);
            }
        }

        public void requestTopDownLeftRightResend(ImageConsumer ic)
        {
          startProduction(ic);
        }

      };
  }
  
  public Vector getSources()
  {
    return null;
  }
  
  public BufferedImage getSubimage(int x, int y, int w, int h)
  {
    WritableRaster subRaster = 
      getRaster().createWritableChild(x, y, w, h, 0, 0, null);
    
    return new BufferedImage(getColorModel(),
			     subRaster,
			     isPremultiplied,
			     properties);
  }

  public Raster getTile(int tileX, int tileY)
  {
    return getWritableTile(tileX, tileY);
  }
    
  public int getTileGridXOffset()
  {
    return 0; // according to javadocs
  }

  public int getTileGridYOffset()
  {
    return 0; // according to javadocs
  }

  public int getTileHeight()
  {
    return getHeight(); // image is one big tile
  }

  public int getTileWidth()
  {
    return getWidth(); // image is one big tile
  }

  public int getType()
  {
    return type;
  }

  public int getWidth()
  {
    return raster.getWidth();
  }

  public int getWidth(ImageObserver imageobserver)
  {
    return getWidth();
  }

  public WritableRaster getWritableTile(int tileX, int tileY)
  {
    isTileWritable(tileX, tileY);  // for exception
    return raster;
  }

  private static final Point[] tileIndices = { new Point() };
    
  public Point[] getWritableTileIndices()
  {
    return tileIndices;
  }

  public boolean hasTileWriters()
  {
    return true;
  }
  
  public boolean isAlphaPremultiplied()
  {
    return isPremultiplied;
  }

  public boolean isTileWritable(int tileX, int tileY)
  {
    if ((tileX != 0) || (tileY != 0))
      throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
    return true;
  }

  public void releaseWritableTile(int tileX, int tileY)
  {
    isTileWritable(tileX, tileY);  // for exception
  }

  //public void removeTileObserver(TileObserver tileobserver) {}

  public void setData(Raster src)
  {
    int x = src.getMinX();
    int y = src.getMinY();
    int w = src.getWidth();
    int h = src.getHeight();
    
    // create a dest child that has the right bounds...
    WritableRaster dest =
      raster.createWritableChild(x, y, w, h, x, y,
				 null  // same bands
				 );

    if (src.getSampleModel () instanceof ComponentSampleModel
        && dest.getSampleModel () instanceof ComponentSampleModel)

      // Refer to ComponentDataBlitOp for optimized data blitting:
      ComponentDataBlitOp.INSTANCE.filter(src, dest);
    else
      {
        // slower path
        int samples[] = src.getPixels (x, y, w, h, (int [])null);
        dest.setPixels (x, y, w, h, samples);
      }
  }

  public void setRGB(int x, int y, int argb)
  {
    Object rgbElem = colorModel.getDataElements(argb, null);
    raster.setDataElements(x, y, rgbElem);
  }
  
  public void setRGB(int startX, int startY, int w, int h,
		     int[] argbArray, int offset, int scanlineStride)
  {
    int endX = startX + w;
    int endY = startY + h;
    
    Object rgbElem = null;
    for (int y=startY; y<endY; y++)
      {
	int xoffset = offset;
	for (int x=startX; x<endX; x++)
	  {
	    int argb = argbArray[xoffset++];
	    rgbElem = colorModel.getDataElements(argb, rgbElem);
	    raster.setDataElements(x, y, rgbElem);
	  }
	offset += scanlineStride;    
      }
  }
    
  public String toString()
  {
    StringBuffer buf;

    buf = new StringBuffer(/* estimated length */ 120);
    buf.append("BufferedImage@");
    buf.append(Integer.toHexString(hashCode()));
    buf.append(": type=");
    buf.append(type);
    buf.append(' ');
    buf.append(colorModel);
    buf.append(' ');
    buf.append(raster);

    return buf.toString();
  }


  /**
   * Adds a tile observer. If the observer is already present, it receives
   * multiple notifications.
   *
   * @param to The TileObserver to add.
   */
  public void addTileObserver (TileObserver to)
  {
    if (observers == null)
      observers = new Vector ();
	
    observers.add (to);
  }
	
  /**
   * Removes a tile observer. If the observer was not registered,
   * nothing happens. If the observer was registered for multiple
   * notifications, it is now registered for one fewer notification.
   *
   * @param to The TileObserver to remove.
   */
  public void removeTileObserver (TileObserver to)
  {
    if (observers == null)
      return;
	
    observers.remove (to);
  }

  /**
   * Return the transparency type.
   *
   * @return One of {@link #OPAQUE}, {@link #BITMASK}, or {@link #TRANSLUCENT}.
   * @see Transparency#getTransparency()
   * @since 1.5
   */
  public int getTransparency()
  {
    return colorModel.getTransparency();
  }
}
