/* 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();
  }
}
