#ifndef IMAGE_H
# define IMAGE_H

# ifndef GPK_STD
#  include "gpk_std.h"
# endif

PLAIN_C_START

# include <sys/types.h>

#ifndef MYLIB_H
# include "gpklib.h"
#endif

/* Images can exist in several states:
   1) Uninitialized (which generally means inconsistent and illegal).
      You can call image_empty() to convert to a legal empty image.
      You can call image_constr() to convert to a legal, allocated image.

   2) Empty.  You can't do anything with an empty image, except test it
      with image_is_empty(), or call image_constr().   Image_destr() is
      safe, but has no effect.
      Constructor failures result in an empty image.
      There is no space allocated, so you do not need to free anything.
      Image_is_empty() returns true,
      image_allocated() returns false,
      image_has_data() returns false.

   3) Allocated.  Allocated images always have a property list allocated,
      but do not necessarily have the image data.
      Images are constructed with no data: you add data space
      with image_alloc(), or image_alloc_float().
      If the data allocation fails, you are left with a allocated image
      with zero size.
      For an allocated image,
      image_is_empty() returns false,
      image_allocated() returns true,
      image_has_data() returns true iff data space has been allocated.
      Note that image_has_data() doesn't distinguish between a
      failed allocation on a nonzero-sized image and a successful
      allocation of a zero-sized image.   It's best to test the
      return value of the data allocation functions.
      Note that the image may have a size but no data.

      Image_destr() returns you to an empty image.

      Image_check() returns true for (2) and (3),
      and is probably false for (1).
*/


struct image	{
	short **h; float **H;	/* One or the other, not both. */
	int npts, nlines;

	/* For floats, it is recommended that zscale=1.0, zshift=0.0.
	 * You use these to get the true value from what you find
	 * in h[i][j] or H[i][j], via  Ztrue = zscale*h[i][j] + zshift. */
	double zscale;
	double zshift;	/* Z = zscale*data + zshift. */

	double xscale;	/* Assoc. with npts, second array index. */
	double xcenter;
	double yscale;	/* Assoc with nlines, first array index. */
	double ycenter;
	long constr_time;
	float i_noise;			/* Noise estimate, in real units. */
	struct proplist *prop;
	};

void image_destr(struct image *tthis);
BOOL image_alloc(struct image *tthis, int nlines, int npts);
BOOL image_alloc_float(struct image *tthis, int nlines, int npts);
BOOL image_alloc_1(struct image *tthis, int nlines, int npts, short **d);
void image_setzscale(struct image *tthis, double value, C char * units, double offset);
void image_addlabel(struct image *tthis, C char *label);

BOOL image_allocated(C struct image *tthis);
BOOL image_is_empty(C struct image *tthis);
BOOL image_has_data(C struct image *tthis);

/* Use on uninitialized structs, not on allocated images: */
void image_empty(struct image *tthis);

void image_set(struct image *tthis, float val);
void image_set_time(struct image *tthis, long t);
BOOL image_check(C struct image *thus);
BOOL image_force_short(struct image *p);
BOOL image_force_float(struct image *p);
BOOL image_normalize(struct image *p);
void image_insert(struct image *bkgr, C struct image *insert, int l0, int p0);


#ifdef __cplusplus
void image_clear_TT(image *o);
void image_xfer_TT(image *o, C image& dd, int from_col, int to_col);
int image_lookup_TTYPE(C struct image &dd, C char *scol);
struct image image_copy_float(C struct image& in);
struct image image_copy_short(C struct image& in);
struct image image_copy(C struct image& in);
struct image image_gcopy(C struct image& in, int l1, int p1, int l2, int p2, float value);
#endif

struct image delta_fcn(int nl, int np);
struct image delta_fcn_float(int nl, int np);

/* obsolete: */
void image_set_cur(struct image *tthis, double noise, double crrnt);
void image_constr(struct image *tthis, int angle, double scale,
					C char *xyu, C char *imagetype);
void image_constr_from(struct image *tthis, C struct image* source);
void image_constr_all(struct image *tthis,
				double xc, double yc,
				double xs, C char *xu, double ys, C char *yu,
				C char *imagetype);

#define NPL	4

struct multi_image	{
	/* enum scantype_e type; */
	struct image image[NPL];
	/* struct plot  plot[NPL]; */
	int n_image;
	};

void multi_image_constr(struct multi_image *tthis, int n);
void multi_image_empty(struct multi_image *tthis);
void multi_image_set(struct multi_image *tthis, float val);
void multi_image_destr(struct multi_image *tthis);
BOOL multi_image_alloc(struct multi_image *tthis, int nlines, int npts);
BOOL multi_image_alloc_float(struct multi_image *tthis, int nlines, int npts);
BOOL multi_image_allocated(C struct multi_image *tthis);
void multi_image_set_delay(struct multi_image *tthis, double delay);
void multi_image_set_time(struct multi_image *tthis, long t);
void multi_image_set_cur(struct multi_image *tthis, double noise, double crrnt);
BOOL multi_image_check(C struct multi_image *p);
BOOL multi_image_force_short(struct multi_image *p);
BOOL multi_image_force_float(struct multi_image *p);
BOOL multi_image_normalize(struct multi_image *p);

PLAIN_C_END

#endif
