// histogram.c
//    This is the implementation file for the template versions of
//    the histogram and cumulative histogram programs.
//

#include "UcharDI.h"
#include "IntDI.h"

#include "PSIter.h"
#include "DDTempl.h"
#include "ClosureDT.h"

//////////////////////////////////////////////////////////////////
//
// class IA_HistogramTemplate<IA_Image<P,T>>
//
//////////////////////////////////////////////////////////////////

// Create a parameterized template which will evaluate
//   to a one point image at each point in the
//   parameterized template domain.

template <class I>
class IA_HistogramTemplate
: public IA_ClosureDT<IA_Image<IA_Point<int>,int> > {
private:
    I im;   // The image we are creating a histogram for

public:
    IA_HistogramTemplate( const I &inImage )
    : IA_ClosureDT<IA_Image<IA_Point<int>,int> >(inImage.domain()),
      im(inImage) {}

    IA_Image<IA_Point<int>,int>
    operator() (const IA_Point<int> &aPt) const;

    IA_ClosureDT<IA_Image<IA_Point<int>,int> > *clone_self() const;

    ostream &print_this(ostream &o) const;
};



template <class I>
IA_Image<IA_Point<int>,int>
IA_HistogramTemplate<I>::operator() (const IA_Point<int> &aPt) const {

    // We return an image that is defined only on the support,
    // namely the one point associated with a non-zero value.

    // Hence, we return a one point image, only defined at the
    // template\'s support.
    return
        IA_Image<IA_Point<int>,int>(
            IA_Set<IA_Point<int> >( IA_Point<int>(im(aPt)) ),
            1 );
}


template <class I>
IA_ClosureDT<IA_Image<IA_Point<int>,int> > *
IA_HistogramTemplate<I>::clone_self() const {
    return new IA_HistogramTemplate<I>(this->im);
}


template <class I>
ostream & IA_HistogramTemplate<I>::print_this(ostream &o) const {

    IA_PSIter<IA_Point<int> >  htIter( (this->im).domain() );
    // The template point set

    IA_Point<int>          iPt;

    while ( htIter( iPt ) ) {  // for each point in the domain
        o   << "(" << iPt << ","
            << this->operator()(iPt)  // range value is an image
            << ")";
    }
    return o;
}
