
#ifndef FLOAT_IMAGE_H
#define FLOAT_IMAGE_H

#include <vector>

struct Vec3 {
  /** Default constructor */
  Vec3() : x(0), y(0), z(0) {}

  /** Initialization constructor */
  Vec3(float a_x, float a_y, float a_z)
    : x(a_x), y(a_y), z(a_z)
  {}
  
  float x;
  float y;
  float z;
};

/**
 * This class represents an image as a std::vector<Vec3>
 */
class FloatImage
{
  public:

    /** Load an image from the file \a filename */
    FloatImage(const char* filename);

    /** Save an image to the file \a filename */
    void save(const char* filename) const;

    /** \returns the pixels as a std::vector<Vec3>  (read-only) */
    const std::vector<Vec3>& values() const { return m_data; }

    /** \returns the pixels as a std::vector<Vec3> (read-write) */
    std::vector<Vec3>& values() { return m_data; }


    /** \returns a pointer to the first component of the first value (read-only) */
    const float* raw_data() const { return &(m_data[0].x); }
    
    /** \returns a pointer to the first component of the first value (read-write) */
    float* raw_data() { return &(m_data[0].x); }

    
    /** \returns the width in pixels of the image */
    int width() const { return m_width; }
    
    /** \returns the height in pixels of the image */
    int height() const { return m_height; }

  protected:
    int m_width, m_height;
    std::vector<Vec3> m_data;
};

class FloatImageGray
{
  public:

    /** Creates an empty emage of size \a width x \a height */
    FloatImageGray(int width, int height);
    
    /** Creates a gray level image from the file \a filename */
    FloatImageGray(const char* filename);
    
    /** Save an image to the file \a filename */
    void save(const char* filename) const;
    
    /** \returns the pixels as a std::vector<float>  (read-only) */
    const std::vector<float>& values() const { return m_data; }
    
    /** \returns the pixels as a std::vector<float>  (read-write) */
    std::vector<float>& values() { return m_data; }

    /** \returns a pointer to the first component of the first value (read-only) */
    const float* raw_data() const { return &(m_data[0]); }

    /** \returns a pointer to the first component of the first value (read-write) */
    float* raw_data() { return &(m_data[0]); }
    
    /** \returns the width in pixels of the image */
    int width() const { return m_width; }
    
    /** \returns the height in pixels of the image */
    int height() const { return m_height; }
    
  protected:
    int m_width, m_height;
    std::vector<float> m_data;
};

#endif
