#include <itk/raster.h>
#include <itk/tiff_reader.h>

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


TIFF_Reader::TIFF_Reader()
: Reader()
, m_tiff( 0)
, m_more_pages( false)
{
}


TIFF_Reader::TIFF_Reader( const char *new_filename)
: Reader( new_filename)
, m_tiff( 0)
, m_more_pages( false)
{
}


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


bool
TIFF_Reader::operate( Raster &raster)
{
  if (is_open_multipage()) {
    return imp_load_next( raster);
  } else {
    return open_multipage() && load_next( raster) && close_multipage();
  }
}


bool
TIFF_Reader::imp_open_multipage()
{
  m_tiff = TIFFOpen( filename(), "r");
//  m_more_pages = m_tiff && (0 != TIFFReadDirectory( m_tiff));
  m_more_pages = (0 != m_tiff);
  return m_more_pages;
}


bool
TIFF_Reader::imp_load_next( Raster &raster)
{
  try {
    uint32 width;
    uint32 height;
    uint16 bits_per_sample;
    uint16 samples_per_pixel;
    uint16 photometric;
    Colormetric cm;
    ColorInterp interp;

    TIFFGetField( m_tiff, TIFFTAG_IMAGEWIDTH     , &width            );
    TIFFGetField( m_tiff, TIFFTAG_IMAGELENGTH    , &height           );
    TIFFGetField( m_tiff, TIFFTAG_BITSPERSAMPLE  , &bits_per_sample  );
    TIFFGetField( m_tiff, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
    TIFFGetField( m_tiff, TIFFTAG_PHOTOMETRIC    , &photometric      );


    cm = colormetric_null;
    switch (bits_per_sample) {
    case 1:
      cm = colormetric_1;
      switch (photometric) {
      case 0: interp = colorinterp_low_is_white; break;
      case 1: interp = colorinterp_low_is_black; break;
      }
      break;
    case 4:
      cm = colormetric_4;
      switch (photometric) {
      case 0: interp = colorinterp_low_is_white; break;
      case 1: interp = colorinterp_low_is_black; break;
      case 3: interp = colorinterp_paletted    ; break;
      }
      break;
    case 8:
      switch (photometric) {
      case 0:
        cm = colormetric_8;
        interp = colorinterp_low_is_white;
        break;
      case 1:
        cm = colormetric_8;
        interp = colorinterp_low_is_black;
        break;
      case 2:
        cm = colormetric_24;
        break;
      case 3:
        cm = colormetric_8;
        interp = colorinterp_paletted;
        break;
      }
      break;
    case 16:
      cm = colormetric_16;
      break;
    }

    if (colormetric_null == cm) {
      return false;
    }

    raster.redimension( width, height, cm, interp);
    uint32 offset    = 0;
    uint32 row       = 0;
    uint32 row_size  = raster.row_size();
    Raster_Data data = raster.raster();
    while ((row < height) &&
           (TIFFReadScanline( m_tiff, &data[ offset], row, 0) >= 0)) {
      offset += row_size;
      ++row;
    }

    return true;
  }
  catch (...) {
    return false;
  }
}


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