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

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

static char copyright[] = "Copyright 1993, Center for Computer Vision and Visualization,\nUniversity of Florida.  All rights reserved.\n";

static char IntDI_rcsid[] = "$Id: IntDI.c,v 1.10.1.3 1995/01/13 19:37:42 thoth Exp thoth $";

//
// $Log: IntDI.c,v $
// Revision 1.10.1.3  1995/01/13  19:37:42  thoth
// CoreImage has been re-merged with Image.  All special stuff should be
// friends of FBI now.
//
// Revision 1.10.1.2  1995/01/09  18:15:45  thoth
// Make functions match prototype.
//
// Revision 1.10.1.1  1994/12/28  17:14:00  thoth
// Image I/O is now ROF
// remove obsolete instantiation cruft.
//
// Revision 1.10  1994/09/16  15:03:40  thoth
// remove unnecessary header files.
//
// Revision 1.9  1994/07/25  17:26:39  thoth
// Name sanitization
//
// Revision 1.8  1994/05/17  12:53:27  thoth
// Image Operations now get their own files.
//
// Revision 1.7  1994/03/14  15:51:35  thoth
// ValueSet has been replaced by container class Set.
// abs is now available on Int images.
//
// Revision 1.6  1994/01/31  15:46:30  thoth
// read_PGM now can return the maxval.
// pseudo_division is now available.
//
// Revision 1.5  1994/01/07  15:10:00  thoth
// Image class is now CoreImage and named image types are
// Image<P,T>.
//
// Revision 1.4  1993/12/29  17:03:42  thoth
// write_PGM functions will no longer calculate a maxval of 0.
//
// Revision 1.3  1993/11/17  18:23:26  thoth
// IPSIter is now PSIter<IntPoint>.
// restriction functions now go in the individual image implementation modules.
// read_PGM and write_PGM now support P2 ASCII images.
//
// Revision 1.2  1993/10/05  19:33:08  thoth
// Move to new Closure naming convention.
//
// Revision 1.1  1993/09/15  12:54:51  thoth
// Initial revision
//
// Revision 1.9  93/05/27  11:36:28  thoth
// Copyright Notices
// 
// Revision 1.8  93/05/26  17:02:11  thoth
// instantiate IAAIO.
// 
// Revision 1.7  93/05/18  21:40:49  thoth
// *** empty log message ***
// 
// Revision 1.6  93/04/29  11:20:40  thoth
// non-boxy images now output correctly.
// 
// Revision 1.5  93/04/17  18:48:02  thoth
// use IA_Point<int> instead of IntPoint
// 
// Revision 1.4  93/04/08  13:15:13  thoth
// write_PGM will now compute maxval if not supplied.
// read/write_PGM now accept character strings as well
// as ostream&s and treat them as filenames.
// const_reduce special cases now available.
// 
// Revision 1.3  93/03/10  13:35:32  thoth
// intimage-intimage operations are now generated by a perl script.
// We must still provide some inline functions to help it out though.
// 
// Revision 1.2  93/02/23  14:25:12  thoth
// force an instantiation of OtherDI.
// FunctionRefDIs are supported again.
// 
// Revision 1.1  93/02/20  12:17:42  thoth
// Initial revision
// 
// 

#include	"Closure.h"
#include	"PSIter.h"

#include	"IntDI.h"
#include	"ImageIter.h"

#include	<math.h>
#include	<fstream.h>
#include	<values.h>

#include	"Bit.h"
#include "image_errors.h"

//
//
//

#include "restrict.h"

IA_BaseImage<IA_Point<int>,int> *restrict_toD(const IA_BaseImage<IA_Point<int>, int> *im, const IA_Set<IA_Point<int> > &ips) {
    return restrictD_toD(im, ips);
}

IA_BaseImage<IA_Point<int>,int> *restrict_toD(const IA_BaseImage<IA_Point<double>, int> *im, const IA_Set<IA_Point<int> > &ips) {
    return restrictC_toD(im, ips);
}

//
//

istream &wsc(istream &);	// from UcharDI.c

IA_Image<IA_Point<int>,int>
read_int_PGM(istream &istr, int *maxval_ret)
{
    int	width, height,maxval;
    int	code;
    if (istr.get()=='P' && ((code=istr.get())=='5' || code == '2')
	&& istr>>wsc>>width>>wsc>>height>>wsc>>maxval) {
	if (maxval_ret)
	    *maxval_ret = maxval;
	{
	    int	ch = istr.get();
	    if (ch!='\n')
		istr.putback(ch);
	}
	const unsigned	size=width*height;
	int	*data = new int[size];
	if (code=='5') {
	    unsigned char	*tmp = new unsigned char[size];
	    if (!istr.read(tmp, size)) {
		delete[] data;
		ia_throw(Image_PNMIO_Exception(__FILE__, __LINE__));
		return IA_Image<IA_Point<int>,int>();
	    }
	    for (unsigned i=0; i<size; i++)
		data[i] = tmp[i];
	    delete[] tmp;
	} else {
	    for (unsigned i=0; i<size; i++) {
		if (!(istr >> data[i])) {
		    delete[] data;
		    ia_throw(Image_PNMIO_Exception(__FILE__, __LINE__));
		    return IA_Image<IA_Point<int>,int>();
		}
	    }
	}
	return IA_Image<IA_Point<int>,int>
	    (IA_boxy_pset(IA_Point<int>(0,0), IA_Point<int>(height-1,width-1)),
	     data, size, 1);
    } else {
	ia_throw(Image_PNMIO_Exception(__FILE__, __LINE__));
	return IA_Image<IA_Point<int>,int>();
    }
}

IA_Image<IA_Point<int>,int>
read_int_PGM(const char *fname, int *maxval)
{
    ifstream	in(fname);
    return read_int_PGM(in, maxval);
}

ostream &write_PGM(const IA_Image<IA_Point<int>,int>&img, ostream &o, unsigned maxval)
{
    // what if image is not dimension 2?

    IA_Set<IA_Point<int> > boxydomain
	= IA_boxy_pset(img.domain().inf(),img.domain().sup());
    IA_Point<int>	width(img.domain().sup()-img.domain().inf()+1);
    const int	binary_pgm = (maxval <= 255);
    if (binary_pgm)
	o<<"P5\n";
    else
	o<<"P2\n";
    o<<width[1] << " " << width[0] << " " << maxval << "\n";
    IA_PSIter<IA_Point<int> >	iter(boxydomain);
    IA_Point<int>	ip;

    int	idx=0;
    int	oldwidth = o.width(7);
    while (iter(ip)) {
	if (binary_pgm) {
	    o.put((char) ( img.domain().contains(ip)?img(ip):0));
	} else {
	    o << ( img.domain().contains(ip)?img(ip):0);
	    if (idx%10 == 0)
		o << '\n';
	    else
		o << ' ';
	}
	idx++;
    }
    return o;
}

ostream & write_PGM(const IA_Image<IA_Point<int>,int>&img, ostream &o)
{
    const unsigned	m = max(img);
    return write_PGM(img, o,m>0?m:1);
}

void write_PGM(const IA_Image<IA_Point<int>,int>&img, const char *fname, unsigned maxval)
{
    ofstream	out(fname);
    write_PGM(img, out, maxval);
}

void write_PGM(const IA_Image<IA_Point<int>,int>&img, const char *fname)
{
    ofstream	out(fname);
    const unsigned	m = max(img);
    write_PGM(img, out, m>0?m:1);
}

//
//
//
