// template_example.03.c

//
// FloatDI magnification -- closure version
//

#include "FloatDI.h"
#include "UcharDI.h"
#include "DDTempl.h"
#include "ClosureDT.h"
#include "FloatConv.h"


const int       ident=1;


class shrinkDT: public IA_ClosureDT<IA_Image<IA_Point<int>,float> > {
    int fact;
public:
    shrinkDT(unsigned dim, int fact_)
    :IA_ClosureDT<IA_Image<IA_Point<int>,float> >(
        IA_universal_ipset(dim)
        ) {
        fact = fact_; }

    IA_ClosureDT<IA_Image<IA_Point<int>,float> > *
    clone_self() const {
        return new shrinkDT(*this); }

    IA_Image<IA_Point<int>,float>
    operator()(const IA_Point<int> &) const;
    
    ostream &print_this(ostream &o) const {
        return o<<"magnify by " << fact << "\n"; }
};


IA_Image<IA_Point<int>,float>
shrinkDT::operator()(const IA_Point<int> &p) const
{
    IA_Point<int>               inf_ = p*fact;
    IA_Point<int>               sup_ = (p+1)*fact -1;
    IA_Set<IA_Point<int> >
        ps( IA_boxy_pset(inf_, sup(inf_,sup_)) );

    return IA_Image<IA_Point<int>,float>( ps, 1.0/ps.card() );
}


int main()
{
    IA_Image<IA_Point<int>,float> 
        im = IA_Image<IA_Point<int>,int>::read_PGM(cin);

    IA_Set<IA_Point<int> >
        ps = im.domain();

    const int factor=3;
    
    IA_DDTemplate<IA_Image<IA_Point<int>,float> >
        mag(shrinkDT(2, factor));  // 2-D, 1/3 image size

    IA_Set<IA_Point<int> > destPS( ps.inf()/factor, ps.sup()/factor );

    IA_Image<IA_Point<int>,int>
        im2 = to_int( linear_product( im, mag, destPS ) );

    display(to_uchar(im));    // display original image
    display(to_uchar(im2));   // display shrunk image

    return 0;
}
