
/****************************************************************************
 * NCSA HDF                                                                 *
 * Scientific Data Technologies                                             *
 * National Center for Supercomputing Applications                          *
 * University of Illinois at Urbana-Champaign                               *
 * 605 E. Springfield, Champaign IL 61820                                   *
 *                                                                          *
 * For conditions of distribution and use, see the accompanying             *
 * hdf/COPYING f.                                                        *
 *                                                                          *
 ****************************************************************************/

#include <hdf5.h>
#include "H5HL.h"
#include "pal_rgb.h"
#include <stdlib.h>


#define DATA_FILE1  "image8.txt"
#define DATA_FILE2  "image24pixel.txt"
#define DATA_FILE3  "image24plane.txt"

#define IMAGE1_NAME  "Image8bit"
#define IMAGE2_NAME  "Image24bitpixel"
#define IMAGE3_NAME  "Image24bitplane"


int      read_data( const char* file_name );
int      read_palette(char *fileName, TRwPaletteEntry *palette, int palette_size);
hsize_t  width, height;
unsigned char *image_data = 0;            


int main( void )
{
 hid_t      file_id;
 hsize_t    pal_dims[2];
 herr_t     status; 
	int        i, n;
	unsigned char   pal[256*3]; /* buffer to hold an HDF5 palette */
	TRwPaletteEntry PAL[256];   /* buffer to hold a PAL file palette */

	/* Make a grey palette */
	for ( i=0, n=0; i<256*3; i++)
	{
		if (i%3==0) n++;
		pal[i]=n-1;
	}


 /* Create a new HDF5 file using default properties. */
 file_id = H5Fcreate( "hdf5images.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );

 /* Read first data file */   
 read_data( DATA_FILE1 );
   
 /* Initialize the palette data */
 pal_dims[0] = 256;
 pal_dims[1] = 3;
 
 /* Make dataset */
 status=H5IMmake_image_8bit( file_id, IMAGE1_NAME, width, height, image_data );

 /* Make a palette */
 status=H5IMmake_palette( file_id, "Rainbow pallete", pal_dims, pal_rgb );

 /* Attach a palette to the image dataset */
 status=H5IMlink_palette( file_id, IMAGE1_NAME, "Rainbow pallete" );

	/* Make a palette */
 status=H5IMmake_palette( file_id, "Grey pallete", pal_dims, pal );

	/* Attach the grey palette to the image dataset */
 status=H5IMlink_palette( file_id, IMAGE1_NAME, "Grey pallete" );

/*-------------------------------------------------------------------------
 * read a PAL file and attach the palette to the HDF5 file
 *-------------------------------------------------------------------------
 */

	/* read a PAL file */
 read_palette("sepia.pal", PAL, sizeof(PAL));

	/* transfer to the HDF5 buffer */
	for ( i=0, n=0; i<256*3; i+=3, n++)
	{
		pal[i]  =PAL[n].r;
		pal[i+1]=PAL[n].g;
		pal[i+2]=PAL[n].b;
	}

	/* Make a palette */
 status=H5IMmake_palette( file_id, "sepia", pal_dims, pal );

	/* Attach the palette to the image dataset */
 status=H5IMlink_palette( file_id, IMAGE1_NAME, "sepia" );

/*-------------------------------------------------------------------------
 * read a PAL file and attach the palette to the HDF5 file
 *-------------------------------------------------------------------------
 */

	/* read a PAL file */
 read_palette("earth.pal", PAL, sizeof(PAL));

	/* transfer to the HDF5 buffer */
	for ( i=0, n=0; i<256*3; i+=3, n++)
	{
		pal[i]  =PAL[n].r;
		pal[i+1]=PAL[n].g;
		pal[i+2]=PAL[n].b;
	}

	/* Make a palette */
 status=H5IMmake_palette( file_id, "earth", pal_dims, pal );

	/* Attach the palette to the image dataset */
 status=H5IMlink_palette( file_id, IMAGE1_NAME, "earth" );

/*-------------------------------------------------------------------------
 * True color image example with pixel interlace
 *-------------------------------------------------------------------------
 */
 read_data( DATA_FILE2 );
 
 /* Make dataset */
 status=H5IMmake_image_24bit( file_id, IMAGE2_NAME, width, height, "INTERLACE_PIXEL", image_data );

/*-------------------------------------------------------------------------
 * True color image example with plane interlace
 *-------------------------------------------------------------------------
 */

 read_data( DATA_FILE3 );
 
 /* Make dataset */
 status=H5IMmake_image_24bit( file_id, IMAGE3_NAME, width, height, "INTERLACE_PLANE", image_data );
 
 /* Close the file. */
 H5Fclose( file_id );
 
 return 0;
}


/*-------------------------------------------------------------------------
 * read_data
 * utility function to read ASCII image data
 * the files have a header of the type
 *
 *   components
 *   n
 *   height
 *   n
 *   width
 *   n
 * 
 * followed by the image data
 *
 *-------------------------------------------------------------------------
 */

int read_data( const char* file_name )
{
 int    i, n;
 int    color_planes;
 char   str[20];
 FILE   *f;
 int    w, h;

 f = fopen( file_name, "r");
 if ( f == NULL )
 {
  printf( "Could not open file %s. Try set $srcdir \n", file_name );
		return -1;
	}
 fscanf( f, "%s", str );
 fscanf( f, "%d", &color_planes );
 fscanf( f, "%s", str );
 fscanf( f, "%d", &h); height = (hsize_t)h;
 fscanf( f, "%s", str );
 fscanf( f, "%d", &w); width = (hsize_t)w;

 if ( image_data )
  free( image_data );

 image_data = (unsigned char*) malloc ( (size_t)width * (size_t)height * color_planes * sizeof( unsigned char ));

 for (i = 0; i < h * w * color_planes ; i++)
 {
  fscanf( f, "%d",&n );
  image_data[i] = (unsigned char)n;
 }
 fclose(f);

 return 1;

}



/*-------------------------------------------------------------------------
 * read_palette
 * Read an ASCII palette file .PAL into an array
 * the files have a header of the type
 *
 * Parameters:          filename - name of file to read.
 *                      palette - array of RwPalleteEntry to store the
 *                                read palette.
 *                      palette_size - number of elements in 'palette' array
 *
 * Return Value:        Returns number of entries read or 0 on error
 *                      palette contains palette.
 *
 *-------------------------------------------------------------------------
 */


int read_palette(char *fileName, TRwPaletteEntry *palette, int palette_size)
{
	
	FILE          *file;
 char          buffer[80];
 int           i;
 unsigned int  red;
 unsigned int  green;
 unsigned int  blue;
	int 		  numEntries;
	
 // Ensure the given palette is valid.
	
 if (!palette)
		return(0);
	
 // Open the input file.
	
	if (!(file = fopen(fileName, "r")))
  return(0);
	
 // Read the file ident string.
	
	if (fgets(buffer, sizeof(buffer), file) == NULL)
	{
		fclose(file);
		return(0);
	}
	
 // Ensure it matches the palette file ident string. 
	
 if ( strncmp(buffer, STRING_JASC, sizeof(STRING_JASC) - 1) != 0 && //and
		strncmp(buffer, STRING_CWPAL, sizeof(STRING_CWPAL) - 1) != 0 )
		
	{
		fclose(file);
  return(0);
 }
	
	
	// Read the version string. 
	
	if (fgets(buffer, sizeof(buffer), file) == NULL)
 {
		fclose(file);
  return(0);
 }
	
 // Ensure it matches the palette file version string. 
	
	if ( strncmp(buffer, VERSION_JASC, sizeof(VERSION_JASC) - 1) != 0 && 
		strncmp(buffer, VERSION_CWPAL, sizeof(VERSION_CWPAL) - 1) != 0 )
 {
		fclose(file);
  return(0);
 }
	
	
	// Read the number of colors. 
 if (fgets(buffer, sizeof(buffer), file) == NULL)
 {
		fclose(file);
  return(0);
 }
	
	
 // Extract the number of colors. 
	
	//Check for missing version or number of colors
	//In this case it reads the first entry
	if ( strlen( buffer ) > 4 ) //null counts
 {
		fclose(file);
  return(0);
 }
	
 if (sscanf(buffer, "%d", &numEntries) != 1)
 {
		fclose(file);
  return(0);
 }
	
	
	// Ensure there are a sensible number of colors in the palette. 
 if ((numEntries < 0) || (numEntries > 256) || (numEntries > palette_size))
 {
		fclose(file);
  return(0);
 }
	
	
	// Read the palette entries. 
	
	for (i = 0; i < numEntries; i++)
	{
		// Extract the red, green and blue color components. 
		
		if (fscanf(file, "%u %u %u", &red, &green, &blue) != 3)
		{
			fclose(file);
			return(0);
		}
				
		// Store this palette entry. 
		
		palette[i].r = (unsigned char)red;
		palette[i].g = (unsigned char)green;
		palette[i].b = (unsigned char)blue;
	}
		
	//The palette was read successfully - close the file and return the new palette.
	
	fclose(file);
	
	return numEntries;
}



