#include <stdlib.h>
#include "mytiff.h"
#include "cv.h"
#include "ipl.h"
#include "highgui.h"
#include "constants.h"


#define TIFFPREFIX "../../movies/tifs/vaibhav1/zvaibhav"
#define TIFFSUFFIX ".tif"

/* returns a raw array of rgba values of a tiff
 * origin is lower left corner, 32 bit pixels, 8 bits per channel (rgba)
 * null otherwise
 */
uint32* readTiff(char* filename, uint32* wid, uint32* hei)
{
  uint32 w, h;
  size_t npixels;
  uint32* raster = NULL;
  TIFF* tif;

  *wid = 0; *hei = 0;

  tif = TIFFOpen(filename, "r");
  if (!tif) {
    fprintf(stderr, "Unable to open %s\n", filename);
    goto end;
  }

  if(!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w) ||
     !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h)) {
    fprintf(stderr, "Unable to retieve size information from %s",
	    filename);
    goto end;
  }
  npixels = w * h;
  raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
  if (raster != NULL) {
    if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {
      *wid = w; *hei = h;
      goto end;
    }
    else {
      _TIFFfree(raster);
    }
  }
 end:
  
  TIFFClose(tif);
  return raster;
}


/* ripped from Copyright (c) Mark J. Kilgard, 1997.
This program is freely distributable without licensing fees  and is
provided without guarantee or warrantee expressed or  implied. This
program is -not- in the public domain. 
*/
int writeTiff(char *filename, char* image, int width, int height, int compression)
{
  TIFF *file;
  int i;

  file = TIFFOpen(filename, "w");
  if (file == NULL) {
    return 1;
  }

  TIFFSetField(file, TIFFTAG_IMAGEWIDTH, (uint32) width);
  TIFFSetField(file, TIFFTAG_IMAGELENGTH, (uint32) height);
  TIFFSetField(file, TIFFTAG_BITSPERSAMPLE, 8);
  TIFFSetField(file, TIFFTAG_COMPRESSION, compression);
  TIFFSetField(file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
  TIFFSetField(file, TIFFTAG_SAMPLESPERPIXEL, 3);
  TIFFSetField(file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  TIFFSetField(file, TIFFTAG_ROWSPERSTRIP, 1);

  for (i = height - 1; i >= 0; i--) {
    if (TIFFWriteScanline(file, image, i, 0) < 0) {
      free(image);
      TIFFClose(file);
      return 1;
    }
    image += width * sizeof(char) * 3;
  }
  TIFFClose(file);
  return 0;
}

/* given a tiff index, returns the IplImage associated with it or NULL*/
IplImage* getImage(char* filename) {
  int w,h;
  /*  int i, j; */
  IplImage* img = NULL;
  uint32* raster;
  CvSize size = {IMAGE_WIDTH, IMAGE_HEIGHT};
  img = cvCreateImage(size, IPL_DEPTH_8U, 3);
  img->origin = IPL_ORIGIN_TL;

  raster = readTiff(filename, (uint32*) &w, (uint32*) &h);
  assert(w = IMAGE_WIDTH);
  assert(h = IMAGE_HEIGHT);

  /* flips the tif and leaves the
     alpha channel behind */
  tiffToIpl(raster, img->imageData);
  free(raster);
  return img;
}

void tiffToIpl( uint32* raster, char* imgData) {
  int i, j;

  for(i = 0; i < IMAGE_HEIGHT; i++) {
    for(j = 0; j < IMAGE_WIDTH; j++) {
      imgData[3*i*IMAGE_WIDTH+3*j] = 
	TIFFGetB(raster[(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+j]);
      imgData[3*i*IMAGE_WIDTH+3*j+1] = 
	TIFFGetG(raster[(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+j]);
      imgData[3*i*IMAGE_WIDTH+3*j+2] = 
	TIFFGetR(raster[(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+j]);  
    }
  }
}

void IplToTiff(char* imgData, char* raster) {
  int i, j;

  for(i = 0; i < IMAGE_HEIGHT; i++) {
    for(j = 0; j < IMAGE_WIDTH; j++) {
      if(imgData[3*i*IMAGE_WIDTH+3*j] != 0 ||
	 imgData[3*i*IMAGE_WIDTH+3*j+1] != 0 ||
	 imgData[3*i*IMAGE_WIDTH+3*j+2] != 0) {
	raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)] =  imgData[3*i*IMAGE_WIDTH+3*j+2]; 
	raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)+1] =  imgData[3*i*IMAGE_WIDTH+3*j+1];  
	raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)+2] =  imgData[3*i*IMAGE_WIDTH+3*j];  
      }
      else { /* zeros out rest of raster */
	raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)] = 0;
	raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)+1] = 0;
	raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)+2] = 0;
      }
    }

  }
}

void IplToTiffFloatMono(float* imgData, char* raster) {
  // assume intensity value x in imgData x >= 0.0 and x <= 1.0
  int i, j;
  char inten;

  for(i = 0; i < IMAGE_HEIGHT; i++) {
    for(j = 0; j < IMAGE_WIDTH; j++) {
      inten = (char) (imgData[i*IMAGE_WIDTH+j] * 255);
      raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)] = inten;
      raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)+1] = inten;
      raster[3*(IMAGE_HEIGHT-i-1)*IMAGE_WIDTH+(3*j)+2] = inten;
    }
  }
}

void markTiff(char* raster, int x, int y, char r, char g, char b) {
  raster[3*(IMAGE_HEIGHT-y-1)*IMAGE_WIDTH+(3*x)]   = r;
  raster[3*(IMAGE_HEIGHT-y-1)*IMAGE_WIDTH+(3*x)+1] = g;
  raster[3*(IMAGE_HEIGHT-y-1)*IMAGE_WIDTH+(3*x)+2] = b;
}

#ifdef TESTTIFF
int main(int argc, char* argv[]) {
  IplImage* image;

  if(argc < 2) {
    printf("you need to specify a tif index (ie: 102)\n");
    exit(0);
  }
  image = getImage(argv[1]);

  cvvInitSystem(argc, argv);
  cvvNamedWindow("foobar!", 0);
  cvvShowImage("foobar!", image);

  cvReleaseImage(&image);
  while(1);

  return 1;
}
#endif
