/*******************************************************************************
*                                                                       
*N  {exportraster2bsq.c}  --  Example of how to write the pixel data of a raster to a BSQ file. 
*                                                                   
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
* How to compile:: 
*       This program provides programming examples of 
*
*
*     1. Add {ibm ICU installation directory}/lib to your library paths
*	  2. Add {ibm ICU installation directory}/include to your include paths
*     3. Add {$SDEHOME}/lib to your library paths;
*     4. Compile and link with icuuc.lib and other needed SDE libraries
*E
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*X  Legalese:
*
* Copyright � 2006-2007 ESRI
*
* All rights reserved under the copyright laws of the United States and 
* applicable international laws, treaties, and conventions.
*
* You may freely redistribute and use this sample code, with or without 
* modification, provided you include the original copyright notice and use 
* restrictions.  
*
* Disclaimer:  THE SAMPLE CODE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 
* WARRANTIES, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ESRI OR 
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
* OR BUSINESS INTERRUPTION) SUSTAINED BY YOU OR A THIRD PARTY, HOWEVER CAUSED 
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
* TORT ARISING IN ANY WAY OUT OF THE USE OF THIS SAMPLE CODE, EVEN IF ADVISED 
* OF THE POSSIBILITY OF SUCH DAMAGE.
* 
* For additional information, contact:
* Environmental Systems Research Institute, Inc.
* Attn: Contracts and Legal Services Department
* 380 New York Street
* Redlands, California, 92373
* USA
* 
* email: contracts@esri.com
*
*E
****************************************************************************/

#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "sdeerno.h"
#include "sdetype.h"
#include "sderaster.h"
#include "raster_source.h"


/* Query the raster attribute. */


void main (void) {

	SE_CONNECTION connection;
	SE_ERROR error;
	SE_RASCOLINFO rascol_info;
	CHAR table[SE_MAX_TABLE_LEN],
	*server,
	*instance,
	*database,
	*username,
	*password,
	raster_column[] = "RASTER",
	name_column[] = "NAME",
	**columns,
	**tables,
	name[SE_MAX_COLUMN_LEN];
	SE_STREAM stream;
	SE_QUERYINFO queryinfo;
	LONG rc, tilex, tiley, pixelwidth, pixelheight, pixeloffset_x, pixeloffset_y, numofbands;
	SHORT name_ind, 
	raster_ind;
	SE_RASTERATTR rasterattr;
	SE_RASBANDINFO *rasterband;
	UCHAR *pixel_buffer=NULL;
	CHAR *filename;
	TILEENV tileenv;
	BOOL firstbyte;
	BSQMETADATA bsqmetadata;
	SE_ENVELOPE rwenv;
	LFLOAT rwoffset_x,
	rwoffset_y;
	UCHAR *colormap;
	SE_COLORMAP_TYPE colormap_type;
	SE_COLORMAP_DATA_TYPE colormap_data_type;

	/* test for byte order */

	union {
	LONG testword;
	CHAR testbyte[sizeof(LONG)];
	} endiantest;

	endiantest.testword = 1;
	if (endiantest.testbyte[0] == 1)
	firstbyte = FALSE;
	else
	firstbyte = TRUE;

	/**********************************/
	/* Set the name of the bsq file to be created. */
	/**********************************/

	filename = (CHAR *)malloc(sizeof(CHAR) * strlen("testbsq"));
	strcpy (filename,"testbsq");

	/*****************/
	/* Set the table name */
	/*****************/

	strcpy(table,"myrastertable");


	/*****************/
	/* Set the ArcSDE Server connection parameters */
	/*****************/

	server = "jolex";
	instance = "9000";
	database = NULL;
	username = "mark";
	password = "mark";

	/* Connect to the ArcSDE server */
		rc = SE_connection_create (server,instance,database,username,password,&error,&connection);
	check_error (rc,connection,NULL,"SE_connection_create");

	/************************/
	/* Create the raster structures  */
	/************************/

	/* Create the SE_RASCOLINFO raster column info structure */ 

	rc = SE_rascolinfo_create (&rascol_info);
	check_error (rc, NULL, NULL, "SE_rascolinfo_create");

	/* Create the SE_RASTERATTR raster attribute info structure */

	rc = SE_rasterattr_create (&rasterattr,FALSE);
	check_error (rc,NULL, NULL, "SE_rasterattr_create");

	/********************************/
	/* Setup the stream and query structures */
	/********************************/

	/* Set up the stream query on the raster table */

	rc = SE_stream_create (connection, &stream);
	check_error (rc, connection, NULL, "SE_stream_create");

	/* Create the queryinfo structure */

	rc = SE_queryinfo_create (&queryinfo);
	check_error (rc, connection, NULL, "SE_stream_create");

	/* Add the raster table to the query info structure */

	tables = (CHAR **)malloc(sizeof(CHAR*));
	tables[0] = malloc((strlen(table) +1) * sizeof(CHAR));

	strcpy(tables[0],table);

	rc = SE_queryinfo_set_tables (queryinfo,1,(const CHAR **)tables,NULL); 
	check_error (rc, connection, NULL, "SE_queryinfo_set_table");

	/* Add the raster table's columns to the query info structure */

	columns = (CHAR **)malloc(sizeof(CHAR*) * 2); 
	columns[0] = malloc((strlen(name_column) +1) * sizeof(CHAR));
	columns[1] = malloc((strlen(raster_column) +1) * sizeof(CHAR));

	strcpy (columns[0],name_column);
	strcpy (columns[1],raster_column);

	rc = SE_queryinfo_set_columns (queryinfo,2,(const CHAR **)columns);
	check_error (rc, connection, NULL, "SE_queryinfo_set_table");

	/* Add the queryinfo structure to the stream */

	rc = SE_stream_query_with_info (stream, queryinfo);
	check_error (rc, NULL, stream, "SE_stream_query_with_info");

	/* Free the queryinfo, we are done with it. */

	SE_queryinfo_free (queryinfo);

	/* Bind the output of the stream (the name column and raster column) */
	/* to the variables for display */

	rc = SE_stream_bind_output_column (stream, 1, name, &name_ind); 
	check_error (rc, NULL, stream, "SE_stream_bind_output_column");

	rc = SE_stream_bind_output_column (stream, 2, rasterattr, &raster_ind); 
	check_error (rc, NULL, stream, "SE_stream_bind_output_column"); 

	/* Execute the query */

	rc = SE_stream_execute (stream);
	check_error (rc, NULL, stream, "SE_stream_execute");

	while (SE_SUCCESS == rc) {

		/* Fetch each record of the business table */

		rc = SE_stream_fetch (stream);

		if (SE_FINISHED != rc) { 

			check_error (rc, NULL, stream, "SE_stream_fetch");

			if (raster_ind == SE_IS_NOT_NULL_VALUE) {

				/* Write the pixel data to the bsq file */

				get_tile_envelope (rasterattr, &tileenv);

				rc = writebsqfile ( stream, rasterattr, filename, tileenv);
				check_error (rc,NULL,NULL,"writebsqfile");

				/******************************/
				/* Populate the bsqmetadata structure */
				/******************************/

				/* Set the byte order */

				if (firstbyte)
				bsqmetadata.byteorder = 'M';
				else
				bsqmetadata.byteorder = 'I';

				/* Get the tile size from the raster attribute */
				/* The tile size is expressed as the width and */
				/* height of the tile expressed as a number of */
				/* of pixels */

				rc = SE_rasterattr_get_tile_size (rasterattr,&tilex,&tiley);
				check_error(rc, NULL, NULL, "SE_rasterattr_get_tile_size");

				/* Set the pixel dimenstions */

				bsqmetadata.pixelwidth = tilex * (tileenv.maxx - tileenv.minx + 1);
				bsqmetadata.pixelheight = tiley * (tileenv.maxy - tileenv.miny + 1);
				bsqmetadata.bandrowbytes = bsqmetadata.pixelwidth;

				/* Get the number of bands from the raster attribute. */

				rc = SE_rasterattr_get_num_bands (rasterattr, &bsqmetadata.numbands);
				check_error (rc, NULL, NULL, "SE_rasterattr_get_tile_size");

				/* Get the pixel depth from the raster attribute */

				rc = SE_rasterattr_get_pixel_type (rasterattr, &bsqmetadata.pixeltype);
				check_error (rc, NULL, NULL, "SE_rasterattr_get_tile_size");

				/* Get the optional colormap. Colormaps can only be applied to */
				/* single band rasters whose pixel depth is 8 or 16 bit. */

				if (bsqmetadata.numbands == 1 && 
				(bsqmetadata.pixeltype == SE_PIXEL_TYPE_8BIT_U ||
				bsqmetadata.pixeltype == SE_PIXEL_TYPE_8BIT_S ||
				bsqmetadata.pixeltype == SE_PIXEL_TYPE_16BIT_U ||
				bsqmetadata.pixeltype == SE_PIXEL_TYPE_16BIT_S)) {

				/* Get the raster band */

				rc = SE_rasterattr_get_rasterband_info_list ( rasterattr,
                                			        &rasterband,
                                          			NULL);
				check_error (rc, NULL,NULL, "SE_rasterattr_get_rasterband_info_list");

				/* Get the colormap metadata from the SE_RASBANDINFO structure. */

				rc = SE_rasbandinfo_get_colormap ( rasterband[0],
                               				&colormap_type,
                               				&colormap_data_type,
                               				&bsqmetadata.colormapentries,
                               				&colormap);
				check_error (rc, NULL, NULL, "SE_rasbandinfo_get_colormap");

				/* This example supports only RGB and BYTE colormaps */
				/* If the colormap is not RGB type and BYTE storage */
				/* set the colormap enties to 0. The colormap will not */
				/* be converted */

				if ( colormap_type != SE_COLORMAP_RGB && 
				colormap_data_type != SE_COLORMAP_DATA_BYTE )
				bsqmetadata.colormapentries = 0;

			}

			else

				bsqmetadata.colormapentries = 0;

			/* Set the bitmask to true */

			bsqmetadata.mask = TRUE; 

			/* Get the coordinates of the image extent for the specified pyramid level. */

			rc = SE_rasterattr_get_extent_by_level ( rasterattr,
                                    			&rwenv, 
                                    			&rwoffset_x, 
                                    			&rwoffset_y, 
                                     			tileenv.level);
			check_error (rc, NULL, NULL, "SE_rasterarrtr_get_extent_by_level");

			/* Get the  pixel dimensions of the pyramid level */

			rc = SE_rasterattr_get_image_size_by_level ( rasterattr,
                        		                     &pixelwidth, 
                                        		     &pixelheight, 
		                                             &pixeloffset_x,
                		                             &pixeloffset_y,
                                		             &numofbands,
		                                             tileenv.level);
			check_error (rc, NULL, NULL, "SE_rasterarrtr_get_image_by_level");

			/* Set the metadata for the world file */

			bsqmetadata.xcellsize = (rwenv.maxx - rwenv.minx) / (pixelwidth-1);
			bsqmetadata.ycellsize = -(rwenv.maxy - rwenv.miny) / (pixelheight-1);
			bsqmetadata.xmin = (tileenv.minx * tilex * bsqmetadata.xcellsize) + (rwenv.minx - rwoffset_x);
			bsqmetadata.xmax = ((tileenv.maxx + 1) * tilex * bsqmetadata.xcellsize) + (rwenv.minx - rwoffset_x);
			bsqmetadata.ymax = (rwenv.maxy + rwoffset_y) - (tileenv.miny * tiley * bsqmetadata.ycellsize); 
			bsqmetadata.ymin = (rwenv.maxy + rwoffset_y) + ((tileenv.maxy + 1) * tiley * bsqmetadata.ycellsize);

			/* Write the bsq file to the metadata to the header file, */
			/* colormap file, and world file */

			rc = writebsqmetadata (filename, &bsqmetadata, colormap);
			check_error(rc,NULL,NULL,"writebsqmetadata");

		} /* if(raster_ind==SE_IS_NOT_NULL_VALUE) */

		else
		printf("The raster value is null\n\n");

		}  /* if( SE_FINISHED != ret)  */

	}  /* while (SE_SUCCESS == ret) */

/* We're done. */

rc = SE_stream_free (stream);
check_error (rc, NULL, stream, "SE_stream_free");

/***************************/
/* Free raster column & band info */
/***************************/

SE_rasterattr_free (rasterattr);
SE_rascolinfo_free (rascol_info);

/* Release the ArcSDE connection */

SE_connection_free (connection);
return;


}