// histogram.c     Section: 9.3 Histogram & 9.4 Cumulative Histogram
//      Copyright 1994, Center for Computer Vision and Visualization,
//      University of Florida.  All rights reserved.
//
// An iterative version of the histogram program.
// This version will usually be faster on sequential machines.
// The template version may be faster on parallel machines.


#include "histogram.h"
#include "ImageIter.h"
#include "Array.h"


//////////////////////////////////////////////////////////////////
// histogram()
//   Calculate the histogram of an image using
//   iteration over the values of the image
//
template <class P ,class T>
IA_Image<IA_Point<int>,int>
histogram( const IA_Image<P,T> & a ) {

    T  aMax( max(a) ), aMin( min(a) );  // Max and Min image values

    // Create an array as large as the cardnality of a.range()
    // Here we use the iac++ class library supplemental class IA_Array<T>
    // because it provides storage management.  We could also have
    // used:  int *h_array = new int[ aMax - aMin + 1 ], but we
    // would have had to manage the storage ourself.

    IA_Array<int> h_array( aMax - aMin + 1 );
    for (int i=0; i<( aMax - aMin + 1 ); i++) {
	// As per the ARM, p.61, sec 5.3.3 only static memory
	//    has a default initial value, zero.
	// Hence we must initialize the array ourself.
	h_array[i] = 0;
    }


    // An Image Value Iterator
    IA_IVIter<P,T>
	ivIter( a );

    // Now iterate over the image and count the values.
    T  value;
    while ( ivIter( value ) ) {
	h_array[ int(value) - int(aMin) ] ++;
    }

    // Now return the result as an image
    return
	IA_Image<IA_Point<int>,int>(
	    IA_boxy_pset( IA_Point<int>(aMin),
			  IA_Point<int>(aMax) ),
	    h_array.data_start(),
	    h_array.len() );
}



//////////////////////////////////////////////////////////////////
// cumulative_histogram()
//   Calculate the cumulative histogram of an image using
//   iteration over the value of the histogram image
//
template <class P, class T>
IA_Image<IA_Point<int>,int>
cumulative_histogram( const IA_Image<P,T> & a ) {

    // First calculate the histogram.
    IA_Image<IA_Point<int>,int>
	ch = histogram( a );

    // Now cumulate the values so  ch  is really a cumulative histogram
    int cum = 0;
    int value;
    IA_Point<int>  ip;
    IA_IPIter<IA_Point<int>,int>
	ipIter( ch ); // Image Pixel Iterator over the histogram

    while ( ipIter(ip,value) ) {
	ch[ip] += cum;
	cum += value;
    }

    return ch;     // Return the cumulative histogram
}




//////////////////////////////////////////////////////////////////
// normalized_histogram()
//   Return the normalized histogram of an image
//
template <class P, class T>
IA_Image<IA_Point<int>,float>
normalized_histogram(const IA_Image<P,T> &a) {

    return
	IA_Image<IA_Point<int>,float>( histogram(a) )
	/ float( a.domain().card() );
}


//////////////////////////////////////////////////////////////////
// normalized_cumulative_histogram()
//   Return the normalized cumulative histogram of an image
//
template <class P, class T>
IA_Image<IA_Point<int>,float>
normalized_cumulative_histogram(const IA_Image<P,T> &a) {

    return
	IA_Image<IA_Point<int>,float>( cumulative_histogram(a) )
	/ float( a.domain().card() );
}

