/*--------------------------------------------------------------------------*
 * 
 * This file contains the basic conversion utilities.
 *
 *  hdf_to_pixrect: Reads an hdf file and returns a pixrect.
 *  pixrect_to_hdf: Takes a pixrect and writes to an hdf file.
 *  hdf_to_rasterfile: Reads an hdf file and writes to a raster file stream.
 *  rasterfile_to_hdf: Reads a raster file stream and writes to an hdf file.
 *
 *
 * 				NO WARRANTY
 *  
 *  This software is distributed free of charge and is in the public domain.
 *  Anyone may use, duplicate or modify this program.  Thinking Machines
 *  Corporation does not restrict in any way the use of this software by
 *  anyone.
 *  
 *  Thinking Machines Corporation provides absolutely no warranty of any kind.
 *  The entire risk as to the quality and performance of this program is with
 *  you.  In no event will Thinking Machines Corporation be liable to you for
 *  damages, including any lost profits, lost monies, or other special,
 *  incidental or consequential damages arising out of the use of this program.
 * 
 * Jim Salem - Thinking Machines - 9/26/89 (Initial version)
 * Please keep this notice with the file.
 * 
 * Peter Webb - NCSA - 10/14/90
 *  - New error handling.
 *  - Removed dependencies on SUN libraries.
 *  - Integrated into Reformat
 *
 *--------------------------------------------------------------------------*/

/* Package include files */

#include "sun2ri8.h"
#include "types.h"      /* Package-wide type definitions */
#include "error.h"      /* Error codes */
#include "extern.h"     /* External routines and global variables */
#include "reformat.h"   /* Package-wide contants */


static void free_colormap_arrays (colormap)
     colormap_t *colormap;
{
  if (colormap->type != RMT_NONE) {
    free (colormap->map[0]);
    free (colormap->map[1]);
    free (colormap->map[2]);
    colormap->type = RMT_NONE;
  }
}

/* Takes out the leftover bytes on the end of each row of a pixrect array */

static void  compress_pixrect_array (dest, source, dest_width, source_width,
				     height)
     char *source,*dest;
     int source_width, dest_width, height;
{
  int i;
  for (i = 0; i< height; ++i, dest += dest_width, source += source_width)
    memcpy (dest, source, dest_width);
}  

#ifdef notdef

struct pixrect *
  hdf_to_pixrect(hdf_file, index, colormap)
char *hdf_file;
int index;
colormap_t *colormap;
/* This reads in an hdf image, allocates a pixrect to hold it, and writes it 
   into the pix rect.
   If the HDF image has a palette, colormap arrays are allocated for it and 
   the colormap structure is updated.
   [Use free_colormap_arrays to free up the space.]

   index identifies the particular image within the hdf file (normally 0)
   If index is -1, the hdf file is not reset and the next image is read.
   Returns the pixrect on success or 0 on error; check the values of DFerror 
     or errno.
  */
{
  struct pixrect  *pixrect;
  int xdim, ydim, ispalette, i;
  unsigned char palette[HDF_COLORMAP_SIZE][3];

  /* Invalidate colormap (to avoid inadvertent frees in the case of an error) */
  colormap->type = RMT_NONE;
  colormap->length = 0;

  /* First, point to the right place in the image file */
  if (index != -1) {
    if (DFR8restart()) ERROR_RETURN;
    for (i = 0; i < index; ++i)
      if (DFR8getdims (hdf_file,&xdim,&ydim,&ispalette)) ERROR_RETURN;
  }
  /* Read the size */
  if (DFR8getdims (hdf_file,&xdim,&ydim,&ispalette)) ERROR_RETURN;

  /* Allocate a pixrect */
  pixrect = mem_create (xdim, ydim, 8);

  /* Get the data */
  if (DFR8getimage (hdf_file, (char *) mpr_d(pixrect)->md_image,
		    mpr_linebytes (xdim, 8), ydim, (unsigned char *) palette))
    {/* Error occurred, deallocate and return */
      pr_destroy(pixrect);
      ERROR_RETURN;
    }

  /* Fill the colormap structure (if necessary) */
  if (colormap && ispalette) {
    unsigned char *map[3];
    int map_num;

    /* Allocate the map arrays */
    map[0] = (unsigned char *) malloc(HDF_COLORMAP_SIZE);
    if (!map[0]) {pr_destroy(pixrect); ERROR_RETURN;}
    map[1] = (unsigned char *) malloc(HDF_COLORMAP_SIZE);
    if (!map[1]) {free(map[0]); pr_destroy(pixrect); ERROR_RETURN;}
    map[2] = (unsigned char *) malloc(HDF_COLORMAP_SIZE);
    if (!map[2])
      {free(map[1]); free(map[0]); pr_destroy(pixrect); ERROR_RETURN;}
	
    /* reorder the data and add pointers to color map struct */
    for (map_num = 0; map_num < 3; ++map_num) {
      colormap->map[map_num] = map[map_num];
      for (i = 0; i < HDF_COLORMAP_SIZE; ++i)
	(map[map_num])[i] = palette[i][map_num];
    }
    /* Change colormap type */
    colormap->type = RMT_EQUAL_RGB;
    colormap->length = HDF_COLORMAP_SIZE;
  }
  /* Done ! */
  return pixrect;
}

#endif

/*--------------------------------------------------------------------------*/

    
/*--------------------------------------------------------------------------*/

#ifdef notdef 

int
  hdf_to_rasterfile (hdf_file, index, ras_file)
char *hdf_file;
int index;
FILE *ras_file;
/* This reads in an hdf image and writes it to a rasterfile.
   index identifies the particular image within the hdf file (normally 0)
   If index is -1, the hdf file is not reset and the next image is read.

   Returns non-zero on success or 0 on error; check the values of DFerror 
     or errno.
  */
{
  struct pixrect *pixrect;
  colormap_t colormap;
  int ret;

  pixrect = hdf_to_pixrect(hdf_file, index, &colormap);
  if (!pixrect) ERROR_RETURN;

  ret = pr_dump(pixrect, ras_file, &colormap, RT_STANDARD, 0);
  pr_destroy(pixrect);
  free_colormap_arrays(&colormap);
  if (ret)
    return False;
  else
    return True;
}
#endif

/* Convert a pixrect and colormap into an image and a palette */

static ErrorCode PixrectToHdf(pixrect, colormap, info, header)
     byte *pixrect;
     byte *colormap;
     FileInfo info;
     SunRasterInfo *header;
{
  int xdim, ydim, ret;
  char *array, *temp_array;
  int i, c, len;

/* Check depth */

  if (header->depth != 8)
    return(err_msg(Pixrect2HDF, ImageTooComplex));

/* initialize */

  xdim = header->pr_width;
  ydim = header->pr_height;

  array = ((char *) mpr_d(pixrect)->md_image)
      + mpr_d(pixrect)->md_linebytes * mpr_d(pixrect)->md_offset.y
      + mpr_d(pixrect)->md_offset.x;

  temp_array = NULL;
    
/* Handle colormap */

  if (colormap && header->maptype == RMT_EQUAL_RGB)
    {
      len = header->maplen;
      if (len > (MAX_PAL/3)) len = (MAX_PAL/3);

      for (i = 0; i < len; ++i)
	for (c = 0; c < 3; ++c)
	  info->palette[i][c] = (colormap->map[c])[i];

/* Fill in empty slots with white. */

      for (i = len; i < (MAX_PAL/3); ++i)
	for (c = 0; c < 3; ++c)
	  palette[i][c] = 255;

/* Set the palette */

      info->values |= (BitMask)CvtPalette;
    }
  else

/* If the image width differs from the array width, squish it down */

  if (xdim != mpr_d(pixrect)->md_linebytes) {
    temp_array = malloc(xdim * ydim);
    if (!temp_array) ERROR_RETURN;
    compress_pixrect_array (temp_array, array,
			    xdim, mpr_d(pixrect)->md_linebytes, ydim);
    array = temp_array;
  }

/* Now write the image */

  info->height = ydim;
  info->width = xdim;
  info->image = array;

  info->values |= (BitMask)CvtImage;

/* Done ! */

  return (AllOk);
}

/* Read in the rasterfile */

static ErrorCode LoadPixrect(name, header, pixrect, colormap)
     char *name;
     SunRasterInfo *header;
     unsigned char **pixrect, **colormap;
{
  FILE *fp;
  int ret;
  ErrorCode error;

/* Open the sun raster file */

  fp = fopen(ras_file, "r");
  if (fp == NULL) return(err_msg(LoadPix, InputOpenFailed));

/* Read in the header */

  ret = fread(header, sizeof(header), 1, fp);
  if (ret != 1) return(err_msg(LoadPix, FileSystemError));

/* Check the magic number */

  if (header->magic != MAGIC)
    return(err_msg(LoadPix, BadFileData));

/* Get the colormap, if there is one. */

  if (header->type != RMT_NONE)
    if (header->maplen != 0)
      {
	*colormap = (byte *) malloc(header->maplen*sizeof(byte));
	ret = fread(*colormap, sizeof(byte), header->maplen, fp);
	if (ret != header->maplen) return(err_msg(LoadPix, FileSystemError));
      }
    else return(err_msg(LoadPix, CorruptedInputFile));

/* Snarf in the image */

  if (header->length == 0)
    if (header->type == RT_BYTE_ENCODED)
      {
	free(*colormap);
	return(err_msg(LoadPix, CorruptedInputFile));
      }
    else header->length = header->width * header->height;

  *pixrect = (byte *)malloc(header->length*sizeof(byte));
  ret = fread(*colormap, sizeof(byte), header->length, fp);
  if (ret != header->length) return(err_msg(LoadPix, FileSystemError));      
  return(AllOk);
}


/* This reads in a rasterfile and returns the image and color map in the 
 * info structure.
 */

ErrorCode SunToRI8 (ras_file, info)
char *ras_file;
FileInfo info;
{
  SunRasterInfo header;
  byte *pixrect, *colormap;
  int ret;

/* Read in the pixrect file */

  if ((error = LoadPixrect(ras_file, &header, &pixrect, &colormap)) != AllOk)
    return(error);

/* Convert the pixrect data and color map to and HDF RI8 and palette */

  if ((error = PixrectToHdf(pixrect, colormap, info)) != AllOk return(error);

/* Free up the memory */

  pr_destroy (pixrect);
  free_colormap_arrays(&colormap);
  return error;
}





