/************************************************************/
/*         File Name: Util.c                                */
/*         Package:   NIST Generic Utilities                */
/*                                                          */
/*         Contents:  Current_time()                        */
/*                    Syserr()                              */
/*                    Fatalerr()                            */
/*                    PixPerByte()                          */
/*                    SizeFromDepth()                       */
/*                    WordAlignFromDepth()                  */
/*                    WordAlignImage()                      */
/************************************************************/
#include <stdio.h>
#include <math.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <time.h>
#include <sys/resource.h>

#ifndef TRUE
#define TRUE	1
#define FALSE	0
#endif

/************************************************************/
/*         Routine:   Current_Time()                        */
/*         Author:    Michael D. Garris                     */
/*         Date:      6/04/90                               */
/************************************************************/
/************************************************************/
/* Current_Time() gets the time of day from the system and  */
/* returns an ASCII date string without a newline char.     */
/************************************************************/
char *current_time()
{
   long tm;
   char *dptr;

   tm = time((long *)NULL);
   dptr = (char *)ctime(&tm);
   *(dptr + strlen(dptr) - 1) = '\0';
   return(dptr);
}

/************************************************************/
/*         Routine:   Syserr()                              */
/*         Author:    Stan Janet                            */
/*         Date:      12/19/90                              */
/************************************************************/
void syserr(funcname, syscall, msg)
char *funcname, *syscall, *msg;
{
   extern int errno, sys_nerr;
   extern char *sys_errlist[], *getenv();
   int err;

   err = errno;

   (void) fflush(stdout);
   if(msg == NULL)
      (void) fprintf(stderr,"ERROR: %s: %s (%d",funcname,syscall,err);
   else
      (void) fprintf(stderr,"ERROR: %s: %s: %s (%d",funcname,syscall,msg,err);
   if(err > 0 && err < sys_nerr)
      (void) fprintf(stderr,"; %s)\n",sys_errlist[err]);
   else
      (void) fprintf(stderr,")\n");
   (void) fflush(stderr);

   exit(-1);
}

/************************************************************/
/*         Routine:   Fatalerr()                            */
/*         Author:    Stan Janet                            */
/*         Date:      12/19/90                              */
/************************************************************/
void fatalerr(s1,s2,s3)
char *s1, *s2, *s3;
{
   extern char *getenv();

   (void) fflush(stdout);
   if (s2 == (char *) NULL)
      (void) fprintf(stderr,"ERROR: %s\n",s1);
   else if (s3 == (char *) NULL)
      (void) fprintf(stderr,"ERROR: %s: %s\n",s1,s2);
   else
      (void) fprintf(stderr,"ERROR: %s: %s: %s\n",s1,s2,s3);
   (void) fflush(stderr);

   exit(1);
}

/************************************************************/
/*         Routine:   PixPerByte()                          */
/*         Author:    Michael D. Garris                     */
/*                    Darrin Dimmick                        */
/*         Date:      3/07/90                               */
/************************************************************/
/************************************************************/
/* PixPerByte() takes the pixel depth of an image and       */
/* returns the corresponding pixperbyte factor.             */
/************************************************************/
float PixPerByte(depth)
int depth;
{
   float pixperbyte;

   switch(depth){
   case 1:
      pixperbyte = 8.0;
      break;
   case 2:
      pixperbyte = 4.0;
      break;
   case 4:
      pixperbyte = 2.0;
      break;
   case 8:
      pixperbyte = 1.0;
      break;
   case 16:
      pixperbyte = 0.5;
      break;
   case 32:
      pixperbyte = 0.25;
      break;
   default:
      fprintf(stderr,"Depth in PixPerByte() NOT a power of 2.\n");
      exit(-1);
   }
   return(pixperbyte);
}

/************************************************************/
/*         Routine:   SizeFromDepth()                       */
/*         Author:    Michael D. Garris                     */
/*                    Darrin Dimmick                        */
/*         Date:      2/20/90                               */
/************************************************************/
/************************************************************/
/* SizeFromDepth() takes the pixel width of an image scan   */
/* line along with the pixel height of the image, and using */
/* the argument "depth" computes the length of the image in */
/* bytes.                                                   */
/************************************************************/
SizeFromDepth(pixwidth,pixheight,depth)
int pixwidth,pixheight,depth;
{
   int filesize;
   float pixperbyte,PixPerByte();

   pixperbyte = PixPerByte(depth);
   filesize = ((int)(pixwidth/pixperbyte) * pixheight);
   return(filesize);
}

/************************************************************/
/*         Routine:   WordAlignFromDepth()                  */
/*         Author:    Michael D. Garris                     */
/*         Date:      3/02/90                               */
/************************************************************/
/************************************************************/
/* WordAlignFromDepth() takes the pixel width of and image  */
/* and determins the actual aligned pixel width of the      */
/* stored scan line.                                        */
/************************************************************/
int WordAlignFromDepth(pixwidth,depth)
int pixwidth, depth;
{
   int bytesperline, pixperline;
   float pixperbyte,PixPerByte();

   pixperbyte = PixPerByte(depth);
   /* byte align pixels */
   bytesperline = (int)(ceil(pixwidth/(double)pixperbyte));
   /* word aling bytes per line */
   bytesperline = (int)(ceil(bytesperline/2.0)) << 1;
   /* calculate aligned pixel per line */
   pixperline = (int)(bytesperline * pixperbyte);
   return(pixperline);
}

/************************************************************/
/*         Routine:   WordAlignImage()                      */
/*         Author:    Michael D. Garris                     */
/*         Date:      03/07/90                              */
/************************************************************/
/* WordAlignImage() takes an input buffer and word aligns   */
/* the scan lines returning the new scan line pixel width   */
/* and the new byte length of the aligned image.            */
/************************************************************/
int WordAlignImage(adata,awidth,alength,data,width,height,depth)
unsigned char **adata, *data;
int *awidth,*alength,width,height,depth;
{
   int i;
   int bytes_in_line, aligned_bytes_in_line, aligned_filesize;
   int aligned_pixels_in_line;
   unsigned char *inline, *outline;
   float pix_per_byte, PixPerByte();

   bytes_in_line = SizeFromDepth(width,1,depth);
   aligned_pixels_in_line = WordAlignFromDepth(width,depth);
   pix_per_byte = PixPerByte(depth);
   aligned_bytes_in_line = (int)(aligned_pixels_in_line / pix_per_byte);
   if(bytes_in_line == aligned_bytes_in_line)
      return(FALSE);
   aligned_filesize = aligned_bytes_in_line * height;
   (*adata) = (unsigned char *)malloc(aligned_filesize);
   memset((*adata), NULL, aligned_filesize);
   inline = data;
   outline = (*adata);
   for(i = 0; i < height; i++){
      memcpy(outline,inline,bytes_in_line);
      outline += aligned_bytes_in_line;
      inline += bytes_in_line;
   }
   *awidth = aligned_pixels_in_line;
   *alength = aligned_filesize;
   return(TRUE);
}
