/*
 *  psychlops_g_color.h
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2006/01/04 by Kenchi HOSOKAWA
 *  (C) 2006 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
 */

#ifndef HEADER_PSYCHLOPS_GRAPHIC_COLOR
#define HEADER_PSYCHLOPS_GRAPHIC_COLOR

#include <vector>
#include <map>
#include "psychlops_g_fundamental.h"

namespace Psychlops {

	class ImageManipulator;
	class DirectGetColor;
	class Color {
		friend class Canvas;
		friend class Image;
		friend class ImageManipulator;
		friend class DirectGetColor;

		public:
		enum CALIBRATION_MODE { NOTHING=0, GAMMA_VALUE=1, TABLE=2, SOFTWARE_GAMMA_VALUE=101, SOFTWARE_TABLE=102,
		                        BITS_MONO=-100 };
		static bool strict_match;
		static void setGammaValue(double r, double g, double b);
		static void setGammaValue(double r, double g, double b, CALIBRATION_MODE mode);
		static void setGammaTable(const double * const table_r, const double * const table_g, const double * const table_b, const int num_steps);
		static void setGammaTable(const std::vector<double> &table_r, const std::vector<double> &table_g, const std::vector<double> &table_b);
		static void forceSoftwareCalibration(bool on_off = true);
		static CALIBRATION_MODE getCalibrationMode();

		protected:
		double Red, Green, Blue, Alpha;

		static bool force_software_calibration_;
		static double gamma_r_inversed_, gamma_g_inversed_, gamma_b_inversed_;
		static double gamma_r_, gamma_g_, gamma_b_;
		static int table_size_;
		static std::vector<double> table_r_, table_g_, table_b_;
		static std::multimap<double, double> restore_table_r_, restore_table_g_, restore_table_b_;
		static void interpolateDiscreteSamplesInLinearFunction(const std::vector<double> &source, std::vector<double> &target);

		static void (*set_)(Color * col, double r, double g, double b, double a);
		static void set_direct(Color * col, double r, double g, double b, double a);
		static void set_correct_value(Color * col, double r, double g, double b, double a);
		static void set_correct_table(Color * col, double r, double g, double b, double a);
		static void set_correct_bits_mono(Color * col, double r, double g, double b, double a);

		static void (*get_)(const Color &col, double &r, double &g, double &b, double &a);
		static void get_direct(const Color &col, double &r, double &g, double &b, double &a);
		static void get_restore_gamma(const Color &col, double &r, double &g, double &b, double &a);
		static void get_restore_table(const Color &col, double &r, double &g, double &b, double &a);
		static void get_restore_bits_mono(const Color &col, double &r, double &g, double &b, double &a);

		static CALIBRATION_MODE calibration_mode_;
		static inline double Int8toFloat64(int value);
		static inline double limitvalue(double value);

		public:
		Color();
		Color(double r, double g, double b, double a = 1.0);
		Color(double r, double g, double b, double a, bool dummy);
		Color(double gray);
		Color & set(double r, double g, double b, double a = 1.0);
		Color & set(double r, double g, double b, double a, bool dummy);
		Color & set(double gray);

		double getR() const;
		double getG() const;
		double getB() const;
		double getA() const;
		void get(double &r, double &g, double &b, double &a) const;

		Color dup() const;

		bool operator ==(Color rhs);
		Color operator +(Color rhs);
		Color operator -(Color rhs);
		Color & operator +=(Color rhs);
		Color & operator -=(Color rhs);



		static Color white;
		static Color black;
		static Color gray;
		static Color red;
		static Color green;
		static Color blue;
		static Color cyan;
		static Color magenta;
		static Color yellow;

		static const Color null_color;
	};


}	/*	<- namespace Psycholops 	*/


#endif
