/* 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.Buffers;
import gnu.java.awt.ClasspathGraphicsEnvironment;
import gnu.java.awt.ComponentDataBlitOp;
import gnu.java.lang.CPStringBuilder;

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;
  
  /**
   * Vector of TileObservers (or null)
   */
  Vector<TileObserver> tileObservers;
  
  /**
   * The image's WritableRaster
   */
  WritableRaster raster;

  /**
   * The associated ColorModel
   */
  ColorModel colorModel;

  /**
   * The image's properties (or null)
   */
  Hashtable properties;

  /**
   * Whether alpha is premultiplied
   */
  boolean isPremultiplied;

  /**
   * The predefined type, if any.
   */
  int type;

  /**
   * 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 width the width (must be > 0).
   * @param height the height (must be > 0).
   * @param type  the image type (see the list of valid types above).
   * 
   * @throws IllegalArgumentException if <code>width</code> or
   *     <code>height</code> is less than or equal to zero.
   * @throws IllegalArgumentException if <code>type</code> is not one of the
   *     specified values.
   */
  public BufferedImage(int width, int height, int type)
  {
    SampleModel sm = null;
    ColorModel cm = null;
    boolean premultiplied = (type == BufferedImage.TYPE_INT_ARGB_PRE
                            || type == BufferedImage.TYPE_4BYTE_ABGR_PRE);

    switch( type )
      {
      case BufferedImage.TYPE_INT_RGB:
        sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT, 
                                               width, height,
                                               new int[]{ 0x00FF0000, 
                                                          0x0000FF00, 
                                                          0x000000FF } ) ;
        cm = new DirectColorModel( 24, 0xff0000, 0xff00, 0xff );
        break;
	
      case BufferedImage.TYPE_3BYTE_BGR:
        sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_BYTE,
                                              width, height,
                                              3, width * 3, 
                                              new int[]{ 2, 1, 0 } );
        cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                                     false, false,
                                     BufferedImage.OPAQUE,
                                     DataBuffer.TYPE_BYTE);
        break;

      case BufferedImage.TYPE_INT_ARGB:
      case BufferedImage.TYPE_INT_ARGB_PRE:
        sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT, 
                                               width, height,
                                               new int[]{ 0x00FF0000, 
                                                          0x0000FF00, 
                                                          0x000000FF, 
                                                          0xFF000000 } );
        if (premultiplied)
          cm = new DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB),
                                     32, 0xff0000, 0xff00, 0xff, 0xff000000,
                                     true,
                                     Buffers.smallestAppropriateTransferType(32));
        else
          cm = new DirectColorModel( 32, 0xff0000, 0xff00, 0xff, 0xff000000 );
        
        break;

      case BufferedImage.TYPE_4BYTE_ABGR:
      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
        sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, 
                                             width, height,
                                             4, 4*width,
                                             new int[]{3, 2, 1, 0});
        cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                                     true, premultiplied,
                                     BufferedImage.TRANSLUCENT,
                                     DataBuffer.TYPE_BYTE);
        break;

      case BufferedImage.TYPE_INT_BGR:
        sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT, 
                                               width, height,
                                               new int[]{ 0x000000FF, 
                                                          0x0000FF00, 
                                                          0x00FF0000 } ) ;
        cm = new DirectColorModel( 24, 0xff, 0xff00, 0xff0000 );
        break;

      case BufferedImage.TYPE_USHORT_565_RGB:
        sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
                                               width, height,
                                               new int[]{ 0xF800, 
                                                          0x7E0, 
                                                          0x1F } ) ;
        cm = new DirectColorModel( 16, 0xF800, 0x7E0, 0x1F );
        break;
        
      case BufferedImage.TYPE_USHORT_555_RGB:
        sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
                                               width, height,
                                               new int[]{ 0x7C00, 
                                                          0x3E0, 
                                                          0x1F } ) ;
        cm = new DirectColorModel( 15, 0x7C00, 0x3E0, 0x1F );
        break;

      case BufferedImage.TYPE_BYTE_INDEXED:
        cm = createDefaultIndexedColorModel( false );

      case BufferedImage.TYPE_BYTE_GRAY:
        sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_BYTE,
                                              width, height,
                                              1, width, new int[]{ 0 } );
        break;

      case BufferedImage.TYPE_USHORT_GRAY:
        sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_USHORT,
                                              width, height,
                                              1, width, new int[]{ 0 } );
        break;

      case BufferedImage.TYPE_BYTE_BINARY:
        cm = createDefaultIndexedColorModel( true );
        sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, 
                                             width, height, 1);
        break;

      default:
        sm = null;
      }

    if( sm == null )
      throw new IllegalArgumentException("Unknown predefined image type.");
    
    if( cm == null ) // only for the grayscale types 
      {
        int buftype;
        int[] bits = new int[1];
        if( type == BufferedImage.TYPE_BYTE_GRAY )
          {
            buftype = DataBuffer.TYPE_BYTE;
            bits[0] = 8;
          }
        else
          {
            buftype = DataBuffer.TYPE_USHORT;
            bits[0] = 16;
          }
        ColorSpace graySpace = ColorSpace.getInstance( ColorSpace.CS_GRAY );
        
        cm = new ComponentColorModel( graySpace, bits, false, false, 
                                      Transparency.OPAQUE, buftype );
      }

    WritableRaster rst = null;
    
    // Attempt to create an accelerated backend for this image
    GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
    if (env instanceof ClasspathGraphicsEnvironment)
      rst = ((ClasspathGraphicsEnvironment)env).createRaster(cm, sm);
    
    // Default to a standard Java raster & databuffer if needed
    if (rst == null)
      rst = Raster.createWritableRaster(sm, new Point( 0, 0 ) );
    
    init(cm, rst, 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 TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED");
    if( indexcolormodel.getMapSize() > 16 && type == TYPE_BYTE_BINARY )
      throw new IllegalArgumentException("Type TYPE_BYTE_BINARY cannot have a larger than 16-color palette.");
    if( indexcolormodel.getMapSize() > 256 )
      throw new IllegalArgumentException("Byte type cannot have a larger than 256-color palette.");

    init( indexcolormodel,
          indexcolormodel.createCompatibleWritableRaster(w, h),
          indexcolormodel.isAlphaPremultiplied(),
          null, // no properties
          type );
  }

  public BufferedImage(ColorModel colormodel, WritableRaster writableraster,
		       boolean premultiplied, Hashtable<?,?> properties)
  {
    init(colormodel, writableraster, premultiplied, properties, TYPE_CUSTOM);
  }
 

  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;
  }

  /**
   * Creates the default palettes for the predefined indexed color types
   * (256-color or black-and-white)
   *
   * @param binary - If <code>true</code>, a black and white palette,
   * otherwise a default 256-color palette is returned.
   */    
  private IndexColorModel createDefaultIndexedColorModel( boolean binary )
  {
    if( binary )
      {
        byte[] t = new byte[]{ 0, (byte)255 };
        return new IndexColorModel( 1, 2, t, t, t );
      }

    byte[] r = new byte[256];
    byte[] g = new byte[256];
    byte[] b = new byte[256];
    
    int index = 0;
    for( int i = 0; i < 6; i++ )
      for( int j = 0; j < 6; j++ )
        for( int k = 0; k < 6; k++ )
          {
            r[ index ] = (byte)(i * 51);
            g[ index ] = (byte)(j * 51);
            b[ index ] = (byte)(k * 51);
            index++;
          }
    
    while( index < 256 )
      {
        r[ index ] = g[ index ] = b[ index ] = 
          (byte)(18 + (index - 216) * 6);
        index++;
      }
    
    return new IndexColorModel( 8, 256, r, g, b );
  }
  
  public void coerceData(boolean premultiplied)
  {
    colorModel = colorModel.coerceData(raster, premultiplied);
    isPremultiplied = 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);
    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<ImageConsumer> consumers = new Vector<ImageConsumer>();

        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 = 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<RenderedImage> 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);

    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()
  {
    CPStringBuilder buf;

    buf = new CPStringBuilder(/* 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 (tileObservers == null)
      tileObservers = new Vector<TileObserver>();
	
    tileObservers.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 (tileObservers == null)
      return;
	
    tileObservers.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();
  }
}
