package imageTiTi.reducer;

import imageTiTi.ImageNew;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferUShort;

/**
 * <p>Description: this class reduces the number of gray level in image with a simple division.</p>
 * <p>Package(s) required:</p>
 * <p>Copyright: Copyright (c) 2006-Today.</p>
 * <p>Updates:<br>
 * May 10 2012, 1.1 => Use of databuffer.<br>
 * 11 Avril 2010 => Creation. Recuperation des methodes qui etaient presentes dans la classe ImageConverter.</p>
 * 
 * @author Guillaume THIBAULT
 * @version 1.1
 */

public class GrayLevelReducer implements ColorReducer
{

/** This method reduces the number of colors.
 * @param source The image to process.
 * @param nbGrayLevel The new number of colors.
 * @param ForbiddenValue The forbidden value, to not taking into account and to replace by 0.
 * @return The result image.*/
public BufferedImage Reduce(BufferedImage source, int nbGrayLevel, int ForbiddenValue)
	{
	BufferedImage result = ImageNew.Same(source) ;
	Reduce(source, result, nbGrayLevel, ForbiddenValue) ;
	return result ;
	}


/** This method reduces the number of colors.
 * @param source The image to process.
 * @param result The result image (must be allocated beforehand).
 * @param nbGrayLevel The new number of colors.
 * @param ForbiddenValue The forbidden value, to not taking into account and to replace by 0.*/
public void Reduce(BufferedImage source, BufferedImage result, int nbGrayLevel, int ForbiddenValue)
	{ 
	int x, v ;
	double ratio ;
	
	switch ( source.getType() )
		{
		case BufferedImage.TYPE_BYTE_GRAY :
		case BufferedImage.TYPE_3BYTE_BGR :
		case BufferedImage.TYPE_4BYTE_ABGR :
			ratio = (double)nbGrayLevel / 256.0 ;
			byte[] bytebufferin = ((DataBufferByte)source.getRaster().getDataBuffer()).getData() ;
			byte[] bytebufferout = ((DataBufferByte)result.getRaster().getDataBuffer()).getData() ;
			for (x=0 ; x < bytebufferin.length ; x++)
				{
				v = bytebufferin[x] & 0xFF ;
				if ( v == ForbiddenValue ) bytebufferout[x] = 0 ; // 0 est pour la valeur interdite.
				else bytebufferout[x] = (byte)((double)v*ratio + 1.0) ;
				}
			bytebufferin = bytebufferout = null ;
			break ;
		case BufferedImage.TYPE_USHORT_GRAY :
			ratio = (double)nbGrayLevel / 65536.0 ;
			short[] shortbufferin = ((DataBufferUShort)source.getRaster().getDataBuffer()).getData() ;
			short[] shortbufferout = ((DataBufferUShort)result.getRaster().getDataBuffer()).getData() ;
			for (x=0 ; x < shortbufferin.length ; x++)
				{
				v = shortbufferin[x] & 0xFFFF ;
				if ( v == ForbiddenValue ) shortbufferout[x] = 0 ; // 0 est pour la valeur interdite.
				else shortbufferout[x] = (short)((double)v*ratio + 1.0) ;
				}
			shortbufferin = shortbufferout = null ;
			break ;
		default: throw new IllegalArgumentException("Image type not supported.") ;
		}
	}

}
