/*****************************************************************************
 * Copyright (C) The Apache Software Foundation. All rights reserved.        *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included with this distribution in  *
 * the LICENSE file.                                                         *
 *****************************************************************************/

package org.apache.batik.extension.svg;

import java.awt.geom.AffineTransform;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.renderable.RenderContext;

import org.apache.batik.ext.awt.image.LinearTransfer;
import org.apache.batik.ext.awt.image.TransferFunction;
import org.apache.batik.ext.awt.image.renderable.AbstractColorInterpolationRable;
import org.apache.batik.ext.awt.image.renderable.Filter;
import org.apache.batik.ext.awt.image.rendered.ComponentTransferRed;

public class BatikHistogramNormalizationFilter8Bit
    extends      AbstractColorInterpolationRable
    implements   BatikHistogramNormalizationFilter {

    private float trim = .01f;

    /**
     * Sets the source of the operation
     */
    public void setSource(Filter src){
        init(src, null);
    }

    /**
     * Returns the source of the operation
     */
    public Filter getSource(){
        return (Filter)getSources().get(0);
    }

    /**
     * Returns the trim percent for this normalization.
     */
    public float getTrim() {
        return trim;
    }

    /**
     * Sets the trim percent for this normalization.
     */
    public void setTrim(float trim) {
        this.trim = trim;
        touch();
    }

    public BatikHistogramNormalizationFilter8Bit(Filter src, float trim) {
        setSource(src);
        setTrim(trim);
    }

    protected int [] histo = null;
    protected float slope, intercept;

    /**
     * This method computes the histogram of the image and
     * from that the appropriate clipping points, which leads
     * to a slope and intercept for a LinearTransfer function
     *
     * @param rc We get the set of rendering hints from rc.
     */
    public void computeHistogram(RenderContext rc) {
        if (histo != null) 
            return;

        Filter src = getSource();
        
        float scale = 100f/src.getWidth();
        float yscale = 100f/src.getHeight();

        if (scale > yscale) scale=yscale;
        
        AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
        rc = new RenderContext(at, rc.getRenderingHints());
        RenderedImage histRI = getSource().createRendering(rc);

        histo = new HistogramRed(convertSourceCS(histRI)).getHistogram();

        int t = (int)(histRI.getWidth()*histRI.getHeight()*trim+0.5);
        int c, i;
        for (c=0, i=0; i<255; i++) {
            c+=histo[i];
            // System.out.println("C[" + i + "] = " + c + "  T: " + t);
            if (c>=t) break;
        }
        int low = i;
        
        for (c=0, i=255; i>0; i--) {
            c+=histo[i];
            // System.out.println("C[" + i + "] = " + c + "  T: " + t);
            if (c>=t) break;
        }
        int hi = i;

        slope = 255f/(hi-low);
        intercept = (slope*-low)/255f;
    }

    
    public RenderedImage createRendering(RenderContext rc) {
        //
        // Get source's rendered image
        //
        RenderedImage srcRI = getSource().createRendering(rc);

        if(srcRI == null)
            return null;

        computeHistogram(rc);

        SampleModel sm = srcRI.getSampleModel();
        int bands = sm.getNumBands();

        // System.out.println("Slope, Intercept: " + slope + ", " + intercept);
        TransferFunction [] tfs = new TransferFunction[bands];
        TransferFunction    tf  = new LinearTransfer(slope, intercept);
        for (int i=0; i<tfs.length; i++) 
            tfs[i] = tf;

        return new ComponentTransferRed(convertSourceCS(srcRI), tfs, null);
    }
}
