#include <tiffio.h>
#include <itk/raster.h>
#include <itk/tiff_writer.h>

#ifndef DO_ITK_INLINE
#include <itk/tiff_writer.inl>
#endif


TIFF_Writer::TIFF_Writer()
: Writer()
, m_tiff( 0)
{
}


TIFF_Writer::TIFF_Writer( const char *new_filename)
: Writer( new_filename)
, m_tiff( 0)
{
}


TIFF_Writer::~TIFF_Writer()
{
  if (is_open_multipage()) {
    close_multipage();
  }
}


bool
TIFF_Writer::operate( Raster &raster)
{
  if (is_open_multipage()) {
    return imp_save_next( raster);
  } else {
    return open_multipage() && save_next( raster) && close_multipage();
  }
}


bool
TIFF_Writer::imp_open_multipage()
{
  m_tiff = TIFFOpen( filename(), "w");
  return (0 != m_tiff);
}


bool
TIFF_Writer::imp_save_next( Raster &raster)
{
  try {
    uint32 width             = raster.width();
    uint32 height            = raster.height();
    uint16 sample_size       = raster.sample_size();
    uint16 bits_per_sample   = 0;
    uint16 samples_per_pixel = 0;
    uint16 photometric       = 0;
    uint16 compression       = 0;
    uint16 planar_config     = 1;


    switch (sample_size) {
    case  1:
    case  4:
    case  8:
    case 16:
      bits_per_sample   = sample_size;
      samples_per_pixel = 1;
      break;
    case 24:
      bits_per_sample   = 8;
      samples_per_pixel = 3;
      break;
    default:
      return false;
    }
    if (raster.is_paletted()) {
      photometric = 3;
    } else if (24 == sample_size) {
      photometric = 2;
    } else if (raster.is_black_low()) {
      photometric = 1;
    } else {
      photometric = 0;
    }
    switch (sample_size) {
    case  1:  compression =     4; break;
    case  4:  compression = 32773; break;
    case  8:  compression = 32773; break;
    case 16:  compression = 32773; break;
    case 24:  compression = 32773; break;
    default:
      return false;
    }

    TIFFSetField( m_tiff, TIFFTAG_IMAGEWIDTH     , width            );
    TIFFSetField( m_tiff, TIFFTAG_IMAGELENGTH    , height           );
    TIFFSetField( m_tiff, TIFFTAG_BITSPERSAMPLE  , bits_per_sample  );
    TIFFSetField( m_tiff, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
    TIFFSetField( m_tiff, TIFFTAG_PHOTOMETRIC    , photometric      );
    TIFFSetField( m_tiff, TIFFTAG_COMPRESSION    , compression      );
    TIFFSetField( m_tiff, TIFFTAG_PLANARCONFIG   , planar_config    );

    uint32 offset    = 0;
    uint32 row       = 0;
    uint32 row_size  = raster.row_size();
    Raster_Data data = raster.raster();
    while ((row < height) &&
           (TIFFWriteScanline( m_tiff, &data[ offset], row, 0) >= 0)) {
      offset += row_size;
      ++row;
    }
    return (0 != TIFFWriteDirectory( m_tiff));
  }
  catch (...) {
    return false;
  }
}


bool
TIFF_Writer::imp_close_multipage()
{
  if (is_open_multipage()) {
    TIFFClose( m_tiff);
  }
  return true;
}