import com.graphics3d.book.image.JImage;

/**
   Uses a combination of intensity, color, and edge matches to attempt
   to match characteristics represented by the low-level human
   perceptual system.
   
   <P> WARNING: statically caches the goal image with a strong
   pointer, preventing it from being garbage collected.  
*/
public class PerceptualMatchFunction implements MatchQualityFunction {
    /**
       Avoid recomputing the edges of the goal image every time.
     */
    static private boolean cachedEdges[] = null;
    static private double cachedFreq[] = null;
    static private JImage cachedBlurGoal = null;

    static private JImage goal = null;


    final static public PerceptualMatchFunction instance = new PerceptualMatchFunction();

    /** 
        Dumps the cache, allowing garbage collection.
     */
    static public void dumpCache() {
        cachedEdges = null;
        goal = null;
    }

    /**
       Given a goal image and a proposed matching image, returns a
       number between 0 (bad) and 1 (perfect) indicating how well the
       proposal matches the goal.  */
    synchronized public float matchQuality(JImage goal, JImage proposal, boolean mask[]) {
        
        if (goal != this.goal) {
            this.goal = goal;
            cachedEdges = JImageUtils.getEdges(goal);
            cachedBlurGoal = JImageUtils.blur(goal);
        }
        
        /*
        if ((goal != this.goal) || (cachedFreq == null)) {
            this.goal = goal;
            cachedFreq = JImageUtils.getFrequencies(goal);
        }
        */

        double e = JImageUtils.edgeMatch(cachedEdges, JImageUtils.getEdges(proposal));
        //double f = JImageUtils.frequencyMatch(cachedFreq, JImageUtils.getFrequencies(proposal), mask);
        //        double i = Math.pow(JImageUtils.intensityMatch(goal, proposal, mask), 1.5);
        double c1 = JImageUtils.colorMatch(goal, proposal, mask);
        double c2 =  //JImageUtils.localAverageColorMatch(goal, proposal, mask) +
            JImageUtils.colorMatch(cachedBlurGoal, JImageUtils.blur(proposal), mask);
        double c3 =  JImageUtils.averageColorMatch(goal, proposal, mask);
        
        return (float)(0.40 * e + 
                       0.10 * c1 +
                       0.35 * c2 +
                       0.15 * c3);
    }

}
