/* PNGEncoder.java --
   Copyright (C) 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 gnu.javax.imageio.png;

import java.util.Vector;
import java.util.zip.Deflater;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.ICC_ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferUShort;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

public class PNGEncoder 
{
  /**
   * The default data chunk size. 8 kb.
   */
  private static final int defaultChunkSize = 8192;

  private PNGHeader header;
  private PNGPalette palette;
  private int stride, bpp;
  private byte[] rawData;
  private PNGICCProfile profile;

  public PNGEncoder( BufferedImage bi ) throws PNGException
  {
    ColorModel c = bi.getColorModel();
    int width = bi.getWidth(); 
    int height = bi.getHeight();
    int depth = 0;
    int colorType;
    boolean interlace = false;

    if( c instanceof IndexColorModel )
      {
	colorType = PNGHeader.INDEXED;
	int n = ((IndexColorModel)c).getMapSize();
	if( n <= 2 )
	  depth = 1;
	else if( n <= 4 )
	  depth = 2;
	else if( n <= 16 )
	  depth = 4;
	else if( n <= 256 )
	  depth = 8;
	else
	  throw new PNGException("Depth must be <= 8 bits for indexed color.");
	palette = new PNGPalette( ((IndexColorModel)c) );
      }
    else
      { 
	ColorSpace cs = c.getColorSpace();
	ColorSpace grayCS = ColorSpace.getInstance( ColorSpace.CS_GRAY );
	if( cs == grayCS || bi.getType() == BufferedImage.TYPE_BYTE_GRAY 
	    || bi.getType() == BufferedImage.TYPE_USHORT_GRAY )
	  colorType = c.hasAlpha() ? PNGHeader.GRAYSCALE_WITH_ALPHA : 
	    PNGHeader.GRAYSCALE;
	else
	  colorType = c.hasAlpha() ? PNGHeader.RGB_WITH_ALPHA : PNGHeader.RGB;
	// Figure out the depth
	int[] bits = c.getComponentSize();
	depth = bits[0];
	for(int i = 1; i < bits.length; i++ )
	  if( bits[i] > depth ) depth = bits[i];
	if( (cs != grayCS && !cs.isCS_sRGB()) && cs instanceof ICC_ColorSpace )
	  profile = new PNGICCProfile( ((ICC_ColorSpace)cs).getProfile() );
      }

    header = new PNGHeader(width, height, depth, colorType, interlace);

    stride = header.getScanlineStride(); // scanline stride 
    bpp = header.bytesPerPixel(); // bytes per pixel
    getRawData( bi );
  }

  /**
   * Returns the generated header.
   */ 
  public PNGHeader getHeader()
  {
    return header;
  }

  /**
   * Returns the generated palette.
   */ 
  public PNGPalette getPalette()
  {
    return palette;
  }

  /**
   * Returns the associated ICC profile, if any.
   */ 
  public PNGICCProfile getProfile()
  {
    return profile;
  }

  /**
   * Encodes the raster and returns a Vector of PNGData chunks.
   */
  public Vector encodeImage()
  {
    Deflater deflater = new Deflater(); // The deflater
    boolean useFilter = PNGFilter.useFilter( header );
    byte[] lastScanline = new byte[ stride ];

    byte[] data = new byte[ rawData.length + header.getHeight() ];

    byte filterByte = PNGFilter.FILTER_NONE;
    for( int i = 0; i < header.getHeight(); i++)
      {
	byte[] scanline = new byte[ stride ]; 
	System.arraycopy(rawData, (i * stride), scanline, 0, stride);
	if( useFilter && i > 0)
	  filterByte = PNGFilter.chooseFilter( scanline, lastScanline, bpp);
	
	byte[] filtered = PNGFilter.filterScanline( filterByte, scanline, 
						    lastScanline, bpp );
	data[i * (stride + 1)] = filterByte;
	System.arraycopy(filtered, 0, data, 1 + (i * (stride + 1)), stride);

	lastScanline = scanline;
      }

    deflater.setInput( data ); 
    deflater.finish();

    PNGData chunk;
    Vector chunks = new Vector();
    do
      {
	chunk = new PNGData( defaultChunkSize );
	chunk.deflateToChunk( deflater );
	chunks.add( chunk );
      }
    while( chunk.chunkFull() );
    chunk.shrink(); // Shrink the last chunk.
    return chunks;
  }

  /**
   * Get the image's raw data.
   * FIXME: This may need improving on.
   */
  private void getRawData( BufferedImage bi ) throws PNGException
  {
    WritableRaster raster = bi.getRaster();
    rawData = new byte[ stride * header.getHeight() ];
    if( header.isIndexed() )
      {
	DataBuffer db = raster.getDataBuffer();
	if( !( db instanceof DataBufferByte ) )
	  throw new PNGException("Unexpected DataBuffer for an IndexColorModel.");
	byte[] data = ((DataBufferByte)db).getData();
	for(int i = 0; i < header.getHeight(); i++ )
	  System.arraycopy( data, i * stride, rawData, i * stride, stride );
	return;
      }

    if( header.getDepth() == 16 )
      {
	DataBuffer db = raster.getDataBuffer();
	if( !( db instanceof DataBufferUShort ) )
	  throw new PNGException("Unexpected DataBuffer for 16-bit.");
	short[] data = ((DataBufferUShort)db).getData();
	for(int i = 0; i < header.getHeight(); i++ )
	  for(int j = 0; j < ( stride >> 1); j++)
	    {
	      rawData[ j * 2 + i * stride ] = (byte)((data[j + i * (stride >> 1 )] & 0xFF00) >> 8);
	      rawData[ j * 2 + i * stride + 1 ] = (byte)(data[j + i * (stride >> 1 )] & 0xFF);
	    }
	return;
      }

    int size = ( header.getColorType() == PNGHeader.RGB_WITH_ALPHA ) ? 4 : 3;
    int width = header.getWidth();
    int height = header.getHeight();
    int[] pixels = bi.getRGB( 0, 0, width, height, null, 0, width );

    for( int i = 0; i < width * height; i++ )
      {
	rawData[ i * size ] = (byte)((pixels[i] & 0xFF0000) >> 16);
	rawData[ i * size + 1 ] = (byte)((pixels[i] & 0xFF00) >> 8);
	rawData[ i * size + 2 ] = (byte)(pixels[i] & 0xFF);
      }

    if( size == 4 )
      for( int i = 0; i < width * height; i++ )
	rawData[ i * size + 3 ] = (byte)((pixels[i] & 0xFF000000) >> 24);
  }
}
