//     ____   ______ __
//    / __ \ / ____// /
//   / /_/ // /    / /
//  / ____// /___ / /___   PixInsight Class Library
// /_/     \____//_____/   PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/LocalNormalizationData.h - Released 2022-03-12T18:59:29Z
// ----------------------------------------------------------------------------
// This file is part of the PixInsight Class Library (PCL).
// PCL is a multiplatform C++ framework for development of PixInsight modules.
//
// Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved.
//
// Redistribution and use in both source and binary forms, with or without
// modification, is permitted provided that the following conditions are met:
//
// 1. All redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. All redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
//    of their contributors, may be used to endorse or promote products derived
//    from this software without specific prior written permission. For written
//    permission, please contact info@pixinsight.com.
//
// 4. All products derived from this software, in any form whatsoever, must
//    reproduce the following acknowledgment in the end-user documentation
//    and/or other materials provided with the product:
//
//    "This product is based on software from the PixInsight project, developed
//    by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
//
//    Alternatively, if that is where third-party acknowledgments normally
//    appear, this acknowledgment must be reproduced in the product itself.
//
// THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
// INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
// DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------

#ifndef __PCL_LocalNormalizationData_h
#define __PCL_LocalNormalizationData_h

/// \file pcl/LocalNormalizationData.h

#include <pcl/Defs.h>

#include <pcl/BicubicInterpolation.h>
#include <pcl/File.h>
#include <pcl/Image.h>
#include <pcl/TimePoint.h>

namespace pcl
{

// ----------------------------------------------------------------------------

class PCL_CLASS XMLDocument;
class PCL_CLASS XMLElement;

/*!
 * \class LocalNormalizationData
 * \brief Normalization data parser and generator
 *
 * %LocalNormalizationData implements support for the %XML normalization data
 * format (XNML format, .xnml file suffix).
 *
 * An XNML file stores local normalization function data suitable for pixel
 * rejection and image integration tasks, including drizzle integration. The
 * %LocalNormalizationData class is a high-level interface for parsing and
 * generation of these special files.
 *
 * Local normalization functions are serialized as floating point real images,
 * where each channel stores scaling and zero offset coefficients, sampled at a
 * prescribed normalization scale, for a channel of a specific image.
 *
 * For a channel index c and position vector i on a given input image, the
 * local normalization function is:
 *
 * v'(c,i) = U(A(c,i))*(v(c,i) - C(c)) + U(B(c,i))
 *
 * where A(c) is the matrix of scaling coefficients, B(c) is the matrix of zero
 * offset coefficients, C(c) is the bias level (C = 0 by default), U() is a
 * scale-dependent interpolation functional, v is an input pixel value, and v'
 * is the normalized pixel value.
 *
 * This implementation can also apply an optional global normalization function
 * after the local normalization. If the corresponding parameters are defined,
 * the global normalization function is:
 *
 * v''(c,i) = S(c)*(v'(c,i) - T(c)) + R(c)
 *
 * where S is a vector of global scaling factors, T is a vector of target
 * locations, and R is a vector of reference locations. v' is the locally
 * normalized pixel value, as defined above, and v'' is the output value after
 * local and global normalization.
 *
 * Local normalization matrices are conveniently stored as multichannel,
 * two-dimensional images, which facilitates two-dimensional interpolation with
 * smooth pixel interpolation algorithms. Normalization matrices are normally
 * much smaller than the reference image dimensions. This happens because we
 * define local normalization functions at a specific dimensional scale, which
 * typically corresponds to a large dyadic scale of 64, 128, or 256 pixels. For
 * this reason, normalization matrices require a smooth interpolation to
 * compute normalization coefficients at reference image coordinates.
 *
 * \sa DrizzleData
 */
class PCL_CLASS LocalNormalizationData
{
public:

   /*!
    * Represents a per-channel set of local image normalization matrices.
    */
   typedef Image                             normalization_matrices;

   /*!
    * Represents a local normalization function coefficient.
    */
   typedef normalization_matrices::sample    normalization_coefficient;

   /*!
    * Represents a smooth interpolation used for calculation of local
    * normalization function values at image pixel coordinates.
    */
   typedef BicubicBSplineInterpolation<normalization_coefficient>
                                             matrix_interpolation;

   /*!
    * Represents an array of local normalization interpolators.
    */
   typedef Array<matrix_interpolation>       matrix_interpolations;

   /*!
    * Constructs an empty %LocalNormalizationData object.
    */
   LocalNormalizationData() = default;

   /*!
    * Copy constructor.
    */
   LocalNormalizationData( const LocalNormalizationData& ) = default;

   /*!
    * Move constructor.
    */
   LocalNormalizationData( LocalNormalizationData&& ) = default;

   /*!
    * Constructs a new %LocalNormalizationData instance by loading and parsing
    * a file in XNML format.
    *
    * \param filePath   Path to an existing file that will be parsed. The file
    *                   contents must be in %XML normalization data format
    *                   (usually, a file with the .xnml suffix).
    *
    * \param ignoreNormalizationData     If true, local normalization data will
    *                   be ignored and not parsed. This includes matrices of
    *                   normalization function coefficients. Setting this
    *                   parameter to true can be useful when the caller only
    *                   needs to retrieve information on file paths and
    *                   reference dimensions.
    *
    * This constructor validates the data retrieved from the specified file. It
    * throws the appropriate Error exceptions in the event of parsing errors or
    * invalid data.
    */
   LocalNormalizationData( const String& filePath, bool ignoreNormalizationData = false )
   {
      Parse( filePath, ignoreNormalizationData );
   }

   /*!
    * Constructs a new %LocalNormalizationData instance by parsing a
    * well-formed %XML document in XNML format.
    *
    * \param xml        Reference to the source %XML document. This constructor
    *                   expects an %XML document in valid %XML normalization
    *                   data format (.xnml).
    *
    * \param ignoreNormalizationData     If true, local normalization data will
    *                   be ignored and not parsed. This includes matrices of
    *                   normalization function coefficients. Setting this
    *                   parameter to true can be useful when the caller only
    *                   needs to retrieve information on file paths and
    *                   reference dimensions.
    *
    * This constructor validates the data retrieved from the specified %XML
    * document. It throws an Error exception in the event of an invalid
    * document or invalid data.
    */
   LocalNormalizationData( const XMLDocument& xml, bool ignoreNormalizationData = false )
   {
      Parse( xml, ignoreNormalizationData );
   }

   /*!
    * Constructs a new %LocalNormalizationData instance by parsing an %XML
    * element in XNML format.
    *
    * \param element    Reference to the source %XML element. This constructor
    *                   expects an %XML document tree in valid %XML
    *                   normalization data format (.xnml) rooted at the
    *                   specified element.
    *
    * \param ignoreNormalizationData     If true, local normalization data will
    *                   be ignored and not parsed. This includes matrices of
    *                   normalization function coefficients. Setting this
    *                   parameter to true can be useful when the caller only
    *                   needs to retrieve information on file paths and
    *                   reference dimensions.
    *
    * This constructor validates the data retrieved from the specified %XML
    * element. It throws an Error exception in the event of invalid data.
    */
   LocalNormalizationData( const XMLElement& element, bool ignoreNormalizationData = false )
   {
      Parse( element, ignoreNormalizationData );
   }

   /*!
    * Virtual destructor.
    */
   virtual ~LocalNormalizationData()
   {
   }

   /*!
    * Returns the full path to the reference image file used for calculation of
    * the normalization data represented by this instance, or an empty string
    * if that file path is not available.
    *
    * \sa SetReferenceFilePath()
    */
   const String& ReferenceFilePath() const
   {
      return m_referenceFilePath;
   }

   /*!
    * Sets the path to the reference image file used for calculation of the
    * normalization data stored in this instance.
    *
    * \sa ReferenceFilePath()
    */
   void SetReferenceFilePath( const String& filePath )
   {
      m_referenceFilePath = File::FullPath( filePath );
   }

   /*!
    * Returns the full path to the image file for which the normalization data
    * represented by this instance was calculated, or an empty string if such
    * file path is not available.
    *
    * The file identified by this function stores the input image of the image
    * normalization task that created this object. This file can be used as
    * input for a regular (non-drizzle) integration task, and the data
    * transported by this object can then be used for normalization of pixel
    * values in pixel rejection and/or integration output generation, including
    * drizzle integration.
    *
    * \sa SetTargetFilePath()
    */
   const String& TargetFilePath() const
   {
      return m_targetFilePath;
   }

   /*!
    * Sets the path to the image file for which the normalization data stored
    * in this instance was calculated.
    *
    * \sa TargetFilePath()
    */
   void SetTargetFilePath( const String& filePath )
   {
      m_targetFilePath = File::FullPath( filePath );
   }

   /*!
    * Returns the scale in pixels at which the local normalization functions
    * were sampled and calculated. For valid normalization data, the returned
    * value must be larger than zero, and should normally be larger than or
    * equal to 32 pixels.
    *
    * \sa SetNormalizationScale()
    */
   int NormalizationScale() const
   {
      return m_scale;
   }

   /*!
    * Sets the scale in pixels at which the local normalization functions have
    * been sampled and calculated.
    *
    * \sa NormalizationScale()
    */
   void SetNormalizationScale( int scale )
   {
      m_scale = scale;
   }

   /*!
    * Returns the width in pixels of the normalization reference and target
    * images, or -1 if this object has not been initialized with valid data.
    *
    * \sa ReferenceHeight(), SetReferenceDimensions()
    */
   int ReferenceWidth() const
   {
      return m_referenceWidth;
   }

   /*!
    * Returns the height in pixels of the normalization reference and target
    * images, or -1 if this object has not been initialized with valid data.
    *
    * \sa ReferenceWidth(), SetReferenceDimensions()
    */
   int ReferenceHeight() const
   {
      return m_referenceHeight;
   }

   /*!
    * Sets new normalization image dimensions in pixels, \a width and
    * \a height, respectively.
    *
    * \sa ReferenceWidth(), ReferenceHeight()
    */
   void SetReferenceDimensions( int width, int height )
   {
      m_referenceWidth = width;
      m_referenceHeight = height;
   }

   /*!
    * Returns the number of channels or pixel sample planes in the image
    * represented by this instance, or zero if this object has not been
    * initialized with valid data.
    */
   int NumberOfChannels() const
   {
      return m_A.NumberOfChannels();
   }

   /*!
    * Returns a reference to the set of matrices of zero offset coefficients in
    * the local normalization function.
    *
    * See the class description for detailed information on local normalization
    * functions.
    *
    * \sa Scale(), SetLocalNormalizationParameters(), NormalizationScale()
    */
   const normalization_matrices& ZeroOffset() const
   {
      return m_B;
   }

   /*!
    * Returns a reference to the set of matrices of scaling coefficients in the
    * local normalization function.
    *
    * See the class description for detailed information on local normalization
    * functions.
    *
    * \sa ZeroOffset(), SetLocalNormalizationParameters(), NormalizationScale()
    */
   const normalization_matrices& Scale() const
   {
      return m_A;
   }

   /*!
    * Returns a reference to the vector of per-channel bias levels. Each bias
    * is a constant scalar subtracted from input pixel sample values before
    * applying the local normalization function. This allows to remove any
    * systematic offset or additive pedestal that could be present in the data
    * to be normalized. The possibility to remove a constant value also adds
    * flexibility to the local normalization function.
    *
    * If not specified, the target bias is always zero by default.
    */
   const Vector& Bias() const
   {
      return m_C;
   }

   /*!
    * Sets new local normalization function parameters.
    *
    * \param A          Reference to an image storing the matrices of scaling
    *                   normalization coefficients.
    *
    * \param B          Reference to an image storing the matrices of zero
    *                   offset normalization coefficients.
    *
    * \param C          Reference to an optional vector of per-channel biases.
    *                   If not specified, the bias will be set to zero for each
    *                   channel by default.
    *
    * See the class description for detailed information on local normalization
    * functions.
    *
    * This function throws an Error exception if some of the specified local
    * normalization parameters are invalid or incongruent.
    *
    * \sa ZeroOffset(), Scale(), Bias(), SetGlobalNormalizationParameters()
    */
   void SetLocalNormalizationParameters( const normalization_matrices& A, const normalization_matrices& B, const Vector& C = Vector() )
   {
      if ( A.Bounds() != B.Bounds() )
         throw Error( "LocalNormalizationData::SetLocalNormalizationParameters(): Incompatible matrix dimensions." );
      if ( A.NumberOfChannels() != B.NumberOfChannels() )
         throw Error( "LocalNormalizationData::SetLocalNormalizationParameters(): Incompatible number of normalization matrices." );
      m_A = A;
      m_B = B;
      if ( !C.IsEmpty() )
      {
         if ( C.Length() != A.NumberOfChannels() )
            throw Error( "LocalNormalizationData::SetLocalNormalizationParameters(): Incompatible bias vector length." );
         m_C = C;
      }
   }

   /*!
    * Returns a reference to the vector of per-channel global reference
    * locations (or zero-offsets).
    *
    * \sa GlobalTargetLocation(), GlobalScalingFactors(),
    * SetGlobalNormalizationParameters()
    */
   const Vector& GlobalReferenceLocation() const
   {
      return m_Rc;
   }

   /*!
    * Returns a reference to the vector of per-channel global target locations
    * (or zero-offsets).
    *
    * \sa GlobalReferenceLocation(), GlobalScalingFactors(),
    * SetGlobalNormalizationParameters()
    */
   const Vector& GlobalTargetLocation() const
   {
      return m_Rc;
   }

   /*!
    * Returns a reference to the vector of per-channel global scaling factors.
    *
    * \sa GlobalReferenceLocation(), GlobalTargetLocation(),
    * SetGlobalNormalizationParameters()
    */
   const Vector& GlobalScalingFactors() const
   {
      return m_S;
   }

   /*!
    * Sets new global normalization vectors.
    *
    * \param Rc         Reference to a vector of per-channel reference global
    *                   locations.
    *
    * \param Tc         Reference to a vector of per-channel target global
    *                   locations.
    *
    * \param S          Reference to a vector of per-channel global scaling
    *                   factors.
    *
    * See the class description for detailed information on local normalization
    * functions.
    *
    * This function throws an Error exception if some of the specified global
    * normalization parameters are invalid or incongruent.
    *
    * \sa GlobalReferenceLocation(), GlobalTargetLocation(),
    * GlobalScalingFactors(), SetLocalNormalizationParameters()
    */
   void SetGlobalNormalizationParameters( const Vector& Rc, const Vector& Tc, const Vector& S )
   {
      if ( m_B.IsEmpty() )
         throw Error( "LocalNormalizationData::SetGlobalNormalizationParameters(): No zero offset coefficient matrix has been defined." );
      if ( Rc.Length() != m_B.NumberOfChannels() || Tc.Length() != m_B.NumberOfChannels() || S.Length() != m_B.NumberOfChannels() )
         throw Error( "LocalNormalizationData::SetGlobalNormalizationParameters(): Incompatible vector lengths." );
      m_Rc = Rc;
      m_Tc = Tc;
      m_S = S;
   }

   /*!
    * Returns a reference to the vector of per-channel relative scale factors.
    */
   const Vector& RelativeScaleFactors() const
   {
      return m_relScale;
   }

   /*!
    * Sets a new relative scale factors vector.
    *
    * \param Rc   Reference to a vector of per-channel relative scale factors.
    *
    * See the class description for detailed information on local normalization
    * functions.
    *
    * This function throws an Error exception if the specified vector is
    * invalid or incongruent with normalization data.
    */
   void SetRelativeScaleFactors( const Vector& s )
   {
      if ( m_B.IsEmpty() )
         throw Error( "LocalNormalizationData::SetRelativeScaleFactors(): No zero offset coefficient matrix has been defined." );
      if ( s.Length() != m_B.NumberOfChannels() )
         throw Error( "LocalNormalizationData::SetRelativeScaleFactors(): Incompatible vector lengths." );
      m_relScale = s;
   }

   /*!
    * Initializes the internal local normalization function interpolators.
    * After this initialization, operator()() can be called repeatedly to apply
    * the local normalization function to pixel sample values in reference
    * image coordinates.
    *
    * Calling this member function is not necessary when valid local
    * normalization data have been loaded from an XNML file or %XML document,
    * since in this case the internal interpolators are always initialized
    * automatically. This function must be called, however, for newly defined
    * normalization data set by calling SetReferenceDimensions() and
    * SetLocalNormalizationParameters().
    *
    * If this object has not been initialized with valid local normalization
    * data, this member function throws an Error exception.
    *
    * \sa operator()()
    */
   void InitInterpolations();

   /*!
    * Returns true iff valid local normalization function data have been loaded
    * and the internal interpolators have been initialized.
    */
   bool HasInterpolations() const
   {
      return !m_UA.IsEmpty() && !m_UB.IsEmpty();
   }

   /*!
    * Returns a locally normalized pixel sample value.
    *
    * \param z          Input pixel sample value (unnormalized).
    * \param x          Horizontal image pixel coordinate.
    * \param y          Vertical image pixel coordinate.
    * \param c          Channel index.
    *
    * This operator interpolates local normalization functions and applies the
    * corresponding linear transformation to the input value \a z, which gives
    * the return value. Note that the normalized value might be out of the
    * input pixel sample range. In such case the normalized value should be
    * truncated or rescaled as appropriate.
    *
    * For performance reasons, this operator does not check that the required
    * normalization and interpolation data have been initialized; if they are
    * not, calling this operator will most likely lead to a crash.
    * Interpolation data are automatically initialized when a valid XNML file
    * or %XML element is loaded and parsed. For newly constructed objects, make
    * sure you define the required reference dimensions and normalization
    * matrices. Then call InitInterpolations() before starting to call this
    * operator.
    */
   double operator()( double z, int x, int y, int c = 0 ) const
   {
      double sx = m_sx*x;
      double sy = m_sy*y;
      if ( likely( m_S.IsEmpty() ) )
         return m_UA[c]( sx, sy )*(z - m_C[c]) + m_UB[c]( sx, sy );
      return (m_UA[c]( sx, sy )*(z - m_C[c]) + m_UB[c]( sx, sy ) - m_Tc[c])*m_S[c] + m_Rc[c];
   }

   /*!
    * Returns the UTC time this normalization data was created, or an invalid
    * TimePoint instance if creation time information is not available.
    */
   TimePoint CreationTime() const
   {
      return m_creationTime;
   }

   /*!
    * Clears all of the image normalization data transported by this instance,
    * yielding an empty %LocalNormalizationData object.
    */
   void Clear();

   /*!
    * Loads and parses a normalization data file in XNML format.
    *
    * \param filePath   Path to an existing file that will be parsed. The file
    *                   contents must be in %XML normalization data format
    *                   (usually, a file with the .xnml suffix).
    *
    * \param ignoreNormalizationData     If true, local normalization data will
    *                   be ignored and not parsed. This includes matrices of
    *                   normalization function coefficients. Setting this
    *                   parameter to true can be useful when the caller only
    *                   needs to retrieve information on file paths and
    *                   reference dimensions.
    *
    * All of the previous data transported by this instance will be replaced
    * with new data acquired from the specified file.
    *
    * This function validates the data retrieved from the specified file. It
    * throws an Error exception in the event of parsing errors or invalid data.
    */
   void Parse( const String& filePath, bool ignoreNormalizationData = false );

   /*!
    * Parses a well-formed %XML document in XNML format.
    *
    * \param xml        Reference to the source %XML document. This member
    *                   function expects an %XML document in valid %XML
    *                   normalization data format (.xnml).
    *
    * \param ignoreNormalizationData     If true, local normalization data will
    *                   be ignored and not parsed. This includes matrices of
    *                   normalization function coefficients. Setting this
    *                   parameter to true can be useful when the caller only
    *                   needs to retrieve information on file paths and
    *                   reference dimensions.
    *
    * All of the previous data transported by this instance will be replaced
    * with new data acquired from the specified %XML contents.
    *
    * This function validates the data retrieved from the specified %XML
    * document. It throws an Error exception in the event of an invalid
    * document or invalid data.
    */
   void Parse( const XMLDocument& xml, bool ignoreNormalizationData = false );

   /*!
    * Parses an %XML element in XNML format.
    *
    * \param element    Reference to the source %XML element. This member
    *                   function expects an %XML document tree in valid %XML
    *                   normalization data format (.xnml) rooted at the
    *                   specified element.
    *
    * \param ignoreNormalizationData     If true, local normalization data will
    *                   be ignored and not parsed. This includes matrices of
    *                   normalization function coefficients. Setting this
    *                   parameter to true can be useful when the caller only
    *                   needs to retrieve information on file paths and
    *                   reference dimensions.
    *
    * All of the previous data transported by this instance will be replaced
    * with new data acquired from the specified %XML contents.
    *
    * This function validates the data retrieved from the specified %XML
    * element. It throws an Error exception in the event of invalid data.
    */
   void Parse( const XMLElement& element, bool ignoreNormalizationData = false );

   /*!
    * Returns true if data compression is enabled for serializations performed
    * with this object.
    *
    * Data compression is enabled by default for newly constructed
    * %LocalNormalizationData objects. Currently the LZ4 compression codec is
    * applied for serialization of local normalization matrices.
    *
    * \sa EnableCompression(), DisableCompression()
    */
   bool IsCompressionEnabled() const
   {
      return m_compressionEnabled;
   }

   /*!
    * Enables compression of serialized local normalization data.
    *
    * \sa IsCompressionEnabled(), DisableCompression()
    */
   void EnableCompression( bool enable = true )
   {
      m_compressionEnabled = enable;
   }

   /*!
    * Returns a version number corresponding to the normalization data
    * transported by this object.
    *
    * Version numbers can be used to control the use and propagation of
    * normalization data generated by different versions of a normalization
    * tool or process, such as the standard LocalNormalization process in
    * PixInsight. The version number is zero by default, meaning that the
    * version is unspecified. An appropriate version number &gt; 0 can be set
    * by calling SetVersion(), which is recommended before serializing
    * normalization data to a new XNML file. When an XNML file is loaded and it
    * contains a valid version number tag, it is loaded and will be returned by
    * this function. Otherwise the returned value will be zero.
    */
   int Version() const
   {
      return m_version;
   }

   /*!
    * Sets the normalization data version. See Version() for information on
    * normalization data versions.
    */
   void SetVersion( int version )
   {
      m_version = version;
   }

   /*!
    * Disables compression of serialized local normalization data.
    *
    * \sa IsCompressionEnabled(), EnableCompression()
    */
   void DisableCompression( bool disable = true )
   {
      EnableCompression( !disable );
   }

   /*!
    * Serializes the normalization data transported by this object as a new
    * %XML document in XNML format.
    *
    * The returned XMLDocument object has been allocated dynamically. The
    * caller is responsible for destroying and deallocating it as appropriate.
    */
   XMLDocument* Serialize() const;

   /*!
    * Serializes the normalization data transported by this object as a new
    * %XML document file in XNML format (.xnml). The file will be newly created
    * at the specified file \a path.
    *
    * \warning If a file already exists at the specified \a path, its previous
    * contents will be lost after calling this function.
    */
   void SerializeToFile( const String& path ) const;

private:

   String                 m_referenceFilePath;    // path to the normalization reference image
   String                 m_targetFilePath;       // path to the normalization target image
   int                    m_scale = -1;           // normalization scale in px
   int                    m_referenceWidth = -1;  // reference image width in px
   int                    m_referenceHeight = -1; // reference image height in px
   normalization_matrices m_A;                    // scaling coefficients
   normalization_matrices m_B;                    // zero offset coefficients
   Vector                 m_C;                    // input bias
   matrix_interpolations  m_UA;                   // interpolators for m_A
   matrix_interpolations  m_UB;                   // interpolators for m_B
   Vector                 m_Rc;                   // global normalization, reference center
   Vector                 m_Tc;                   // global normalization, target center
   Vector                 m_S;                    // global normalization, scale factor
   Vector                 m_relScale;             // relative scale factor
   double                 m_sx;                   // coordinate scaling factor, X axis
   double                 m_sy;                   // coordinate scaling factor, Y axis
   TimePoint              m_creationTime;
   bool                   m_compressionEnabled = true;
   int                    m_version = 0;

   void ParseNormalizationMatrices( normalization_matrices&, const XMLElement& ) const;
   void SerializeNormalizationMatrices( XMLElement*, const normalization_matrices& ) const;
};

// ----------------------------------------------------------------------------

} // pcl

#endif   // __PCL_LocalNormalizationData_h

// ----------------------------------------------------------------------------
// EOF pcl/LocalNormalizationData.h - Released 2022-03-12T18:59:29Z
