/*************************************************************/
/*                                                           */
/* print_raster_attribute - Displays the contents of a       */
/*              SE_RASTERATTR structure, fetched from a      */
/*              raster column.                               */
/*                                                           */
/*              connection <SE_CONNECTION> - The connection  */
/*                          handle.                          */
/*              stream <SE_STREAM> - The data stream         */
/*              raster_attrib <SE_RASTERATTR> - the raster   */
/*                            attribute structure.           */
/*                                                           */
/*************************************************************/

void print_raster_attribute (SE_CONNECTION connection, 
                             SE_STREAM stream, 
                             SE_RASTERATTR raster_attrib) {

	SE_RASBANDINFO *rasband_list, rasband_info;
	SE_RASTERINFO raster_info;
	SE_RASCONSTRAINT rasconstraint;
	SE_RASTILEINFO rastile_info;
	SE_INTERPOLATION_TYPE pyramid_interpolation;
	SE_COMPRESSION_TYPE compression_type;
	LONG rc, band, number_of_bands, *band_numbers, band_width, 
      	     band_height, max_level, tile_width, tile_height, 
      	     pixel_type, raster_id, rascol_id, level,
      	     band_id, row, column, length, tiles, skip_level1,
      	     pixels_per_tile, ioffset_x,ioffset_y;
	CHAR raster_description[SE_MAX_DESCRIPTION_LEN],
      	     raster_column[] = "RASTER", name_column[] = "NAME";
	LFLOAT eoffset_x, eoffset_y;
	SHORT max_tiles, i;
	SE_ENVELOPE raster_env;
	UCHAR *pixel_buffer=NULL;
	TILEENV tileenv;

	/* Initialize the SE_RASCONSTRAINT structure. */

	rc = SE_rasconstraint_create (&rasconstraint);
	check_error (rc, NULL, NULL, "SE_rasconstraint_create");

	/* Initialize the SE_RASTILEINFO structure. */

	rc = SE_rastileinfo_create (&rastile_info);
	check_error (rc, NULL, NULL, "SE_rastileinfo_create");

	/* Print the compression type. */

	rc = SE_rasterattr_get_compression_type ( raster_attrib, &compression_type);
	check_error (rc, NULL, stream, "SE_rasterattr_get_compression_type");

	printf("\n");

	switch(compression_type) {
    		case SE_COMPRESSION_NONE:
            		printf("Image compression type is NONE \n");
            		break;
    		case SE_COMPRESSION_LZ77:
            		printf("Image compression type is LZ77\n");
            		break;
    		case SE_COMPRESSION_JPEG:
            		printf("Image compression type is JPEG\n");
            		break;
    		case SE_COMPRESSION_JP2:
            		printf("Image compression type is JP2000\n");
            		break;
    		default:
            		printf("Unknown image type \n");
 		        break;
	}

	/* Display the image extent. */

	rc = SE_rasterattr_get_extent (raster_attrib, &raster_env);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_extent");

	printf ("Image extent minimum X: %lf \n",raster_env.minx);
	printf ("Image extent minimum Y: %lf \n",raster_env.miny);
	printf ("Image extent maximum X: %lf \n",raster_env.maxx);
	printf ("Image extent maximum Y: %lf \n",raster_env.maxy);

	/* Display the image size. */

	rc = SE_rasterattr_get_image_size (raster_attrib, &band_width, &band_height, &number_of_bands);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_image_size");

	printf ("Image size band width: %d\n",band_width);
	printf ("Image size band height: %d\n",band_height);
	printf ("Image size number of bands: %d\n",number_of_bands);

	/* Display the pixel type */ 

	rc = SE_rasterattr_get_pixel_type (raster_attrib, &pixel_type);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_pixel_type");

	print_pixel_type (pixel_type);

	/* Display raster column id. */

	rc = SE_rasterattr_get_rascol_id (raster_attrib, &rascol_id);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_rasterband_info_list");

	printf ("Raster column ID: %d\n",rascol_id);

	/* Display the raster id */

	rc = SE_rasterattr_get_raster_id (raster_attrib, &raster_id);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_raster_id");

	printf("Raster ID: %d\n\n",raster_id);
	
	/* Display the raster info */

	rc = SE_rasterattr_get_raster_info (raster_attrib, &raster_info);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_raster_info");

	rc = SE_rasterinfo_get_description (raster_info, raster_description);	
	check_error (rc, NULL, NULL, "SE_rasterinfo_get_description");

	/* Display the rasterband info. */

	for (band=1; band<= number_of_bands; band++) {

		rc = SE_rasterattr_get_rasterband_info ( raster_attrib, &rasband_info, band);
		check_error (rc, NULL, NULL, "SE_rasterattr_get_rasterband_info");

		print_rasterbandinfo (connection, rasband_info);

	}

	/* Display the rasterband info from a list. */

	rc = SE_rasterattr_get_rasterband_info_list ( raster_attrib, &rasband_list, &number_of_bands);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_rasterband_info_list");

	for (band=0; band< number_of_bands; band++) 
  		print_rasterbandinfo (connection, rasband_list[band]);

	/* Display the number of bands. */

	rc = SE_rasterattr_get_num_bands (raster_attrib, &number_of_bands);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_num_bands");

	printf ("Number of raster bands: %d\n",number_of_bands);

	rc = SE_rasterattr_get_tile_size ( raster_attrib, &tile_width, &tile_height);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_tile_size");

	pixels_per_tile = tile_width * tile_height;

	/* Display the pyramid info */

	rc = SE_rasterattr_get_pyramid_info ( raster_attrib, &max_level, &skip_level1, &pyramid_interpolation);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_pyramid_info");

	printf("\nPyramid info \n");

	if (skip_level1)  
 		printf ("Skipping the first level.\n");
	else 
 		printf("Do not skip the first level.\n");

	printf ("Max Level: %d \n",max_level);

	switch (pyramid_interpolation){
   		case SE_INTERPOLATION_NONE:
           		printf ("The pyramid does not have an interpolation method.\n");
           		break;
   		case SE_INTERPOLATION_NEAREST:
           		printf ("The pyramid is interpolated with the nearest-neighbor method.\n");
           		break;
   		case SE_INTERPOLATION_BILINEAR:
           		printf ("The pyramid is interpolated with the bilinear method.\n");
           		break;
   		case SE_INTERPOLATION_BICUBIC:
           		printf ("The pyramid is interpolated with the bicubic interpolation method.\n");
           		break;
   		default:
          		printf("The pyramid interpolation method is unknown.\n");
          		break;
	}

	/* Display the maximum pyramid level and the skip the first level */

	rc = SE_rasterattr_get_max_level ( raster_attrib, &max_level, &skip_level1);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_max_level");

	printf("The maximum pyramid level is: %d \n",max_level);

	/************************************************/
	/*  Set the raster constraints, in preparation  */
	/*  of querying and displaying the tile info    */
	/************************************************/

	/* Get the tiles and pyramid level to be displayed */

	get_tile_envelope (raster_attrib, &tileenv);

	/* Display the raster extent for the specified pyramid level */

	rc = SE_rasterattr_get_extent_by_level (raster_attrib, &raster_env, &eoffset_x, &eoffset_y, tileenv.level);
	check_error ( rc, NULL, NULL, "SE_rasterattr_get_extent_by_level");

	printf ("Raster extent minimum X %lf for level %d\n",raster_env.minx,tileenv.level);	
	printf ("Raster extent minimum Y %lf for level %d\n",raster_env.miny,tileenv.level);
	printf ("Raster extent maximum X %lf for level %d\n",raster_env.maxx,tileenv.level);
	printf ("Raster extent maximum Y %lf for level %d\n",raster_env.maxy,tileenv.level);
	printf ("X offset %lf for level %d\n",eoffset_x,tileenv.level);
	printf ("Y offset %lf for level %d\n",eoffset_y,tileenv.level);

	/* Display the image size for each pyramid level */

	rc = SE_rasterattr_get_image_size_by_level ( raster_attrib, 
                                                     &band_width, 
                                                     &band_height,  
                                                     &ioffset_x, 
                                                     &ioffset_y, 
                                                     &number_of_bands,
                                                     tileenv.level);
	check_error (rc, NULL, NULL, "SE_rasterattr_get_image_size_by_level");

	printf ("Raster band width %d for level %d\n",band_width,tileenv.level);
	printf ("Raster band height %d for level %d\n",band_height,tileenv.level);
	printf ("Raster band X offset %d for level %d\n",ioffset_x,tileenv.level);
	printf ("Raster band Y offset %d for level %d\n",ioffset_y,tileenv.level);
	printf ("Number of bands %d\n",number_of_bands);

	rc = SE_rasconstraint_set_envelope ( rasconstraint, 
					     tileenv.minx, 
					     tileenv.minx, 
					     tileenv.maxx, 
					     tileenv.maxy);
	check_error (rc, NULL, NULL, "SE_rasconstraint_set_envelope");

	band_numbers = malloc(sizeof(LONG) * number_of_bands);

	for (i=0; i<number_of_bands; i++) 
		band_numbers[i] = i+1;

	rc = SE_rasconstraint_set_bands ( rasconstraint, number_of_bands, band_numbers);
	check_error (rc, NULL, NULL, "SE_rasconstraint_set_bands");

	free(band_numbers);

	/* Query each band */

	rc = SE_rasconstraint_set_interleave (rasconstraint, SE_RASTER_INTERLEAVE_BSQ);
	check_error (rc, NULL, NULL, "SE_rasconstraint_set_envelope");

	/* Query the specified pyramid level */

	rc = SE_rasconstraint_set_level (rasconstraint, tileenv.level);
	check_error (rc, NULL, NULL, "SE_rasconstraint_set_level");

	/******************************/
	/*  Query the raster tile     */
	/******************************/

	rc = SE_stream_query_raster_tile (stream, rasconstraint);
	check_error ( rc, NULL, stream, "SE_stream_query_raster_tile");

	/********************************************************************/
	/*  Fetch and display the tiles for the all the bands of the image  */
	/********************************************************************/

	max_tiles = number_of_bands * (tileenv.maxx - tileenv.minx + 1) * (tileenv.maxy - tileenv.miny + 1);

	for (tiles=0; tiles<max_tiles; tiles++) {

		rc = SE_stream_get_raster_tile (stream, rastile_info);
		check_error ( rc, NULL, stream, "SE_stream_get_raster_tile");

		/* Display the tile info */

		rc = SE_rastileinfo_get_band_id (rastile_info,&band_id);
		check_error ( rc, NULL, stream, "SE_rastileinfo_get_band_id");

		printf("\n\nTile raster band id: %d\n",band_id);

		/* Print the upper left pixel position, or row column */
		/* of the tile */

		rc = SE_rastileinfo_get_rowcol (rastile_info, &row, &column);
		check_error ( rc, NULL, stream, "SE_rastileinfo_get_rowcol");

		printf ("Tile row: %d column: %d\n",row,column);

		/* Display the tile's the pyramid level */

		rc = SE_rastileinfo_get_level (rastile_info, &level);
		check_error ( rc, NULL, stream, "SE_rastileinfo_get_level");

		printf ("Tile level: %d\n",level);

		/* Display the tile's pixel data */

		rc = SE_rastileinfo_get_pixel_data (rastile_info, (void *)&pixel_buffer, &length);
		check_error ( rc, NULL, stream, "SE_rastileinfo_get_pixel_data");

		print_pixels (pixel_type, pixels_per_tile, pixel_buffer, length);

		printf("\n\n");


	} /* for loop for tiles */

	/* Release the SE_RASCONSTRAINT structure */

	SE_rasconstraint_free (rasconstraint);

	/* Release the SE_RASTILEINFO structure. */

	SE_rastileinfo_free (rastile_info);

	return;

} /* print_raster_attribute */