
////////////////////////////////////////////////////////////////////////////////
//
// Generate tensor image from a set of images, a vector image, or ...
//
////////////////////////////////////////////////////////////////////////////////

#ifndef _DTImageReader_h
#define _DTImageReader_h

#include <string>

#include "itkObject.h"
#include "itkVectorImage.h"

#include "DTImage.h"

#include "DynArray.h"

#include "vnl/vnl_vector.h"

class DTImageReader: public itk::Object
{

public:

  typedef DTImageReader Self;
  typedef itk::SmartPointer<Self> Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  itkNewMacro(Self);

  typedef itk::Image<unsigned char, 3> ByteImageType;
  typedef ByteImageType::Pointer ByteImagePointer;
  typedef ByteImageType::RegionType ByteImageRegionType;
  typedef ByteImageType::IndexType ByteImageIndexType;
  typedef ByteImageType::SizeType ByteImageSizeType;

  typedef itk::Image<short, 3> ShortImageType;
  typedef ShortImageType::Pointer ShortImagePointer;
  typedef ShortImageType::RegionType ShortImageRegionType;
  typedef ShortImageType::IndexType ShortImageIndexType;
  typedef ShortImageType::SizeType ShortImageSizeType;

  typedef itk::Image<float, 3> FloatImageType;
  typedef FloatImageType::Pointer FloatImagePointer;
  typedef FloatImageType::RegionType FloatImageRegionType;
  typedef FloatImageType::IndexType FloatImageIndexType;
  typedef FloatImageType::SizeType FloatImageSizeType;

  //typedef itk::Vector<float, 6> VectorType;
  //typedef itk::Image<VectorType, 3> VectorImageType;
  typedef itk::VectorImage<float, 3> VectorImageType;
  typedef VectorImageType::Pointer VectorImagePointer;

  typedef DynArray<std::string> StringList;

  typedef vnl_vector<double> VNLVectorType;

  // Read >= 7 images containing raw DTI data
  void ReadRawImages(const StringList& l);

  void ReadStackedImage(const char* fn);

  void ReadVTKImage(const char* fn);

  void ReadVectorImage(const char* fn);

  // List of 3x1 matrices describing the gradient directions
  void SetGradients(const DynArray<DiffusionTensor::MatrixType>& glist);

  DynArray<DiffusionTensor::MatrixType> GetGradients() { return m_Gradients; }

  DTImageType* GetOutput()
  {
    return m_Output.GetPointer();
  }

  itkGetMacro(ThresholdS0Fraction, double);
  itkSetMacro(ThresholdS0Fraction, double);

  itkGetMacro(BFactor, double);
  itkSetMacro(BFactor, double);

protected:

  DTImageReader();
  ~DTImageReader();

  void NormalizeGradients();

  double m_ThresholdS0Fraction;

  // Imaging parameters: LeBihan's b-factor and gradients
  double m_BFactor;
  DynArray<DiffusionTensor::MatrixType> m_Gradients;

  DTImagePointer m_Output;

};

#endif
