//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2015 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
// 
#ifndef IMAGE_HPP
#define IMAGE_HPP

#include <Config.hpp>

#include <cuda/CudaExport.hpp>
#include <Vector.hpp>

#include <QString>
#include <QStringList>

namespace mgx 
{
  class Progress;
  
  typedef Vector<3, unsigned int> Point3u;
  
  mgx_EXPORT QStringList supportedImageReadFormats();
  mgx_EXPORT QStringList supportedImageWriteFormats();
  
  struct mgx_EXPORT Image3D {
    Image3D();
    Image3D(const Image3D& copy);
    Image3D(HVecUS& data, const Point3u& size, const Point3f& step = Point3f(1, 1, 1), bool labels = false);
  
    ~Image3D();
  
    void allocate(const Point3u& size);
    void allocate();
  
    void setPlane(int i)
    {
      if(i >= 0 and size_t(i) < size.z())
        plane = i;
      else
        plane = -1;
    }
  
    const ushort& operator[](int i) const {
      return (*data)[i];
    }
  
    ushort& operator[](int i) {
      return (*data)[i];
    }
  
    HVecUS* data;
    Point3u size;
    Point3f step;
    Point3f origin;
    uint minc, maxc;
    float brightness;
    int plane;     ///< To load a 2D image in a 3D stack
    bool labels;   ///< If the image contains labels
  
  protected:
    bool allocated;
  };
  
  // In case of an error, this function will throw a QString with the description of the error
  mgx_EXPORT bool saveImage(QString filename, const Image3D& data, QString type = "CImg Auto",
                            unsigned int nb_digits = 0);
  
  // Save a TIFF image as a single file
  mgx_EXPORT bool saveTIFFImage(QString filename, const Image3D& data);
  
  mgx_EXPORT bool loadTIFFImage(QString filename, Image3D& data, bool allocate_data = false);
  mgx_EXPORT bool loadImage(QString filename, Image3D& data, bool allocate_data = false);
  
  mgx_EXPORT HVecUS resize(const HVecUS& data, const Point3i& before, const Point3i& after, bool center);
}

#endif
