/* pict2ri8.c
 * Convert a PICT file to an HDF file.
 *
 * Original?
 * Modified by Peter Webb, Summer 1990.
 */

/* Standard Include files */

#include <stdio.h>
/* #include <Quickdraw.h>
#include <Types.h>
#include <Files.h>
#include <FCntl.h>
*/

/* Package Include files */

#include "reformat.h"
#include "extern.h"
#include "types.h"
#include "error.h"

/* Static variables */

static PixMapHandle tempPM;
static Boolean rstrFound;

/*
 *	BadPicture (CopyPic)
 *
 *	This routine will check the picture rectange to see if the picture
 * 	is valid or not. 
 *
 */
 
Boolean BadPicture (CopyPic)
	PicHandle CopyPic;
{
	if (EmptyRect (&(**CopyPic).picFrame))
		return true;
	else
		return false;
}

/*
 *	
 *	CTab2CTab
 *	
 *	This routine simply duplicates the source color table passed in to the 
 *	destination color table if FillChar is -1, otherwise it fills the 
 *      destination table with the entry indexes by FillChar.
 *
 */

static void CTab2CTab(source, destin, Fill)
	CTabHandle source, destin;
	int Fill;
{
	register ColorSpec * src, * dest;
	register int * index;
	int i;
	
/* duplicate the other fields. */
	
	(**destin).ctSeed = (**source).ctSeed;
	(**destin).ctFlags = (**source).ctFlags;
	(**destin).ctSize = (**source).ctSize;

/* do we want to set them all to one color?  */

	if (Fill == -1)
		index = &i;
	else
		index = &Fill;

/* copy the color table. */
	
	src = (**source).ctTable;
	dest = (**destin).ctTable;
	dest[0].rgb = src[0].rgb;
	dest[255].rgb = src[255].rgb;
	
	for (i = 1 ; i < 255 ; i++)
		{
		dest[i].rgb.red = src[*index].rgb.red;
		dest[i].rgb.green = src[*index].rgb.green;
		dest[i].rgb.blue = src[*index].rgb.blue;
		}
		
}

/*
 *	Read_File		
 *
 *	This program will read a PICT file. It reads it just like a
 *	raw file, but it starts at some offset. In the case of PICT
 *	it is 512. 
 */

Handle  Read_File(fName, vRefNum, start, end)
     char *fName;		/* the pict file name. */
     short vRefNum;		/* the volume ref num for the pict file. */
     long start,		/* where to start reading the file. */
       end;			/* where to stop reading. */
{
  short	refNum;			/* the file id. */
  long	fSize,			/* will contain the file size. */
    size;	   		/* store the bytes of data needed. */
  Handle dataH = NULL;	        /* handle to store the data in. */
	
/* open the file. */
	
  if (fsopen(fName, vRefNum, &refNum) != noErr)
    {	/* get the error string. */
      return(dataH);
    }
		
/* find out how long the file is. */
	
  if (GetEOF(refNum, &fSize) != noErr)
    ;	/* file error. */
  else
    {
		
/* if the file is smaller than the size requested, something is wrong. */
			
      if(fSize < end)
	end = fSize;
			
/* calculate the number of bytes to read. */
		
      fSize = size = end - start;
		
/* get a handle to store the data. */
		
      dataH = NewHandle(size);
		
/* was the allocation successfull? */
		
      if (dataH != nil)
	{
			
/* if start is greater than zero, move the file pointer. */
			
	  if ((start > 0) && (SetFPos(refNum, fsFromStart, start) != noErr))
	    {
	      DisposHandle(dataH);
	      dataH = nil;
	    }
	  else
	    {
	      
/* read the data. */
	      
	      HLock(dataH);
	      if ((FSRead(refNum, &fSize, *dataH) != noErr) || (fSize != size))
		{
		  HUnlock(dataH);
		  DisposHandle(dataH);
		  dataH = nil;
		}
	      else 
		HUnlock(dataH);
	    }
	}
    }
	
/* close the file. */
	
  FSClose(refNum);
  return(dataH);
}

/*
 * 	RstrGrabber (srcBits, srcRect, destRect, mode, maskRgn)
 * 	
 * 	This routine will grab a pix map from a picture during a draw pict 
 *	operation. This is a temporary replacement for StdBits.
 *
 */

static pascal ClutGrabber(srcBits, srcRect, destRect, mode, maskRgn)
     PixMap * srcBits;		/* the source pix map. */
     Rect *srcRect,		/* the rectangle in the source. */
       *destRect;		/* destination in the current grafport.*/
     short mode;		/* the copybits mode. */
     RgnHandle maskRgn;	        /* the region to be masked off. */
{

/* is it a pix map or a bit map. */
	
  if ((*srcBits).rowBytes & 0x8000)
    { /* its a pixMap */
      CGrafPtr theGraf;
      
/* save the current port. */
		
      GetPort (& ((GrafPtr) theGraf));
      (**(*srcBits).pmTable).ctSeed =
	(**(**theGraf->portPixMap).pmTable).ctSeed;
		
/* if a color table was not prevoiusly found, get this one. */
		
      if (!rstrFound)
	{
	  CTab2CTab((*srcBits).pmTable, (**tempPM).pmTable, -1);
	  rstrFound = true;
	}
			
/* set entries so that color matching works. */
		
      StdBits ((BitMap *) srcBits, srcRect, destRect, mode, maskRgn);
    } else
      StdBits ((BitMap *) srcBits, srcRect, destRect, mode, maskRgn);
}

/*
 * PICT2Image	This routine will convert a pichandle to an pixmap.
 *
 */

static Ptr PICT2Image (pict, newPM)
     PicHandle pict;			/* the pict to be converted. */
     PixMapHandle newPM;		/* the new pix map. */
{ 
  CQDProcs cProcs;			/* the standard quick draw procs. */
  CGrafPtr tempPortPtr;	                /* will be our offscreen port. */
  CGrafPort tempPort;     		/* space for the above. */
  WindowPtr savePort;    		/* the saved current port. */
  Rect	r;				/* pict frame rect, zero origined. */
  PixMapHandle oldPM;     		/* the old pix map handle. */
  Ptr Data = NULL;              	/* pointer to the data. */
		
/* set up the enclosing rectangle. */
	
  r = (**pict).picFrame;
  r.right  -= r.left;
  r.bottom -= r.top;
  r.left    = 0;
  r.top     = 0;
	
/* save the current port. */
	
  GetPort(&savePort);
  tempPortPtr = &tempPort;
  OpenCPort(tempPortPtr);	/* open a port of our own. */
  tempPM = newPM;		/* set global pix map handle to our pix map. */
	
  HLock(((Handle)tempPM));
	
/* init pix map fields. */
	
  (**tempPM).rowBytes  = r.right | 0x8000;
  (**tempPM).bounds    = r;
  tempPortPtr->portRect = r;
  ClipRect (&r);		/* clip the area outside the picture frame. */
  RectRgn (tempPortPtr->visRgn, &r);	/* set vis region. */
	
/* allocate the base address pointer. */
	
  Data = NewPtr ((long) r.right * (long) r.bottom);
  if (Data == NULL) 		goto errorexit;	/* no mem. */
	
/* set up the base address. */
	
  (**tempPM).baseAddr = Data;
  HUnlock(((Handle)tempPM));
	
/* save the old pix map, and set portpixmap to ours. */
	
  oldPM = tempPort.portPixMap;	
  tempPort.portPixMap = tempPM;
	
/* set the standard process to one ours that grabbes the image. */
	
  SetStdCProcs(&cProcs);
  cProcs.bitsProc = (Ptr)&ClutGrabber;
  tempPort.grafProcs = (QDProcsPtr)&cProcs;
  rstrFound = false;
  EraseRect (&tempPort.portRect);
  DrawPicture(pict, &r);		/* grab the thing. */
	
errorexit:
	
	tempPort.portPixMap = oldPM;
	CloseCPort(tempPortPtr);	/* This disposes the tempPM too */
	SetPort(savePort);			/* restore the old port. */
	KillPicture(pict);			/* kill the picture. */
	
	return Data;				/* return the pix map data. */
}

/*
 * Read_PICT_File (fname, vRefNum)
 *
 * Read a pict file. The files name and the volume ref number are provided.
 */
 
static PixMapHandle  Read_PICT_File(fName, vRefNum)
     char *fName;	/* the file name. */
     short vRefNum;	/* the volume reference number. */
{
  PicHandle PictImage;	/* the picture handle. */
  PixMapHandle newPM;	/* the pix map. */
  Ptr ImageData;	/* image data pointer. */
	
/* Allocate space for a new PixMap */

  newPM = NewPixMap();
  if(newPM == NULL)
    {
      return NULL;
    }
	
/* get a full color table. */
	
  DisposCTable ((**newPM).pmTable);
  HLock ((Handle) newPM);
  (**newPM).pmTable = (CTabHandle)NewHandle(2056);
  HUnlock ((Handle) newPM);
  if((**newPM).pmTable == NULL)
    {
      return NULL;
    }
	
/* read in the PICT file */

  PictImage = (PicHandle)Read_File(fName, vRefNum, 512, 0x7FFFFFFF);
  if(PictImage == NULL || BadPicture (PictImage))
    {
      return NULL;
    }

/* turn PICT handle into a PixMapHandle */

  ImageData =  PICT2Image(PictImage, newPM);
  if(ImageData == NULL)
    {
      KillPicture(PictImage);
      return NULL;
    }
	
  KillPicture(PictImage);
  return newPM;
}

typedef union {
	RGBColor irgb;
	struct {
		unsigned char ured;
		unsigned char fil1;
		unsigned char ugreen;
		unsigned char fil2;
		unsigned char ublue;
		unsigned char fil3;
		}crgb;
	} uRGB;

/*
 *	
 *	mPalette2HDF(cTab, colors)
 *	
 *	This routine converts a color table as returned from and HDF call to
 *	a mac style of color table.
 *	
 */
 
static void mPalette2HDF (cTab, colort)
     register CTabHandle cTab;
     register unsigned char colort[][3];
{
	
  register int i;
  register uRGB * ctColors;
	
  for (i = 0; i < 256; i++)
    {
      ctColors = (uRGB *) &(**cTab).ctTable[i].rgb;
      
      colort[i][0] = ctColors->crgb.ured;	/* red		*/
      colort[i][1] = ctColors->crgb.ugreen;	/* green 	*/
      colort[i][2] = ctColors->crgb.ublue;	/* blue  	*/
    }
}

/*
 *	PictToPix (aFilename, refnum, image, dim1, dim2)
 *
 *	This routine will read a Pict file and return the image data,
 *	and dims.
 */
 
ErrorCode PictToRI8 (aFilename, file_info)
     char * aFilename;
     FileInfo *file_info;
/*     short refnum;
     char ** image;
     long *dim1, *dim2;
     char * palette; */
{

  PixMapHandle tmp;
	
  tmp = Read_PICT_File (aFilename, refnum);
	
  if (tmp)
    {
      *dim1 = (**tmp).bounds.right - (**tmp).bounds.left;		
      *dim2 = (**tmp).bounds.bottom - (**tmp).bounds.top;
      *image = (char *) (**tmp).baseAddr;
      mPalette2HDF ((**tmp).pmTable, palette);
      DisposPixMap (tmp);
      return 0;
    }
  else return 1;
}

		
