/*****************************************************************************/
// Copyright 2006-2019 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE:	Adobe permits you to use, modify, and distribute this file in
// accordance with the terms of the Adobe license agreement accompanying it.
/*****************************************************************************/

/** \file
 * Classes for conversion of RAW data to final image.
 */

/*****************************************************************************/

#ifndef __dng_render__
#define __dng_render__

/*****************************************************************************/

#include "dng_1d_function.h"
#include "dng_auto_ptr.h"
#include "dng_big_table.h"
#include "dng_camera_profile.h"
#include "dng_classes.h"
#include "dng_matrix.h"
#include "dng_spline.h"
#include "dng_uncopyable.h"
#include "dng_xy_coord.h"

/******************************************************************************/

/// \brief Curve for removing zero offset from stage3 image.

class dng_function_zero_offset: public dng_1d_function
	{
	
	public:
	
		real64 fZeroOffset;
		
		real64 fScale;
		
	public:
		
		dng_function_zero_offset (real64 zeroOffset);
		
		virtual real64 Evaluate (real64 x) const;

	};

/******************************************************************************/

/// \brief Curve for pre-exposure-compensation adjustment based on noise floor,
/// shadows, and highlight level.

class dng_function_exposure_ramp: public dng_1d_function
	{
	
	public:
	
		real64 fSlope;		// Slope of straight segment.
		
		real64 fBlack;		// Intercept of straight segment.
		
		real64 fRadius;		// Rounding radius.
		
		real64 fQScale;		// Quadradic scale.

		const bool fSupportOverrange = false;
		
	public:
		
		dng_function_exposure_ramp (real64 white,
									real64 black,
									real64 minBlack,
									bool supportOverrange);
			
		virtual real64 Evaluate (real64 x) const;

	};
			
/******************************************************************************/

/// \brief Exposure compensation curve for a given compensation amount in stops using
/// quadric for roll-off.

class dng_function_exposure_tone: public dng_1d_function
	{
	
	protected:
	
		bool fIsNOP;		// Is this a NOP function?
		
		real64 fSlope;		// Slope for lower part of curve.
		
		real64 a;			// Quadradic parameters for upper two f-stops.
		real64 b;
		real64 c;
	
	public:
	
		dng_function_exposure_tone (real64 exposure);
				
		/// Returns output value for a given input tone.

		virtual real64 Evaluate (real64 x) const;
	
	};
	
/*****************************************************************************/

/// Default ACR3 tone curve.

class dng_tone_curve_acr3_default: public dng_1d_function
	{
	
	public:
		
		/// Returns output value for a given input tone.

		virtual real64 Evaluate (real64 x) const;
		
		/// Returns nearest input value for a given output tone.

		virtual real64 EvaluateInverse (real64 x) const;
		
		static const dng_1d_function & Get ();

	};
			
/*****************************************************************************/

/// \brief Encoding gamma curve for a given color space.

class dng_function_gamma_encode: public dng_1d_function
	{
	
	protected:
	
		const dng_color_space &fSpace;
	
	public:
	
		dng_function_gamma_encode (const dng_color_space &space);
		
		virtual real64 Evaluate (real64 x) const;
		
	};

/*****************************************************************************/

/// \brief Class used to render digital negative to displayable image.

class dng_render: private dng_uncopyable
	{
	
	protected:
	
		dng_host &fHost;
	
		const dng_negative &fNegative;
	
		dng_xy_coord fWhiteXY;
		
		real64 fExposure;
		
		real64 fShadows;
		
		const dng_1d_function *fToneCurve;
		
		const dng_color_space *fFinalSpace;
		
		uint32 fFinalPixelType;
		
		uint32 fMaximumSize;

		// Which camera profile to use?

		dng_camera_profile_id fProfileID;
		
	private:
	
		AutoPtr<dng_spline_solver> fProfileToneCurve;
		
	public:
	
		/// Construct a rendering instance that will be used to convert a given digital negative.
		/// \param host The host to use for memory allocation, progress updates, and abort testing.
		/// \param negative The digital negative to convert to a displayable image.

		dng_render (dng_host &host,
					const dng_negative &negative);
		
		virtual ~dng_render ()
			{
			}
		
		/// Set the white point to be used for conversion.
		/// \param white White point to use.

		void SetWhiteXY (const dng_xy_coord &white)
			{
			fWhiteXY = white;
			}
			
		/// Get the white point to be used for conversion.
		/// \retval White point to use.

		const dng_xy_coord WhiteXY () const
			{
			return fWhiteXY;
			}
			
		/// Set exposure compensation.
		/// \param exposure Compensation value in stops, positive or negative.

		void SetExposure (real64 exposure)
			{
			fExposure = exposure;
			}
			
		/// Get exposure compensation.
		/// \retval Compensation value in stops, positive or negative.

		real64 Exposure () const
			{
			return fExposure;
			}
			
		/// Set shadow clip amount.
		/// \param shadows Shadow clip amount.

		void SetShadows (real64 shadows)
			{
			fShadows = shadows;
			}
			
		/// Get shadow clip amount.
		/// \retval Shadow clip amount.

		real64 Shadows () const
			{
			return fShadows;
			}
			
		/// Set custom tone curve for conversion.
		/// \param curve 1D function that defines tone mapping to use during conversion.
	
		void SetToneCurve (const dng_1d_function &curve)
			{
			fToneCurve = &curve;
			}
			
		/// Get custom tone curve for conversion.
		/// \retval 1D function that defines tone mapping to use during conversion.

		const dng_1d_function & ToneCurve () const
			{
			return *fToneCurve;
			}

		/// Set final color space in which resulting image data should be represented.
		/// (See dng_color_space.h for possible values.)
		/// \param space Color space to use.

		void SetFinalSpace (const dng_color_space &space)
			{
			fFinalSpace = &space;
			}
			
		/// Get final color space in which resulting image data should be represented.
		/// \retval Color space to use.

		const dng_color_space & FinalSpace (const dng_camera_profile *profile) const;
			
		/// Set pixel type of final image data.
		/// Can be ttByte (default), ttShort, or ttFloat.
		/// \param type Pixel type to use.

		void SetFinalPixelType (uint32 type)
			{
			fFinalPixelType = type;
			}
			
		/// Get pixel type of final image data.
		/// Can be ttByte (default), ttShort, or ttFloat.
		/// \retval Pixel type to use.

		uint32 FinalPixelType () const
			{
			return fFinalPixelType;
			}

		/// Set maximum dimension, in pixels, of resulting image.
		/// If final image would have either dimension larger than maximum, the larger
		/// of the two dimensions is set to this maximum size and the smaller dimension
		/// is adjusted to preserve aspect ratio.
		/// \param size Maximum size to allow.

		void SetMaximumSize (uint32 size)
			{
			fMaximumSize = size;
			}
			
		/// Get maximum dimension, in pixels, of resulting image.
		/// If the final image would have either dimension larger than this maximum, the larger
		/// of the two dimensions is set to this maximum size and the smaller dimension
		/// is adjusted to preserve the image's aspect ratio.
		/// \retval Maximum allowed size.

		uint32 MaximumSize () const
			{
			return fMaximumSize;
			}

		/// Set the id of the preferred camera profile for rendering the image.

		void SetCameraProfileID (const dng_camera_profile_id &id)
			{
			fProfileID = id;
			}

		/// Get the id of the preferred camera profile for rendering the image.

		const dng_camera_profile_id & CameraProfileID  () const
			{
			return fProfileID;
			}

		/// Actually render a digital negative to a displayable image.
		/// Input digital negative is passed to the constructor of this dng_render class.
		/// \retval The final resulting image.

		virtual dng_image * Render ();
									
	};

/*****************************************************************************/

#endif	// __dng_render__
	
/*****************************************************************************/
