/******************************************************************************
  File          TGALIB.C
  Author        Phil Klassen
  Contents      Targa image file access routines.
  Created       11-05-00
  Modified      Dan Williams
                12-01-02000
 *****************************************************************************/

#include <stdio.h>    // SEEK_SET
#include <sys/stat.h> // S_IREAD
#include <fcntl.h>    // O_RDONLY
#include "tga_read.h" 

/*
int _init_tga_read(const char *fileName, TgaStruct* info) {

  int palColour;
  int palEntries;
  RGBStruct24 black, tempColour;

  black.Red = 0; // this is for viod pallette entries
  black.Green = 0;
  black.Blue = 0;  // hehe...

  if ((info->handle = open_tga(info->head, fileName)) == (-1)) {
    return (-1);
  }

  info->Height = *(u_int16_t *)&info->head[14];
  info->Width = *(u_int16_t *)&info->head[12];
  
  info->bpp = *(u_int8_t *)&info->head[16];
  info->PixelOrder = (*(u_int8_t *)&info->head[17])&0x48 >> 4;

  info->ImageOffset = *(u_int8_t *)&info->head[0] + 18 + *(u_int16_t *)&info->head[5]*3; //!!!???!!! only 24 bit pallettes

  info->PalletteOffset = *(u_int8_t *)&info->head[0]+18;

  if (info->bpp == 8) { //set up the pallette
    palEntries = *(u_int16_t *)&info->head[5];
    lseek(info->handle, info->PalletteOffset, SEEK_SET); // wind to end of header

    for (palColour = 0; palColour < 256; palColour ++) {

      if (palColour < palEntries) {
	if (read(info->handle, &tempColour, 3) != 3) {
	  printf ("EOF while reading pallette\n");
	  info->Pallette[palColour] = black;
	}
        info->Pallette[palColour] = tempColour;
      } else {
	info->Pallette[palColour] = black;
      }

    }

  }


  return (info->handle);
     
}
*/


int init_tga_read(const char *fileName, TgaStruct* info) {

  int palColour;
  int palEntries;
  RGBStruct24 black, tempColour;

  black.Red   = 0; // this is for viod pallette entries
  black.Green = 0;
  black.Blue  = 0;  // hehe...

  if ((info->handle = open_tga(&info->head, fileName)) == (-1)) {
    return (-1);
  }

  printf("Height          %d\n", ((int)(&info->head.IDLength)) - ((int)(&info->head.IDLength)) );
  printf("MapType         %d\n",  ((int)(&info->head.MapType)) - ((int)(&info->head.IDLength)) );
  printf("ImageType       %d\n",  ((int)(&info->head.ImageType)) - ((int)(&info->head.IDLength)) );
  printf("MapOrigin       %d\n",  ((int)(&info->head.MapOrigin)) - ((int)(&info->head.IDLength)) );
  printf("MapLengthh      %d\n",  ((int)(&info->head.MapLength)) - ((int)(&info->head.IDLength)) );
  printf("MapDepth        %d\n",  ((int)(&info->head.MapDepth)) - ((int)(&info->head.IDLength)) );
  printf("XOrigin         %d\n",  ((int)(&info->head.XOrigin)) - ((int)(&info->head.IDLength)) );
  printf("YOrigin         %d\n",  ((int)(&info->head.YOrigin)) - ((int)(&info->head.IDLength)) );
  printf("Width           %d\n",  ((int)(&info->head.Width)) - ((int)(&info->head.IDLength)) );
  printf("Height          %d\n",  ((int)(&info->head.Height)) - ((int)(&info->head.IDLength)) );
  printf("PixelSize       %d\n",  ((int)(&info->head.PixelSize)) - ((int)(&info->head.IDLength)) );
  printf("ImageDescriptor %d\n",  ((int)(&info->head.ImageDescriptor)) - ((int)(&info->head.IDLength)) );

  info->Height         = info->head.Height;
  info->Width          = info->head.Width;
  info->bpp            = info->head.PixelSize;
  info->PixelOrder     = (info->head.ImageDescriptor)&0x48 >> 4;
  info->ImageOffset    = info->head.IDLength + 18 + info->head.MapLength*3; //!!!???!!! only 24 bit pallettes
  info->PalletteOffset = info->head.IDLength + 18;

  if (info->bpp == 8) { //set up the pallette
    palEntries = info->head.MapLength;
    lseek(info->handle, info->PalletteOffset, SEEK_SET); // wind to end of header

    for (palColour = 0; palColour < 256; palColour ++) {
      if (palColour < palEntries) {
	     if (read(info->handle, &tempColour, 3) != 3) {
	        printf ("EOF while reading pallette\n");
	        info->Pallette[palColour] = black;
	     }
        info->Pallette[palColour] = tempColour;
       } else {
	     info->Pallette[palColour] = black;
      }
    }
  }
  return (info->handle);
     
}

int open_tga(TgaHeader *header, const char *fileName) {
   int handle;

   // error out if cannot open file
   if ((handle = open(fileName, O_RDONLY, S_IREAD)) == (-1)) {
    return (-1);
   }

   // error out if file too short
   if (read(handle, header, 18) != 18){
     close (handle);
     return (-1);
   }
   

   return(handle);

}


// X and Y are from top left
// returns black if there's an error
RGBStruct24 get_tga_pixel(TgaStruct* info, u_int16_t X, u_int16_t Y){

  RGBStruct24 result;
  u_int8_t  colourIndex;
  u_int32_t pixelOffset;

  result.Red = 0;
  result.Green = 0;
  result.Blue = 0;

  pixelOffset = 0;


  // sanity check:
  //  X and Y arn't greater than width/height
  if (( X > info->Width) || ( Y > info->Height)) return (result);

  // Find the pixel index
  switch (info->PixelOrder) {
  case 0: // left to right, bottom to top
    pixelOffset = ((Y*info->Width)+X)*(info->bpp/8);
    break;
  case 1: // right to left, bottom to top
    printf("its type 2\n");
    break;
  case 2: // left to right, top to bottom
    printf("its type 3\n"); 
    break;
  case 3: // right to left, top to bottom
    printf("its type 4\n");
    break;
  }  


  lseek(info->handle, pixelOffset+info->ImageOffset, SEEK_SET);


  // Get the pixel
  if (info->bpp == 24) {

    if (read(info->handle, &result, sizeof(result)) != sizeof(result)){
      printf("end of file error\n");
      result.Red = 0;
      result.Green = 0;
      result.Blue = 0;
      return (result);
    }
  
  } else {

  // Translate the colour

    if (read(info->handle, &colourIndex, sizeof(colourIndex)) != sizeof(colourIndex)){
      printf("end of file error\n");
    }
    result = info->Pallette[colourIndex];
  }


  return(result);

}


int fin_tga_read(TgaStruct* info) {
  close(info->handle);
  return 0;
}













