/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once

#ifndef RX_STATIC
    #ifdef RXCOREEX_EXPORTS
		#define RXCOREEX_API __declspec(dllexport)
    #else
		#define RXCOREEX_API __declspec(dllimport)
    #endif
#else
	#define RXCOREEX_API
#endif

#include "Rx.Interop.Runtime28/RxIfcImage.h"
#include "RxImageFormat.h"
#include "Rx.InlinePixel.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Rx
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rx
{
	/**
	        \addtogroup RxCore_Image
	**/
	/// @{

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 	Image class. Implements the interface Interop::Runtime28::IImage.
	///
	/// 	This class implements only the basic functionality for an image like create, delete and convert. All image processing
	/// 	has to be implemented separately.
	///
	/// 	The format of an image is described by the class CRxImageFormat. It consist of an image width, height, a pixel type and
	/// 	a data type. The pixel type defines the number and order of color channels, and the data type specifies the data type
	/// 	of each color channel. For example, the pixel type can be RGBA or BGRA and the data type may be unsigned byte (8bit) or
	/// 	unsigned short (16bit). The various pixel types available are defined in Rx::Interop::Runtime28::EPixelType::ID and the
	/// 	data types in Rx::Interop::Runtime28::EDataType::ID. Note that the values of the data type and pixel type defines are
	/// 	identical to the corresponding OpenGL IDs.
	///
	/// 	All possible pixel and data types are represented by the TPixeltemplate structure. Specializations of this template
	/// 	structure cover all possible combinations of the defined pixel types and data types. The specialization names have the
	/// 	form TPixel_[PixelType]_[Data Type]. For example, the pixel structure for an RGBA unsigned char image is TPixel_RGBA_uc.
	///
	/// 	The main advantage of using the TPixel_* typedefs to access the pixels of an image is, that you can write template
	/// 	functions that work on many different pixel types. The TPixel structure defines functions to access the various color
	/// 	channels that map to the correct element within a pixel.
	///
	/// 	The pointer to the image data can be obtained with the function GetDataPtr().
	/// </summary>
	///
	/// <seealso cref="Interop::Runtime28::IImage"/>
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	class RXCOREEX_API CRxImage : public Interop::Runtime28::IImage
	{
	public:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Default constructor. Creates an invalid image without using any memory.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImage();

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Copy constructor. Creates a copy of the given image
		/// </summary>
		///
		/// <param name="xImage"> The image to copy. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImage(const CRxImage& xImage);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Move constructor.
		/// </summary>
		///
		/// <param name="xImage"> [in] The image to move. This is invalid after the call. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImage(CRxImage&& xImage);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Constructor. Creates a valid image within the given format and allocates memory accordingly.
		/// </summary>
		///
		/// <param name="xFormat"> The image format. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImage(const CRxImageFormat& xFormat);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Destructor. All used memory is freed.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual ~CRxImage();

	public:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Assignment operator. Copies the contents of the given image.
		/// </summary>
		///
		/// <param name="xImage"> The image. </param>
		///
		/// <returns> A shallow copy of this object. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImage& operator=(const CRxImage& xImage);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Move assignment operator.
		/// </summary>
		///
		/// <param name="xImage"> [in] The image to move. This is invalid after the call. </param>
		///
		/// <returns> A shallow copy of this object. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImage& operator=(CRxImage&& xImage);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Copies the content of the given image data into this image.
		///
		/// 	Expects that the image formats of the given data pointer and this image are identical.
		/// </summary>
		///
		/// <param name="pvImgData"> The image data to copy. </param>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		bool Set(const void* pvImgData);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets the image data to contain only zeros.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void SetZero();

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Creates an image of the given format. Only (re)allocates memory if required.
		/// </summary>
		///
		/// <param name="xFormat"> The image format. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Create(const CRxImageFormat& xFormat);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Creates an image of the given format. Only (re)allocates memory if required. Copies the image data into this image.
		/// </summary>
		///
		/// <param name="xFormat">   The image format. </param>
		/// <param name="pvImgData"> Pointer to the image data. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Create(const CRxImageFormat& xFormat, const void* pvImgData);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Creates a copy of the given image. Only (re)allocates memory if required.
		/// </summary>
		///
		/// <param name="xImage"> The image to copy. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Create(const CRxImage& xImage);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Creates an image of the given format. This copies only the image data pointer. Does not allocate memory.
		///
		/// 	An images created with this method does never free the memory behind the pointer. The pointer responsibility stays with
		/// 	the caller.
		/// </summary>
		///
		/// <param name="xFormat">    The image format. </param>
		/// <param name="pvImgData">  The image data pointer. </param>
		/// <param name="dTimestamp"> (Optional) The timestamp of the image capture. </param>
		/// <param name="uID">		  (Optional) The image ID. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void CreateMoniker(const CRxImageFormat& xFormat, void* pvImgData, double dTimestamp = 0.0, unsigned uID = 0);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Creates this image by moving the data of the given image into this image.
		/// </summary>
		///
		/// <param name="xImage"> [in,out] The image to move. Is invalid after this call. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Create(CRxImage&& xImage);

	public:

		/************************************************************************/
		/* Rx::Interop::Runtime28::IImage                                       */
		/************************************************************************/

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Create an image of given type and size and reserve the appropriate amount of memory. No re-allocation is applied if
		/// 	this is of requested format.
		/// </summary>
		///
		/// <param name="iWidth">	  The width of image. </param>
		/// <param name="iHeight">    The height of the image. </param>
		/// <param name="ePixelType"> The pixel type. </param>
		/// <param name="eDataType">  The data type. </param>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Create(int iWidth, int iHeight, Interop::Runtime28::EPixelType::ID ePixelType, Interop::Runtime28::EDataType::ID eDataType);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Create an image of given type and size and copy the data from the given pointer. No re-allocation is applied if this is
		/// 	of requested format.
		/// </summary>
		///
		/// <param name="iWidth">	  Width of image. </param>
		/// <param name="iHeight">    Height. </param>
		/// <param name="ePixelType"> Type of the pixel. </param>
		/// <param name="eDataType">  Type of the data. </param>
		/// <param name="pData">	  The data. </param>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Create(int iWidth, int iHeight, Interop::Runtime28::EPixelType::ID ePixelType, Interop::Runtime28::EDataType::ID eDataType, const void* pData);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Creates copy of the given image. No re-allocation is applied if image is of requested format.
		/// </summary>
		///
		/// <param name="pxImage"> The image. </param>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Create(const Interop::Runtime28::IImage* pxImage);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Destroys this image if one has been created. Resets all internal variables.
		/// </summary>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Destroy();

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Query if this image is valid.
		/// </summary>
		///
		/// <returns> True if valid, false if not. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool IsValid() const
		{
			return m_pvData ? true : false;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Get number of bytes per pixel.
		/// </summary>
		///
		/// <returns> The bytes per pixel. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual int GetBytesPerPixel() const
		{
			return m_xFormat.GetBytesPerPixel();
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the number of pixels.
		/// </summary>
		///
		/// <returns> The pixel count. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual unsigned GetPixelCount() const
		{
			return m_xFormat.GetPixelCount();
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the number of bytes of the whole image.
		/// </summary>
		///
		/// <returns> The byte count. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual unsigned GetByteCount() const
		{
			return m_xFormat.GetByteCount();
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the size of the image.
		/// </summary>
		///
		/// <param name="iWidth">  [out] The width. </param>
		/// <param name="iHeight"> [out] The height. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual void GetSize(int& iWidth, int& iHeight) const
		{
			iWidth  = m_xFormat.m_iWidth;
			iHeight = m_xFormat.m_iHeight;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the type of the image.
		/// </summary>
		///
		/// <param name="ePixelType"> [out] The pixel type. </param>
		/// <param name="eDataType">  [out] The data type. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual void GetType(Interop::Runtime28::EPixelType::ID& ePixelType, Interop::Runtime28::EDataType::ID& eDataType) const
		{
			ePixelType = m_xFormat.m_ePixelType;
			eDataType  = m_xFormat.m_eDataType;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Return the pointer to the data array.
		/// </summary>
		///
		/// <returns> Null if it fails, else the data pointer. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual void* GetDataPtr()
		{
			return m_pvData;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Return the constant pointer to the data array.
		/// </summary>
		///
		/// <returns> Null if it fails, else the data pointer. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual const void* GetDataPtr() const
		{
			return m_pvData;
		}

	public:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the image format.
		/// </summary>
		///
		/// <returns> The format. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		const CRxImageFormat& GetFormat() const
		{
			return m_xFormat;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the ID of this image.
		/// </summary>
		///
		/// <returns> The ID of this image. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		unsigned GetID() const
		{
			return m_uID;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets the ID of this image.
		/// </summary>
		///
		/// <param name="uID"> The ID. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void SetID(unsigned uID)
		{
			m_uID = uID;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the timestamp of the image capture. Is 0.0 if this image has no timestamp.
		/// </summary>
		///
		/// <returns> The timestamp. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		double GetTimestamp() const
		{
			return m_dTimestamp;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets the timestamp of the image capture.
		/// </summary>
		///
		/// <param name="dTimestamp"> The timestamp. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void SetTimestamp(double dTimestamp)
		{
			m_dTimestamp = dTimestamp;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets the timestamp and the ID of the image.
		/// </summary>
		///
		/// <param name="dTimestamp"> The timestamp. </param>
		/// <param name="uID">		  The ID. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void SetTimestampID(double dTimestamp, unsigned uID)
		{
			m_dTimestamp = dTimestamp;
			m_uID        = uID;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Query if this image is a moniker.
		///
		/// 	A moniker holds an image data pointer but is not responsible for the memory. Thus, destroying an image moniker does not
		/// 	free the memory.
		/// </summary>
		///
		/// <returns> True if this image is a moniker, false if not. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		bool IsMoniker() const
		{
			return m_bIsMoniker;
		}

	public:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Convert this image to a different type and store result in xImage.
		/// </summary>
		///
		/// <param name="xImage">	  [in,out] The image instance into which to write the result. The size of this image is adapted to
		/// 						  this size. </param>
		/// <param name="ePixelType"> The target pixel type. </param>
		/// <param name="eDataType">  The target data type. </param>
		///
		/// <returns> False if an error occurred, otherwise true. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		bool ConvertType(CRxImage& xImage, Interop::Runtime28::EPixelType::ID ePixelType, Interop::Runtime28::EDataType::ID eDataType) const;

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Convert the pSrcImage to a different type and store result in pDstImage.
		/// </summary>
		///
		/// <param name="pDstImg">    [in,out] Pointer to target image interface. </param>
		/// <param name="pSrcImg">    Pointer to source image interface. </param>
		/// <param name="ePixelType"> The target pixel type. </param>
		/// <param name="eDataType">  The targer data type. </param>
		/// <param name="bCreate">    If true, the memory for the target image is created. </param>
		///
		/// <returns> False if an error occurred, otherwise true. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		static bool ConvertType(Interop::Runtime28::IImage* pDstImg,
				const Interop::Runtime28::IImage* pSrcImg,
				Interop::Runtime28::EPixelType::ID ePixelType,
				Interop::Runtime28::EDataType::ID eDataType,
				bool bCreate);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Convert the pSrcMem memory to a different type and store result in memory pTrgMem.
		/// </summary>
		///
		/// <param name="pTrgMem">    [in] Target memory (must have correct target size). </param>
		/// <param name="pSrcMem">    Source memory. </param>
		/// <param name="xTrgFormat"> The target image format. </param>
		/// <param name="xSrcFormat"> The source image format. </param>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		static bool ConvertMemory(void* pTrgMem, const void* pSrcMem, const CRxImageFormat& xTrgFormat, const CRxImageFormat& xSrcFormat);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Converts this image from a custom data type into the corresponding primitive data type.
		///
		/// 	The following conversion are implemented:
		/// 	- EDataType::Custom_10in16_LSB into EDataType::UShort
		/// 	- EDataType::Custom_12in16_LSB into EDataType::UShort.
		/// </summary>
		///
		/// <param name="xTrgImg"> [out] The target image. This is created within the correct format. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void ConvertCustomType(CRxImage& xTrgImg) const;

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Test whether image is of a particular pixel and data type.
		/// </summary>
		///
		/// <param name="ePixelType"> The pixel type. </param>
		/// <param name="eDataType">  The data type. </param>
		///
		/// <returns> True if of type, false if not. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		bool IsOfType(Interop::Runtime28::EPixelType::ID ePixelType, Interop::Runtime28::EDataType::ID eDataType) const
		{
			return ePixelType == m_xFormat.m_ePixelType && eDataType == m_xFormat.m_eDataType;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Find minimal and maximal value of image and normalize image to range [0,1].
		///
		/// 	Is currently only implemented for pixel type TPixel_L_f.
		/// </summary>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		bool Normalize();

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Swaps the data between this and the given image.
		/// </summary>
		///
		/// <param name="xImage"> [in,out] The image to swap with. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Swap(CRxImage& xImage);

	public:

		void GetPixel(TPixel_RGBA_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGBA_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGBA_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGBA_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGBA_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGBA_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGBA_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGBA_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_RGB_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGB_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGB_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGB_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGB_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGB_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGB_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_RGB_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_BGRA_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGRA_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGRA_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGRA_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGRA_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGRA_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGRA_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGRA_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_BGR_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGR_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGR_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGR_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGR_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGR_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGR_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_BGR_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_L_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_L_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_L_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_L_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_L_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_L_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_L_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_L_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_LA_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_LA_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_LA_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_LA_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_LA_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_LA_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_LA_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_LA_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_Bay_RG_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_RG_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_RG_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_RG_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_RG_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_RG_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_RG_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_RG_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_Bay_BG_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_BG_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_BG_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_BG_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_BG_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_BG_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_BG_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_BG_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_Bay_GR_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GR_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GR_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GR_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GR_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GR_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GR_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GR_d& xPix, int iX, int iY) const;

		void GetPixel(TPixel_Bay_GB_c& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GB_uc& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GB_s& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GB_us& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GB_i& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GB_ui& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GB_f& xPix, int iX, int iY) const;
		void GetPixel(TPixel_Bay_GB_d& xPix, int iX, int iY) const;

		void SetPixel(const TPixel_RGBA_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGBA_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGBA_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGBA_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGBA_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGBA_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGBA_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGBA_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_RGB_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGB_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGB_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGB_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGB_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGB_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGB_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_RGB_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_BGRA_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGRA_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGRA_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGRA_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGRA_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGRA_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGRA_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGRA_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_BGR_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGR_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGR_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGR_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGR_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGR_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGR_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_BGR_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_L_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_L_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_L_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_L_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_L_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_L_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_L_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_L_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_LA_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_LA_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_LA_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_LA_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_LA_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_LA_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_LA_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_LA_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_Bay_RG_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_RG_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_RG_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_RG_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_RG_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_RG_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_RG_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_RG_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_Bay_BG_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_BG_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_BG_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_BG_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_BG_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_BG_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_BG_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_BG_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_Bay_GR_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GR_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GR_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GR_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GR_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GR_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GR_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GR_d& xPix, int iX, int iY);

		void SetPixel(const TPixel_Bay_GB_c& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GB_uc& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GB_s& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GB_us& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GB_i& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GB_ui& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GB_f& xPix, int iX, int iY);
		void SetPixel(const TPixel_Bay_GB_d& xPix, int iX, int iY);

	protected:

		template<class TTrgPix, class TSrcPix>
		static bool _Convert(unsigned uPixelCount, TTrgPix* pTrgPix, const TSrcPix* pSrcPix);

		template<class TPix>
		static bool _ConvertSrcSwitch(const void* pSrcMem, const CRxImageFormat& xSrcFormat, TPix* pTrgPix);

		static bool _ConvertTrgSwitch(void* pDstMem, const void* pSrcMem, const CRxImageFormat& xDstFormat, const CRxImageFormat& xSrcFormat);

		template<class TPix>
		TPix& _GetPixel(int iX, int iY);

		template<class TPix>
		const TPix& _GetPixel(int iX, int iY) const;

	protected:

		/// <summary> The image format. </summary>
		CRxImageFormat m_xFormat;
		/// <summary> The image data. </summary>
		void* m_pvData;
		/// <summary> The image ID. </summary>
		unsigned m_uID;
		/// <summary> The timestamp of the image capture. Is 0.0 if this image has no timestamp. </summary>
		double m_dTimestamp;
		/// <summary> True if this image is only a moniker for an image data pointer. </summary>
		bool m_bIsMoniker;
	};

	/// @}
}

#pragma make_public(Rx::CRxImage)
