// neighborhood_example.02.c
// Averaging using neighborhoods and the array version of the
//    general neighborhood_reduction().

// We will average the image at each point over a localized set
//   of 9 points, the point in question, and it\'s eight
//   neighborhooding point.

// We will calculate the average by:
//    1) Providing an averaging function that takes an array of
//       of values and the array size to determine the average.


// Note: This approach has the failing that average calculated at the
//    boundary of the image maybe too small.  This is because this
//    method does not take into account that not every point has a
//    full neighborhood.


#include "IntDI.h"
#include "Nbh.h"


// This little function simply adds up the elements of an array and
//   returns the average of that value.
//
average_array( int* values, unsigned int array_size ) {
    int total( 0 );

    // We should probably check if array_size > 0 ...
    for (int i=0; i< array_size; i++ ) {
        total += values[i];
    }
    return total/array_size;
}


int main() {

    // Read in the image from the standard input stream: cin
    IA_Image<IA_Point<int>,int>
        in_image = read_int_PGM( cin );

    IA_Image<IA_Point<int>,int>
        avg_image;

    // Define the point set of the 9 points centered at <0,0>
    IA_Set<IA_Point<int> >
        nbhd_ps = IA_boxy_pset( IA_Point<int>(-1,-1),
                                IA_Point<int>( 1, 1) );

    // Now create the neighborhood based on the point set just defined.
    IA_Neighborhood<IA_Point<int>,IA_Point<int> >
        nbhd( 2,          // The dimension of the pointset
              nbhd_ps );  // This is similar to a template\'s image


    // Finally calculate the image by simple division
    avg_image = neighborhood_reduction( in_image,
                                        nbhd,
                                        in_image.domain(),
                                        average_array );


    // Write the result to the standard output stream
    avg_image.write_PGM( cout );

    return 0;
}
