/****************************************************************************
 *   graster_adt.h  :  header file for raster ADTs
 *   
 *   Change Log :
 *		   06-12-1996 Initial version,  Liujian Qian
 *		   07-07-1997 Major rewriting, Liujian Qian
 *
 *   $Id: gadt_raster.h,v 1.9 1998/12/10 00:11:31 qian Exp $
 ***************************************************************************/

#ifndef _GRASTER_H_
#define _GRASTER_H_

#include "gslab.h"
#include "grasterio.h"
#include "gadt.h"

/**
 * the header structure for a raster object.
 */
struct GRasterMeta
{
    double 	geo_xlow;	//longitude/latitude
    double 	geo_ylow;
    double 	cell_size_x;	//size of each cell along x/lon dimension
    double 	cell_size_y;	//size of each cell along y/lat dimension
    GeoUnit	cs_unit; 	//unit for cell size
    
    int 	x_dim; 		//sizes at x and y dimensions (in # of cells)
    int 	y_dim;		
    int 	easting;	//transform from real world coordnate to raster coords.
    int 	northing;	//
    int 	flags;		//flags for the raster
    char 	key[64];	//a key (id) string for the raster/grid

    GCellType 	ctype;
    GCellValue 	max_val;	//some statistics of the raster
    GCellValue 	min_val;
    GCellValue 	avg_val;
    GCellValue 	ignore_val; 	//value to be ignored (background or nil)
};

struct GRasterHdr
{
    GRasterMeta meta;
    
    int 	n_slabs;	//number of slabs for the raster object.
    GSlabDesc* slab_tbl;   //the slab table

    GRasterHdr():slab_tbl(0)  { init(); }
    ~GRasterHdr();
    
    void   	  init(void);		
    int    	  getPSize(void) const;
    static int    fixedSize(void);
    
    Result 	  pack(DataPipe& p);	//store header into a pipe
    Result 	  unpack(DataPipe& p);	//load header form a pipe
    Result 	  allocSlabTable(int n);

    Result   	  partialLoad(DataPipe& p); //used only by GRaster::loadFromFile()

    GRasterHdr&    operator= (const GRasterHdr&);
};

ostream& 	operator<<(ostream& s, const GRasterHdr& hdr);


/**
      ADT for raster data.


 A raster is a regular grid of cells which are divided into "morton slabs" of fixed
 size. Each slab is then stored individualy  as one record.  Besides
 slabs, a raster object also contains a header which holds the meta
 information of the raster object (such as size, number of slabs, file
 id where the slabs are stored, and flags for compression etc). The header
 of a raster also contains the indexing information to the records of
 individual Slabs, so that individual slab can be retrieved quickly without
 scanning the whole raster data. 

 8, 16, 24 and 32-bit rasters are all supported.

 The raster can be compressed upon request, in which case every slab
 will have their data compressed using the deflate algorithm of zlib.
 This compress/uncompress procedure is transparent to GRaster users.
 */
class GRaster : public GSpatial
{
    friend class GSlab;
    
    enum {ZIP_F 	= 1<<0};	 //flag for zipped/unzipped storage
    enum {GRAY_F	= 1<<1};	 //check if a gray image or color image

    enum {cache_sz = 1};
    
private:
    GRasterHdr	hdr;    
    //GSlab*	slab_cache[cache_sz];  	  //slabs cache.

    GSlab	*cache_slab;

    GRasterIO 	io;

    // where to hold the hit-slabs 
    DataPipe 	hits_pipe;
    char 	*slab_line_buf;

    bool 	base_io;	//true if using base RasterIO for i/o
    
public:
    enum FileType { ascii=0, binary=1 };
    
public:
    
    /**
     * initalize with specific bit depth.
     * 16 bits for each value
     *
     */
    GRaster(int _bpp =16);  
    /**
     * initialize the raster with a pipe containing header info
     *
     */
    GRaster(DataPipe& hdr_p);
    /**
     * initialize the raster; open and load the file containing 
     * previously stored raster data
     */
    GRaster(const char* file);
    /**
     * copy ctor
     */
    GRaster(const GRaster& r);
    /**
     * assignment operator
     */
    GRaster& operator= (const GRaster& r);
    /**
     */ 
    virtual ~GRaster();

    //====================================================
    //====
    //====  common methods
    //====
    //====================================================
    
    virtual GType  	type() const { return _Raster; }
    virtual uint32  	getPSize() const;
    virtual Result 	init(void);
    virtual Result 	mbr(GRect& box) const;
    virtual GADT* 	clone() const { return new GRaster; }
    virtual int		cmp(const GADT& a) const;
    /**
     * print (only) the raster header
     */
    friend ostream& 	operator<<(ostream& s, const GRaster& ras);

    /**
     * generate a raster object out of a user string; the format of the
     * string: "w h V00 V01 V02... V10 V11 V12... Vwh" where w and h
     * are the width and height of the user supplied grid
     */
    virtual Result 	input     (const char* in);
    /**
     * output the raster object into a user string.
     * the format is the same as for input.
     */
    virtual Result 	output    (char*& out);
    /**
     * pack the (zipped) raster data into a pipe	
     */
    virtual Result	pack	  (DataPipe& p);
    /**
     * unpack the (zipped) data from a pipe
     */
    virtual Result 	unpack      (DataPipe& p);

    /**
     * store the (zipped) raster data into a file
     */
    virtual Result  	storeToFile  (const char* fname);
    /**
     * load raster data from a previously stored raster file
     */
    virtual Result	loadFromFile (const char* fname);
    /**
     * import user specified raster data file; it may be a text file or
     * binary. The user specify the size (in byte) for the values. The width
     * and height of the raster should also be specified. The user file
     * should contain nothing but the data itself. The fifth parameter indicates
     * whether the result raster object should be zipped or not. Note that a raster
     * image can only have ineger values.
     */
    virtual Result	import    (const char* fname, int w, int h, 
				   FileType t=ascii,  int val_sz=16, 
				   bool zipit=0);

    virtual Result	scale      (double xf, double yf, double zf=1);
    virtual Result      translate  (double xf, double yf, double zf=1);    
    virtual Result	rotate	   (double, bool);
    virtual Result	transform  (const GMatrix&);

    virtual int		intersects (const GSpatial&) const;
    virtual int		covers     (const GSpatial&) const;
    

    /**
     * return number of cells on x dimension
     */
    inline int		width() {return hdr.x_dim;}
    /**
     * return number of cells on y dimension
     */
    inline int		height() {return hdr.y_dim;}
    /**
     * retu4n maximum value
     */
    inline double	max()   {return (double)(hdr.max_val);}
    /**
     * return maximum value for given region
     */
    double              max(GRect& r);
    /**
     * return minimum value
     */
    inline double	min()	{return (double)(hdr.min_val);}
    
    /**
     * return min value for given region
     */
    double              min(GRect& r);
    /**
     * return average val
     */
    inline double	avg()	{return (double)(hdr.avg_val);}
    /**
     * return average value for given region
     */
    double              avg(GRect& r);
    /**
     * return the value to be ignored (for background/non-value)
     */
    inline int  	ignore() const {return hdr.ignore_val;}
    /**
     * set  ignorant value
     */
    inline void		setIgnoreValue(int v) {	hdr.ignore_val=v; }
    /**
     * return the easting value
     */
    inline int 		easting() const {return hdr.easting;}
    /**
     * return the northing value
     */
    inline int		northing() const {return hdr.northing;}
    /**
     * set easting value
     */
    inline void 	setEasting(int e) { hdr.easting = e; }
    /**
     * set northing value
     */
    inline void 	setNorthing(int n) {hdr.northing = n; }

    /**
     * set the factor
     */
    inline void 	setFactor (double f) {hdr.factor = f;}
    /**
     * get the factor
     */
    inline double 	factor() {return hdr.factor; }

    /**
     * set geographic coordinates for lower corner
     */
    inline void	 	setGeoLow (int glx, int gly) {hdr.geo_xlow = glx;
                                               hdr.geo_ylow = gly; }
    /**
     */ 
    inline void  	geoLow (int & glx, int & gly) { 
	glx = hdr.geo_xlow, gly=hdr.geo_ylow;}
    /**
     * set the size of a pixel (cell)
     */
    inline void  	setCellSize (int sz) {hdr.cell_size = sz;}
    /**
     * get the size of a pixel
     */ 
    inline int   	cellSize () {return hdr.cell_size; }
    /**
     * return number of slabs.
     */
    inline int		numSlabs() {return hdr.n_slabs;}
    /**
     * set a pixel value
     */
    virtual Result 	setPixel(int val, int x, int y);
    /**
     * get the value of a pixel. Note that the value
     * returned is not adjusted. To get the true value at
     * the pixel you must divide it by  factor() !
     */
    virtual int		getPixel(int x, int y);
    /**
     * return a pointer to the slab with given id
     */
    GSlab*		getSlab(int idx); 
    /**
     * return a scan line of the raster
     */
    virtual Result 	scanLine(int y, char* line_buf);
    /**
     * convert the raster to linear array of float-value
     * with row-major order
     */
    virtual Result      toRowOrder(float * va) ;
    
    /**
     * set the raster to be zipped (compressed)
     */
    void		setZipped(void) {hdr.flags |= ZIP_F; }
    /**
     * return true if the raster is zipped on storage
     */
    bool		zipped(void) { return hdr.flags & ZIP_F; }
    /**
     * calculate the statistics (min, max, average) of the
     * raster. These statistics are updated and stored permanantly
     * in the raster header.
     */

    virtual Result	updateStats();
protected:

    /**
     * retrieve the slab with given index; in GFC  it is retrieved 
     * from a previously written raster data file;  in a DB contecxt
     * the programmer can inherit  this class and override this
     * method so that individual slab will be fetched from the db (out of
     * a table for  instance.)
     */
    virtual Result	loadSlab (int idx);

    /**
     * store an individual  slab into the  data file; (or to a db  table
     * if the programmer choose to do so in an overriden function. return
     * the (zipped) size actulay stored into the file. or -1 if failed.
     */
    virtual int		storeSlab(GSlab& s);
    virtual Result	importAscii(const char* fname);
    virtual Result	importBin (const char* fname);


private:
    //
    // return the cell-value-size for a cell (4 bytes for 24/32 bpp)
    //
    inline int		cvs() const { return (hdr.bpp==8)?1:(hdr.bpp==16)?2:4;}
    
    // return the owning slab's order for a given cell
    //
    int			whichSlab (int x, int y);
    
    // set an array indicating the slabs overlaping the given rectangle;
    // return the number of such slabs.
    //
    int			findHits(GRect& window, DataPipe& hits_p);
    
    Result		updateStats(const GSlab& slab);
    
}; // class GRaster



#endif 

Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999