// Emacs: -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//


//
// $Log: CoreImage.h,v $
// Revision 1.12  1994/08/22  15:20:29  thoth
// DOS-inspired name rework.
//
// Revision 1.11  1994/07/25  17:24:13  thoth
// Name sanitization
//
// Revision 1.10  1994/03/30  13:53:09  thoth
// FBI now has enough class parameters to describe friendliness of
// certain function templates.
// FBI functions are now inlines removing the need for ptrepository
// objects.
//
// Revision 1.9  1994/03/14  15:50:22  thoth
// ValueSet has been replaced by container class Set.
// FBI will eventually contain all image-image ops.
//
// Revision 1.8  1994/02/26  16:03:53  thoth
// operator() of the container now relies upon the contained classes
// to check if p is contained in the domain.  This means that users
// could possibly write an erroneous operator().
//
// Revision 1.7  1994/01/31  15:42:14  thoth
// chi_contains and compositions have been moved into AuxImage.c.
// transpose of a 2D boxy image is now available.
//
// Revision 1.6  1994/01/07  15:10:00  thoth
// Image class is now CoreImage and named image types are
// Image<P,T>.
//
// Revision 1.5  1993/12/29  16:57:16  thoth
// new chi_contains function
// Pixel array constructor.
// pointarray valuearray constructor.
// Improved error handling.
//
// Revision 1.4  1993/11/17  18:20:12  thoth
// translated is now translate.
// extensivep is now extensive.
// CFront bug workaround is now disabled.
// zero_extend is a void function.
//
// Revision 1.3  1993/10/05  19:33:08  thoth
// Move to new Closure naming convention.
//
// Revision 1.2  1993/09/27  15:50:57  thoth
// xlated is now translated.
//
// Revision 1.1  1993/09/15  12:53:58  thoth
// Initial revision
//

#ifndef CoreImage_h_
#define CoreImage_h_

#include <iostream.h>
#include "ia.h"
#include "Point.h"

#include "Set.h"
#include "IntPS.h"
#include "DblPS.h"

#include "BaseI.h"
#include "Pixel.h"


template < class P,class T> class IA_IVIter;
template < class P,class T> class IA_IPIter;

template < class P,class T> class IA_ClosureI;

template < class P,class T> class IA_CoreImage;

template < class P, class Q, class R, class S, class T> class IA_FBI;

template < class P,class T>
friend ostream& operator <<(ostream&, const IA_CoreImage<T,P>&);

#include "AuxImage.h"

template < class P,class T>
class IA_CoreImage {
    template <class Q, class U>
	friend class IA_FBI;
  protected:
    
    // INVARIANT:  bip has a value in every image.  The uninitialized
    //		   value is errorDI.
    IA_BaseImage<P,T> *bip;
    
    // Places a valid value in bip and refcounts appropriately.
    void set_and_reference_image(IA_BaseImage<P,T> *i);
    
    // Decrement the BaseDI\'s refcount and delete if necessary.
    void disassociate_image();
    
    // no one else should be tossing BaseDIs around
    IA_CoreImage(IA_BaseImage<P,T> *base) {
	set_and_reference_image(base);
    }
    
    static IA_VectorI<P,T> *sortedPixel_to_VectorI(const IA_Pixel<P,T> *pixels,
						   unsigned count);

  public:
    IA_CoreImage();
    
    // copy constructor
    IA_CoreImage(const IA_CoreImage&);
    
    // const image constructor
    IA_CoreImage(const IA_Set<P>&, const T&);
    
    // vector image constructor
    IA_CoreImage(const IA_Set<P>&, T *, unsigned, int giveaway);
    IA_CoreImage(const IA_Set<P>&, const T *, unsigned);
    IA_CoreImage(const IA_Pixel<P,T> *, unsigned);
    IA_CoreImage(const P*, unsigned, const T *, unsigned);
    IA_CoreImage(const P*, unsigned, T *, unsigned, int giveaway);
    IA_CoreImage(const IA_ClosureI<P,T>& i);
    IA_CoreImage(const IA_Set<P>&, T (*)(const P&));
    IA_CoreImage(const IA_Set<P>&, T (*)(P));
    
    virtual ~IA_CoreImage();
    
    IA_CoreImage& operator =(const IA_CoreImage &);
    
    // keep the domain, but make all values the same
    IA_CoreImage& operator =(const T&);
    
    // what sort of image is this?
    IA::Type type() const { return bip->type(); }
    
    // retrieve a value from the image
    T operator ()(const P& p) const {
	return (*this->bip)(p);
    }
    
    // retrieve a reference to a value in the image
    T& operator [](const P&);

    IA_CoreImage<IA_Point<int>,T> restrict( const IA_Set<IA_Point<int> >&) const;
    IA_CoreImage<P,T> restrict( const IA_Set<IA_Point<double> >&) const;
    IA_CoreImage restrict( const IA_Set<T>&) const;
    // the next one looks gratuitous --thoth
    //IA_CoreImage restrict( int (*)(const P&)) const;
    
    // Image Extension -- NOT ASSOCIATIVE!!!
  private:
#define FUNKY_ERROR
    static void vec_vec_2_vec_structcopy (const T **lhs_data,
					  const T **rhs_data,
					  T **dest, const IA_SetStructure &ss);
    static void vec_iter_2_vec_structcopy(const T **lhs_data,
#ifdef FUNKY_ERROR
					  void *rhs_iter,
#else
					  IA_IVIter<P,T> *rhs_iter,
#endif
					  T **dest,
					  const IA_SetStructure &ss);
    static void iter_vec_2_vec_structcopy( //
#ifdef FUNKY_ERROR
	void *lhs_iter,
#else
	IA_IVIter<P,T> *lhs_iter,
#endif
	const T **rhs_data,
	T **dest,
	const IA_SetStructure &ss);
    static void iter_iter_2_vec_structcopy( //
#ifdef FUNKY_ERROR
	void *lhs_iter,
	void *rhs_iter,
#else
	IA_IVIter<P,T> *lhs_iter,
	IA_IVIter<P,T> *rhs_iter,
#endif
	T **dest,
	const IA_SetStructure &ss);
  public:
    IA_CoreImage extend( const IA_CoreImage&) const;

    IA_CoreImage translate( const P &) const;

    IA_Set<P> domain() const { return this->bip->domain(); }

    IA_Set<T> range() const;
    IA_Array<T> value_array() const { return this->bip->value_array(); }
    
    unsigned card() const {
#if 0
	IA_Set<P>	temp = this->domain();
	return temp.card();
#else
	return this->domain().card();
#endif
    }
    
    int extensive() const { return this->bip->extensive(); }
    
    T reduce(T (*)(const T&, const T&),T) const;
    
    T reduce(T (*) (T, T), T) const;

    friend IA_CoreImage<IA_Point<int>,IA_Bit>
	chi_contains(const IA_CoreImage<IA_Point<int>, T> &lhs,
		     const IA_Set<T> &rhs);
    friend IA_CoreImage<IA_Point<int>,T>
	transpose(const IA_CoreImage<IA_Point<int>, T> &lhs);

#include "ImgRestrictAssn.h"

public:
    friend ostream& operator <<(ostream&, const IA_CoreImage<P,T>&);
    
#if 0
    static IA_CoreImage read_IAA(istream &header, istream &values);
    static IA_CoreImage read_IAA(const char *fname1,
			     const char *fname2);
    static IA_CoreImage read_IAA(const char *fname);
    
    void write_IAA(ostream &header, ostream &values) const;
    
    void write_IAA(const char *fname1, const char *fname2) const;
    void write_IAA(const char *fname) const;
#endif

    friend class IA_CoreImage<IA_Point<int>, T>;
    friend class IA_CoreImage<IA_Point<double>, T>;
    friend class IA_IVIter<P,T>;
    friend class IA_IPIter<P,T>;
    
    friend void zero_extend(const IA_CoreImage<P,T> &, const IA_Set<P>&,
			    T*, T);
};

#endif // Image_h_
