/******************************************************************************

   This file is a part of the

             COMPLEX PSEUDO-RAW SAR IMAGE PROCESSING TOOLBOX

   Copyright (C) 2017 Rémy Abergel (Remy.Abergel AT parisdescartes.fr), Loïc
   Denis (Loic.Denis AT univ-st-etienne.fr), Saïd Ladjal (Said.Ladjal AT
   telecom-paristech.fr) and Florence Tupin (Florence.Tupin AT
   telecom-paristech.fr).

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.

******************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <tiffio.h>
#include <fftw3.h>

/* prototypes */
int save_monopage_striped_tiff_from_double(char*,double*,int,int,char,int);
int save_monopage_striped_tiff_float_from_double(char*,double*,int,int,char);
int save_2pages_striped_tiff_float_from_double(char*,double*,double*,int,int,char);
int save_2pages_striped_tiff_float_from_fftw_complex(char*,fftw_complex*,int,int,char);

static int _save_page_striped_tiff_float_from_fftw_complex(TIFF*,fftw_complex*,int,int,uint32,int);
static int _save_page_striped_tiff_uint8_from_double(TIFF*,double*,int,int,uint32);
static int _save_page_striped_tiff_int8_from_double(TIFF*,double*,int,int,uint32);
static int _save_page_striped_tiff_uint16_from_double(TIFF*,double*,int,int,uint32);
static int _save_page_striped_tiff_int16_from_double(TIFF*,double*,int,int,uint32);
static int _save_page_striped_tiff_uint32_from_double(TIFF*,double*,int,int,uint32);
static int _save_page_striped_tiff_int32_from_double(TIFF*,double*,int,int,uint32);
static int _save_page_striped_tiff_float_from_double(TIFF*,double*,int,int,uint32);

int save_monopage_striped_tiff_float_from_double(filename,pixmap,nx,ny,verbose)
     char *filename,verbose;
     double *pixmap;
     int nx,ny;
{
  int err;
  uint32 rowsperstrip;

  TIFF *tiffp = TIFFOpen(filename,"w");

  TIFFSetDirectory(tiffp,0);
  TIFFSetField(tiffp,TIFFTAG_IMAGEWIDTH,nx);
  TIFFSetField(tiffp,TIFFTAG_IMAGELENGTH,ny);
  TIFFSetField(tiffp,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
  TIFFSetField(tiffp,TIFFTAG_SAMPLESPERPIXEL,(uint16)1);
  TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_IEEEFP);
  TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)32);
  TIFFSetField(tiffp,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
  TIFFSetField(tiffp,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_MINISBLACK);
  TIFFSetField(tiffp,TIFFTAG_COMPRESSION,(uint16)1);
  rowsperstrip = TIFFDefaultStripSize(tiffp,(uint32)-1);
  TIFFSetField(tiffp,TIFFTAG_ROWSPERSTRIP,rowsperstrip);
  TIFFSetField(tiffp,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB);

  if(verbose) {
    printf("save '%s' image in float precision: in progress",filename);
    fflush(stdout);
  }

  if (tiffp) err = _save_page_striped_tiff_float_from_double(tiffp,pixmap,nx,ny,rowsperstrip);
  else err = EXIT_FAILURE;

  if(verbose) {
    printf("\33[2K\rsave '%s' image in float precision: %s\n",filename,(EXIT_SUCCESS == err)?"done":"failure");
    fflush(stdout);
  }

  TIFFClose(tiffp);
  return err;
}

int save_monopage_striped_tiff_from_double(filename,pixmap,nx,ny,verbose,type)
     char *filename,verbose;
     double *pixmap;
     int nx,ny,type;
{
  int err;
  uint32 rowsperstrip;

  TIFF *tiffp = TIFFOpen(filename,"w");

  TIFFSetDirectory(tiffp,0);
  TIFFSetField(tiffp,TIFFTAG_IMAGEWIDTH,nx);
  TIFFSetField(tiffp,TIFFTAG_IMAGELENGTH,ny);
  TIFFSetField(tiffp,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
  TIFFSetField(tiffp,TIFFTAG_SAMPLESPERPIXEL,(uint16)1);
  TIFFSetField(tiffp,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
  TIFFSetField(tiffp,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_MINISBLACK);
  TIFFSetField(tiffp,TIFFTAG_COMPRESSION,(uint16)1);
  rowsperstrip = TIFFDefaultStripSize(tiffp,(uint32)-1);
  TIFFSetField(tiffp,TIFFTAG_ROWSPERSTRIP,rowsperstrip);
  TIFFSetField(tiffp,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB);

  switch (type) { // output TIFF precision (personal convention)
  case 0 : // TIFF float precision
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_IEEEFP);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)32);
    if(verbose) {
      printf("save '%s' image (precision float): in progress",filename);
      fflush(stdout);
    }
    if (tiffp) err = _save_page_striped_tiff_float_from_double(tiffp,pixmap,nx,ny,rowsperstrip);
    else err = EXIT_FAILURE;
    if(verbose) {
      printf("\33[2K\rsave '%s' image (precision float): %s\n",filename,(EXIT_SUCCESS == err)?"done":"failure");
      fflush(stdout);
    }
    break;
  case 8 : // TIFF uint8 precision
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_UINT);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)8);
    if(verbose) {
      printf("save '%s' image (precision uint8): in progress",filename);
      fflush(stdout);
    }
    if (tiffp) err = _save_page_striped_tiff_uint8_from_double(tiffp,pixmap,nx,ny,rowsperstrip);
    else err = EXIT_FAILURE;
    if(verbose) {
      printf("\33[2K\rsave '%s' image (precision uint8): %s\n",filename,(EXIT_SUCCESS == err)?"done":"failure");
      fflush(stdout);
    }
    break;
  case -8 : // TIFF int8 precision
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)8);
    if(verbose) {
      printf("save '%s' image (precision int8): in progress",filename);
      fflush(stdout);
    }
    if (tiffp) err = _save_page_striped_tiff_int8_from_double(tiffp,pixmap,nx,ny,rowsperstrip);
    else err = EXIT_FAILURE;
    if(verbose) {
      printf("\33[2K\rsave '%s' image (precision int8): %s\n",filename,(EXIT_SUCCESS == err)?"done":"failure");
      fflush(stdout);
    }
    break;
  case 16 : // TIFF uint16 precision
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_UINT);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)16);
    if(verbose) {
      printf("save '%s' image (precision uint16): in progress",filename);
      fflush(stdout);
    }
    if (tiffp) err = _save_page_striped_tiff_uint16_from_double(tiffp,pixmap,nx,ny,rowsperstrip);
    else err = EXIT_FAILURE;
    if(verbose) {
      printf("\33[2K\rsave '%s' image (precision uint16): %s\n",filename,(EXIT_SUCCESS == err)?"done":"failure");
      fflush(stdout);
    }
    break;
  case -16 : // TIFF int16 precision
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)16);
    if(verbose) {
      printf("save '%s' image (precision int16): in progress",filename);
      fflush(stdout);
    }
    if (tiffp) err = _save_page_striped_tiff_int16_from_double(tiffp,pixmap,nx,ny,rowsperstrip);
    else err = EXIT_FAILURE;
    if(verbose) {
      printf("\33[2K\rsave '%s' image (precision int16): %s\n",filename,(EXIT_SUCCESS == err)?"done":"failure");
      fflush(stdout);
    }
    break;
  case 32 : // TIFF uint32 precision
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_UINT);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)32);
    if(verbose) {
      printf("save '%s' image (precision uint32): in progress",filename);
      fflush(stdout);
    }
    if (tiffp) err = _save_page_striped_tiff_uint32_from_double(tiffp,pixmap,nx,ny,rowsperstrip);
    else err = EXIT_FAILURE;
    if(verbose) {
      printf("\33[2K\rsave '%s' image (precision uint32): %s\n",filename,(EXIT_SUCCESS == err)?"done":"failure");
      fflush(stdout);
    }
    break;
  case -32 : // TIFF int32 precision
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)32);
    if(verbose) {
      printf("save '%s' image (precision int32): in progress",filename);
      fflush(stdout);
    }
    if (tiffp) err = _save_page_striped_tiff_int32_from_double(tiffp,pixmap,nx,ny,rowsperstrip);
    else err = EXIT_FAILURE;
    if(verbose) {
      printf("\33[2K\rsave '%s' image (precision int32): %s\n",filename,(EXIT_SUCCESS == err)?"done":"failure");
      fflush(stdout);
    }
    break;
  default : // unrecognized precision
    if(verbose) printf("used unrecognized type in internal module 'save_monopage_striped_tiff_from_double'.\n");
    err = EXIT_FAILURE;
  }

  TIFFClose(tiffp);
  return err;
}

int save_2pages_striped_tiff_float_from_double(filename,pixmap1,pixmap2,nx,ny,verbose)
     char *filename,verbose;
     double *pixmap1,*pixmap2;
     int nx,ny;
{
  int err,directory,npages=1;
  uint32 rowsperstrip;

  TIFF *tiffp = TIFFOpen(filename,"w");

  for(directory = 0;directory<=1; directory++) {

    TIFFSetField(tiffp,TIFFTAG_PAGENUMBER,directory,npages);
    TIFFSetField(tiffp, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
    TIFFSetField(tiffp,TIFFTAG_IMAGEWIDTH,nx);
    TIFFSetField(tiffp,TIFFTAG_IMAGELENGTH,ny);
    TIFFSetField(tiffp,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
    TIFFSetField(tiffp,TIFFTAG_SAMPLESPERPIXEL,(uint16)1);
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_IEEEFP);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)32);
    TIFFSetField(tiffp,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
    TIFFSetField(tiffp,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_MINISBLACK);
    TIFFSetField(tiffp,TIFFTAG_COMPRESSION,(uint16)1);
    rowsperstrip = TIFFDefaultStripSize(tiffp,(uint32)-1);
    TIFFSetField(tiffp,TIFFTAG_ROWSPERSTRIP,rowsperstrip);
    TIFFSetField(tiffp,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB);

    if(verbose) {
      printf("save directory %d of image '%s' in float precision : in progress",directory,filename);
      fflush(stdout);
    }

    if (tiffp) err = (directory == 0) ? _save_page_striped_tiff_float_from_double(tiffp,pixmap1,nx,ny,rowsperstrip) : _save_page_striped_tiff_float_from_double(tiffp,pixmap2,nx,ny,rowsperstrip);
    else err = EXIT_FAILURE;

    if(verbose) {
      printf("\33[2K\rsave directory %d of image '%s' in float precision : %s\n",directory,filename,(EXIT_SUCCESS == err)?"done":"failure");
      fflush(stdout);
    }
  }

  TIFFClose(tiffp);
  return err;
}

int save_2pages_striped_tiff_float_from_fftw_complex(filename,pixmap,nx,ny,verbose)
     char *filename,verbose;
     fftw_complex *pixmap;
     int nx,ny;
{
  int err,directory,npages=1;
  uint32 rowsperstrip;

  TIFF *tiffp = TIFFOpen(filename,"w");

  for(directory = 0;directory<=1; directory++) {

    TIFFSetField(tiffp,TIFFTAG_PAGENUMBER,directory,npages);
    TIFFSetField(tiffp, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
    TIFFSetField(tiffp,TIFFTAG_IMAGEWIDTH,nx);
    TIFFSetField(tiffp,TIFFTAG_IMAGELENGTH,ny);
    TIFFSetField(tiffp,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
    TIFFSetField(tiffp,TIFFTAG_SAMPLESPERPIXEL,(uint16)1);
    TIFFSetField(tiffp,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_IEEEFP);
    TIFFSetField(tiffp,TIFFTAG_BITSPERSAMPLE,(uint16)32);
    TIFFSetField(tiffp,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
    TIFFSetField(tiffp,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_MINISBLACK);
    TIFFSetField(tiffp,TIFFTAG_COMPRESSION,(uint16)1);
    rowsperstrip = TIFFDefaultStripSize(tiffp,(uint32)-1);
    TIFFSetField(tiffp,TIFFTAG_ROWSPERSTRIP,rowsperstrip);
    TIFFSetField(tiffp,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB);

    if(verbose) {
      printf("save '%s' image (%s part) in float precision : in progress",filename,(directory==0)?"real":"imaginary");
      fflush(stdout);
    }

    if (tiffp) err = _save_page_striped_tiff_float_from_fftw_complex(tiffp,pixmap,nx,ny,rowsperstrip,directory);
    else err = EXIT_FAILURE;

    if(verbose) {
      printf("\33[2K\rsave '%s' image (%s part) in float precision : %s\n",filename,(directory==0)?"real":"imaginary",(EXIT_SUCCESS==err)?"done":"failure");
      fflush(stdout);
    }
  }

  TIFFClose(tiffp);
  return err;
}





static int _save_page_striped_tiff_float_from_fftw_complex(tiffp,pixmap,nx,ny,rowsperstrip,offset)
     TIFF *tiffp;
     fftw_complex *pixmap;
     int nx,ny,offset;
     uint32 rowsperstrip;
{
  unsigned int row,rr,cc;
  uint32 nrow;
  tstrip_t strip;
  tsize_t i;
  float *buf;

  buf = (float*) _TIFFmalloc(TIFFStripSize(tiffp));
  if(!buf) { printf("Not enough memory\n"); return EXIT_FAILURE; }

  for (row = 0; row<ny; row+=rowsperstrip){
    nrow = (row + rowsperstrip>ny?ny-row:rowsperstrip);
    strip = TIFFComputeStrip(tiffp,row,0);
    i = 0;
    for (rr = 0; rr<nrow; ++rr)
      for (cc = 0; cc<nx; ++cc)
	buf[i++] = (float) pixmap[(row+rr)*nx + cc][offset];
    if (TIFFWriteEncodedStrip(tiffp,strip,buf,i*sizeof(float))<0) return EXIT_FAILURE;
  }
  _TIFFfree(buf);

  TIFFWriteDirectory(tiffp);

  return EXIT_SUCCESS;
}



static int _save_page_striped_tiff_uint8_from_double(tiffp,pixmap,nx,ny,rowsperstrip)
     TIFF *tiffp;
     double *pixmap;
     int nx,ny;
     uint32 rowsperstrip;
{
  unsigned int row,rr,cc;
  uint32 nrow;
  tstrip_t strip;
  tsize_t i;
  uint8 *buf;

  buf = (uint8*) _TIFFmalloc(TIFFStripSize(tiffp));
  if(!buf) { printf("Not enough memory\n"); return EXIT_FAILURE; }

  for (row = 0; row<ny; row+=rowsperstrip){
    nrow = (row + rowsperstrip>ny?ny-row:rowsperstrip);
    strip = TIFFComputeStrip(tiffp,row,0);
    i = 0;
    for (rr = 0; rr<nrow; ++rr)
      for (cc = 0; cc<nx; ++cc)
	buf[i++] = (uint8) pixmap[(row+rr)*nx + cc];
    if (TIFFWriteEncodedStrip(tiffp,strip,buf,i*sizeof(uint8))<0) return EXIT_FAILURE;
  }
  _TIFFfree(buf);

  TIFFWriteDirectory(tiffp);

  return EXIT_SUCCESS;
}

static int _save_page_striped_tiff_int8_from_double(tiffp,pixmap,nx,ny,rowsperstrip)
     TIFF *tiffp;
     double *pixmap;
     int nx,ny;
     uint32 rowsperstrip;
{
  unsigned int row,rr,cc;
  uint32 nrow;
  tstrip_t strip;
  tsize_t i;
  int8 *buf;

  buf = (int8*) _TIFFmalloc(TIFFStripSize(tiffp));
  if(!buf) { printf("Not enough memory\n"); return EXIT_FAILURE; }

  for (row = 0; row<ny; row+=rowsperstrip){
    nrow = (row + rowsperstrip>ny?ny-row:rowsperstrip);
    strip = TIFFComputeStrip(tiffp,row,0);
    i = 0;
    for (rr = 0; rr<nrow; ++rr)
      for (cc = 0; cc<nx; ++cc)
	buf[i++] = (int8) pixmap[(row+rr)*nx + cc];
    if (TIFFWriteEncodedStrip(tiffp,strip,buf,i*sizeof(int8))<0) return EXIT_FAILURE;
  }
  _TIFFfree(buf);

  TIFFWriteDirectory(tiffp);

  return EXIT_SUCCESS;
}

static int _save_page_striped_tiff_uint16_from_double(tiffp,pixmap,nx,ny,rowsperstrip)
     TIFF *tiffp;
     double *pixmap;
     int nx,ny;
     uint32 rowsperstrip;
{
  unsigned int row,rr,cc;
  uint32 nrow;
  tstrip_t strip;
  tsize_t i;
  uint16 *buf;

  buf = (uint16*) _TIFFmalloc(TIFFStripSize(tiffp));
  if(!buf) { printf("Not enough memory\n"); return EXIT_FAILURE; }

  for (row = 0; row<ny; row+=rowsperstrip){
    nrow = (row + rowsperstrip>ny?ny-row:rowsperstrip);
    strip = TIFFComputeStrip(tiffp,row,0);
    i = 0;
    for (rr = 0; rr<nrow; ++rr)
      for (cc = 0; cc<nx; ++cc)
	buf[i++] = (uint16) pixmap[(row+rr)*nx + cc];
    if (TIFFWriteEncodedStrip(tiffp,strip,buf,i*sizeof(uint16))<0) return EXIT_FAILURE;
  }
  _TIFFfree(buf);

  TIFFWriteDirectory(tiffp);

  return EXIT_SUCCESS;
}

static int _save_page_striped_tiff_int16_from_double(tiffp,pixmap,nx,ny,rowsperstrip)
     TIFF *tiffp;
     double *pixmap;
     int nx,ny;
     uint32 rowsperstrip;
{
  unsigned int row,rr,cc;
  uint32 nrow;
  tstrip_t strip;
  tsize_t i;
  int16 *buf;

  buf = (int16*) _TIFFmalloc(TIFFStripSize(tiffp));
  if(!buf) { printf("Not enough memory\n"); return EXIT_FAILURE; }

  for (row = 0; row<ny; row+=rowsperstrip){
    nrow = (row + rowsperstrip>ny?ny-row:rowsperstrip);
    strip = TIFFComputeStrip(tiffp,row,0);
    i = 0;
    for (rr = 0; rr<nrow; ++rr)
      for (cc = 0; cc<nx; ++cc)
	buf[i++] = (int16) pixmap[(row+rr)*nx + cc];
    if (TIFFWriteEncodedStrip(tiffp,strip,buf,i*sizeof(int16))<0) return EXIT_FAILURE;
  }
  _TIFFfree(buf);

  TIFFWriteDirectory(tiffp);

  return EXIT_SUCCESS;
}

static int _save_page_striped_tiff_uint32_from_double(tiffp,pixmap,nx,ny,rowsperstrip)
     TIFF *tiffp;
     double *pixmap;
     int nx,ny;
     uint32 rowsperstrip;
{
  unsigned int row,rr,cc;
  uint32 nrow;
  tstrip_t strip;
  tsize_t i;
  uint32 *buf;

  buf = (uint32*) _TIFFmalloc(TIFFStripSize(tiffp));
  if(!buf) { printf("Not enough memory\n"); return EXIT_FAILURE; }

  for (row = 0; row<ny; row+=rowsperstrip){
    nrow = (row + rowsperstrip>ny?ny-row:rowsperstrip);
    strip = TIFFComputeStrip(tiffp,row,0);
    i = 0;
    for (rr = 0; rr<nrow; ++rr)
      for (cc = 0; cc<nx; ++cc)
	buf[i++] = (uint32) pixmap[(row+rr)*nx + cc];
    if (TIFFWriteEncodedStrip(tiffp,strip,buf,i*sizeof(uint32))<0) return EXIT_FAILURE;
  }
  _TIFFfree(buf);

  TIFFWriteDirectory(tiffp);

  return EXIT_SUCCESS;
}

static int _save_page_striped_tiff_int32_from_double(tiffp,pixmap,nx,ny,rowsperstrip)
     TIFF *tiffp;
     double *pixmap;
     int nx,ny;
     uint32 rowsperstrip;
{
  unsigned int row,rr,cc;
  uint32 nrow;
  tstrip_t strip;
  tsize_t i;
  int32 *buf;

  buf = (int32*) _TIFFmalloc(TIFFStripSize(tiffp));
  if(!buf) { printf("Not enough memory\n"); return EXIT_FAILURE; }

  for (row = 0; row<ny; row+=rowsperstrip){
    nrow = (row + rowsperstrip>ny?ny-row:rowsperstrip);
    strip = TIFFComputeStrip(tiffp,row,0);
    i = 0;
    for (rr = 0; rr<nrow; ++rr)
      for (cc = 0; cc<nx; ++cc)
	buf[i++] = (int32) pixmap[(row+rr)*nx + cc];
    if (TIFFWriteEncodedStrip(tiffp,strip,buf,i*sizeof(int32))<0) return EXIT_FAILURE;
  }
  _TIFFfree(buf);

  TIFFWriteDirectory(tiffp);

  return EXIT_SUCCESS;
}

static int _save_page_striped_tiff_float_from_double(tiffp,pixmap,nx,ny,rowsperstrip)
     TIFF *tiffp;
     double *pixmap;
     int nx,ny;
     uint32 rowsperstrip;
{
  unsigned int row,rr,cc;
  uint32 nrow;
  tstrip_t strip;
  tsize_t i;
  float *buf;

  buf = (float*) _TIFFmalloc(TIFFStripSize(tiffp));
  if(!buf) { printf("Not enough memory\n"); return EXIT_FAILURE; }

  for (row = 0; row<ny; row+=rowsperstrip){
    nrow = (row + rowsperstrip>ny?ny-row:rowsperstrip);
    strip = TIFFComputeStrip(tiffp,row,0);
    i = 0;
    for (rr = 0; rr<nrow; ++rr)
      for (cc = 0; cc<nx; ++cc)
	buf[i++] = (float) pixmap[(row+rr)*nx + cc];
    if (TIFFWriteEncodedStrip(tiffp,strip,buf,i*sizeof(float))<0) return EXIT_FAILURE;
  }
  _TIFFfree(buf);

  TIFFWriteDirectory(tiffp);

  return EXIT_SUCCESS;
}
