#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <tiffio.h>
#include <string.h>
#include <sys/types.h>
#include <stddef.h>

int Extract_Signal(TIFF *tif, uint16 *amplitude, char *filename)
{
    int DEBUG=0;
    int DEBUG_Start=425;
    
    if (tif) 
    {
	TIFFRGBAImage img;
	char emsg[1024];
	uint16 x, y, dotcount, dotmax, indot, amptemp;

	if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) 
	{
	    size_t npixels;
	    uint32* raster;
	    int red;
	    
	    npixels = img.width * img.height;
	    raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
	    if (raster != NULL) {
		if (TIFFRGBAImageGet(&img, raster, img.width, img.height)) 
		{
		    dotcount=0;
		    for (x=0;x<img.width;x++)
		    {
			dotcount = dotmax= amptemp = 0;
			for (y=0;y<img.height;y++)
			{
			    red = TIFFGetR(raster[y*img.width+x]);
			    if (red==0)                                 // We're in a Black region
			    {
				if (DEBUG && y>DEBUG_Start && y<DEBUG_Start+132) { printf("*");}
				dotcount++;
				indot=0;
			    }
			    else                                        // We're in white region
			    {
				if (DEBUG && y>DEBUG_Start && y<DEBUG_Start+132) { printf("-");}
				if (dotcount>dotmax)
				{
				    amptemp=y-dotcount/2;
				    dotmax=dotcount;
				}
				dotcount=0;
				indot=1;
			    }
			}
			if (DEBUG) { printf("\n"); }
			amplitude[x]=amptemp;
		    }
		}
		_TIFFfree(raster);
	    }
	    else
		printf("Not enough memory to hold raster image!\n");
	    TIFFRGBAImageEnd(&img);
	} 
	else
	    TIFFError(filename, emsg);
    }
    return(0);
}

int WriteFile(uint16 *amplitude, char *filename,float X,float Y,double TimeScale,double Voltscale,uint32 width)
{
    FILE *ofp;
    typedef struct eWavHead {
	u_int64_t Channels;            /* number of channels stored in file */
	u_int64_t WFD_Offset;          /* Offset in bytes from beginning of file to first eWav File Directory */
    } eWavHead;                     /* 16 bytes */

    typedef struct ChannelHeader {
	float ResX;                 /* Image resolution in dots/cm */
	float RexY;                 /* Image resolution in dots/cm */
	double Scale_mm_sec;
	double Scale_mv_cm;
	u_int32_t Samples;
   } ChannelHeader;


    eWavHead FileHeader;
    ChannelHeader ChannelHead;

    FileHeader.Channels=1;
    FileHeader.WFD_Offset=16;

    ChannelHead.ResX=X;
    ChannelHead.RexY=Y;
    ChannelHead.Scale_mm_sec=TimeScale;
    ChannelHead.Scale_mv_cm=Voltscale;
    ChannelHead.Samples=width;

    ofp = fopen(filename, "wb");
    fwrite(&FileHeader,sizeof(eWavHead),1,ofp);
    fwrite(&ChannelHead,sizeof(ChannelHeader),1,ofp);
    fwrite(amplitude,sizeof(uint16),width,ofp);
    fclose(ofp);

    return(0);

}
int main(int argc, char* argv[])
{ 

    float Xres, Yres;
    double scale_mm_sec, scale_mv_cm;
    u_int32_t BitsPerSample,Photometric,width, height;
    u_int16_t *Amplitudes, retval, resunit;
    char emsg[1024];

    TIFF* ECGtif = TIFFOpen(argv[1], "r");
    scale_mm_sec=atof(argv[2]);
    scale_mv_cm=atof(argv[3]); 

    TIFFGetField(ECGtif,TIFFTAG_IMAGEWIDTH,&width);
    TIFFGetField(ECGtif,TIFFTAG_IMAGELENGTH,&height);
    TIFFGetField(ECGtif,TIFFTAG_XRESOLUTION,&Xres);
    TIFFGetField(ECGtif,TIFFTAG_YRESOLUTION,&Yres);
    TIFFGetField(ECGtif,TIFFTAG_BITSPERSAMPLE,&BitsPerSample);
    TIFFGetField(ECGtif,TIFFTAG_PHOTOMETRIC,&Photometric);
    TIFFGetField(ECGtif,TIFFTAG_RESOLUTIONUNIT,&resunit); // 2:inch, 3:centimeter

    Amplitudes=(uint16 *)calloc(width,sizeof(uint16));

    if (2==resunit) 
    {
	Yres/=2.54;
	Xres/=2.54;
    }


    printf ("Horizontal=%d pixels, vertical=%d pixles\n",(int)width,(int)height);
    printf ("Horiz_res=%f dpc, Vert_res=%f dpc\n",Yres, Xres);
    printf ("%f mm/sec,\t%f mV/cm\n",scale_mm_sec,scale_mv_cm);


    if (!TIFFRGBAImageOK(ECGtif,emsg))
	printf("Tiff Image CANNOT be read by RGBA routines.\n");

    
    retval = Extract_Signal(ECGtif,Amplitudes,argv[1]);
    TIFFClose(ECGtif);
    WriteFile(Amplitudes,argv[4],Xres,Xres,scale_mm_sec,scale_mv_cm, width);
    exit(0);
}